From 034f32617efc2d4cda029d3a7e66c57c641f626c Mon Sep 17 00:00:00 2001 From: Mikolaj Tomczynski Date: Sun, 28 Jul 2024 23:51:16 +0100 Subject: [PATCH] fixed GCS import for v4, moved actor import to separate file --- ReleaseProcess.md | 36 +- changelog.md | 14 +- lang/en.json | 2332 +++++++------- lang/pt_br.json | 2260 +++++++------- lib/hitpoints.js | 388 +-- lib/markdown-it.js | 12 +- lib/moustachewax.js | 20 +- lib/parselink.js | 2 +- lib/ranges.js | 442 ++- lib/xregexp-all.js | 51 +- module/actor/actor-importer.js | 2314 ++++++++++++++ module/actor/actor-sheet.js | 4 +- module/actor/actor.js | 2718 +---------------- module/actor/effect-modifier-control.js | 2 +- module/actor/effect-modifier-popout.js | 8 +- module/actor/resource-tracker-editor.js | 2 +- module/chat/anim.js | 25 +- module/chat/chat-processors.js | 3 +- module/effects/effects.js | 2 +- module/journal.js | 16 +- module/modifier-bucket/bucket-app.js | 3 +- .../modifier-bucket/resolve-diceroll-app.js | 2 +- module/pdf-refs.js | 3 +- module/pdf/edit.js | 14 +- module/utilities/gurpslink.js | 2 +- styles/apps.css | 171 +- styles/simple.css | 4 +- system.json | 6 +- templates/die-roll-chat-message.hbs | 25 +- templates/modifier-bucket/bucket-app.html | 28 +- templates/resource-editor-popup.hbs | 119 +- 31 files changed, 5474 insertions(+), 5554 deletions(-) create mode 100644 module/actor/actor-importer.js diff --git a/ReleaseProcess.md b/ReleaseProcess.md index 22efc4a02..d6d5b5acf 100644 --- a/ReleaseProcess.md +++ b/ReleaseProcess.md @@ -7,11 +7,11 @@ Make certain "main" branch is up to date with the latest features, and commit. Check out the "release" branch git checkout release - + Merge in the "main" branch git merge main - + Edit the following files: README.md - Change the release version @@ -20,24 +20,24 @@ changelog.md - Add the date of the release system.json - - Change the version - +Change the version + "version": "0.17.2" - - NOTE: Do NOT prefix a number with zero (0). "0.17.02" will cause problems later. - - Update the compatibility, if necessary: - + +NOTE: Do NOT prefix a number with zero (0). "0.17.02" will cause problems later. + +Update the compatibility, if necessary: + "compatibility": { "minimum": "12", "verified": "12.324" }, - - Update the download (Use the exact same version string as the ZIP file name prefix): - + +Update the download (Use the exact same version string as the ZIP file name prefix): + "download": "https://github.com/crnormand/gurps/archive/0.17.2.zip", - -Commit as the version "0.17.2" and push. Although the commit tag isn't as important. + +Commit as the version "0.17.2" and push. Although the commit tag isn't as important. If you messed up something, you can fix and recommit as a different tag. I usually go with something like "0.17.2b". @@ -48,13 +48,14 @@ Checkout "main" and update git push # On GitHub + Click on "**Releases**" Then "**Draft a new release**" Click on "**Choose a tag**" and create a new tag, using the exact same version string "0.17.2". -As we have found out... you must NOT prefix number with zero. Example: "0.17.02". +As we have found out... you must NOT prefix number with zero. Example: "0.17.02". Click on "**Target: main**" and select the "release" branch. @@ -64,7 +65,6 @@ Paste the changelog enrties into the "Describe this release" text area. Click "**Public release**". -Let me know that you have created a new release. I need to update the Foundry website. - -NOTE: Existing customers will be able to upgrade to the new release immediately. New customers will get the version identified on the Foundry website. +Let me know that you have created a new release. I need to update the Foundry website. +NOTE: Existing customers will be able to upgrade to the new release immediately. New customers will get the version identified on the Foundry website. diff --git a/changelog.md b/changelog.md index 34821474c..d8d541370 100644 --- a/changelog.md +++ b/changelog.md @@ -6,18 +6,18 @@ Release 0.17.6 - Fixed Physical Dice roll - Fixed Resource Tracker display (esp for Control Points) - Fixed setting 'dead' status from combat tracker -- Fixed Target Range (in Effects Modifier), when scene grid is NOT yards +- Fixed Target Range (in Effects Modifier), when scene grid is NOT yards Release 0.17.5 - Add CSS to enable horizontal scrollbars if the width of the window is less than the width of the actor sheet. -Release 0.17.4 6/29/2024 +Release 0.17.4 6/29/2024 - Dice So Nice now works for most targetted rolls and damage. This appears to also fix the public/private/blind chat messages. - Fix Shock and Major Wound errors when clicked on in the chat. - -Release 0.17.3 6/19/2024 + +Release 0.17.3 6/19/2024 - Update 'duplicate' method (deprecated) to 'foundry.utils.duplicate'. - Fix problem where Tracker value was being treated as a string. @@ -25,15 +25,15 @@ Release 0.17.3 6/19/2024 - Fix setting Maneuvers on actors in combat. - Fix right side truncation of default GCS sheet with PopOut! (It still opens the width of your monitor, though.) -Release 0.17.2 6/03/2024 +Release 0.17.2 6/03/2024 - Fix merge issue -Release 0.17.1 6/03/2024 +Release 0.17.1 6/03/2024 - Fix version number issue -Release 0.17.0 6/02/2024 +Release 0.17.0 6/02/2024 - Update for Foundry V12 - Update for JB2A v0.6.8 diff --git a/lang/en.json b/lang/en.json index 6504befcd..b904d232a 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1,1168 +1,1168 @@ { - "GURPS.title": "GURPS", - "GURPS.changelog": "README", - "GURPS.DontShowAgain": "Don't show README again", - "GURPS.copyrightGURPS": "GURPS is a trademark of Steve Jackson Games, and its rules and art are copyrighted by Steve Jackson Games. All rights are reserved by Steve Jackson Games. This game aid is the original creation of Chris Normand/Nose66 and is released for free distribution, and not for resale, under the permissions granted by http://www.sjgames.com/general/online_policy.html", - "GURPS.copyrightGCS": "GCS is copyrighted 1998-2020 by Richard A. Wilkes. All rights reserved ", - "__Char Sheet__": "=========", - "GURPS.portrait": "Portrait", - "__Character Sheet Identity__": "=========", - "GURPS.identity": "Identity", - "GURPS.identityName": "Name", - "GURPS.identityPlayer": "Player", - "GURPS.identityTitle": "Title", - "__Character Sheet Miscellaneous__": "=========", - "GURPS.miscellaneous": "Miscellaneous", - "GURPS.miscellaneousCreated": "Created", - "GURPS.miscellaneousModified": "Modified", - "GURPS.miscellaneousOptions": "Options", - "__Character Description__": "=========", - "GURPS.description": "Description", - "GURPS.descriptionAge": "Age", - "GURPS.descriptionAppearance": "Appearance", - "GURPS.descriptionBirthday": "Birthday", - "GURPS.descriptionBodyPlan": "Body Plan", - "GURPS.descriptionEyes": "Eyes", - "GURPS.descriptionGender": "Gender", - "GURPS.descriptionHair": "Hair", - "GURPS.descriptionHand": "Hand", - "GURPS.descriptionHeight": "Height", - "GURPS.descriptionReligion": "Religion", - "GURPS.descriptionSizeModifier": "Size Modifier (SM)", - "GURPS.descriptionSkin": "Skin", - "GURPS.descriptionTechLevel": "Tech Level (TL)", - "GURPS.weight": "Weight", - "GURPS.share": "Share", - "__Character Points__": "=========", - "GURPS.point": "Point", - "GURPS.points": "Points", - "GURPS.pointsAdvantages": "Advantages", - "GURPS.pointsAttributes": "Attributes", - "GURPS.pointsDisadvantages": "Disadvantages", - "GURPS.pointsQuirks": "Quirks", - "GURPS.pointsRace": "Race", - "GURPS.pointsSkills": "Skills", - "GURPS.pointsSpells": "Spells", - "GURPS.pointsUnspent": "Unspent", - "__Character Attributes__": "=========", - "GURPS.attributes": "Attributes", - "GURPS.attributesDX": "DX", - "GURPS.attributesDXNAME": "Dexterity", - "GURPS.attributesFPNAME": "Fatigue", - "GURPS.attributesHPNAME": "Hit Points", - "GURPS.attributesHT": "HT", - "GURPS.attributesHTNAME": "Health", - "GURPS.attributesIQ": "IQ", - "GURPS.attributesIQNAME": "Intelligence", - "GURPS.attributesPER": "Per", - "GURPS.attributesPERNAME": "Perception", - "GURPS.attributesST": "ST", - "GURPS.attributesSTNAME": "Strength", - "GURPS.attributesWILL": "Will", - "GURPS.attributesWILLNAME": "Will", - "GURPS.basicmove": "Basic Move", - "GURPS.basicspeed": "Basic Speed", - "GURPS.speed": "Speed", - "GURPS.FP": "FP", - "GURPS.frightcheck": "Fright Check", - "GURPS.hearing": "Hearing", - "GURPS.HP": "HP", - "GURPS.swing": "Basic Swing", - "GURPS.tastesmell": "Taste/Smell", - "GURPS.thrust": "Basic Thrust", - "GURPS.touch": "Touch", - "GURPS.vision": "Vision", - "GURPS.attributesQN": "QN", - "GURPS.attributesQNNAME": "Quintessence", - "__ Character AddsDisadsPerksQuirks__": "=========", - "GURPS.advDisadvPerkQuirks": "Advantages, Disadvantages, Perks & Quirks", - "GURPS.highPainThreshold": "High Pain Threshold", - "GURPS.lowPainThreshold": "Low Pain Threshold", - "GURPS.perfectBalance": "Perfect Balance", - "__ Character Skills__": "=========", - "GURPS.rsl": "RSL", - "GURPS.SkillDXA": "DX/A", - "GURPS.SkillDXE": "DX/E", - "GURPS.SkillDXH": "DX/H", - "GURPS.SkillDXVH": "DX/VH", - "GURPS.SkillHTA": "HT/A", - "GURPS.SkillHTE": "HT/E", - "GURPS.SkillHTH": "HT/H", - "GURPS.SkillHTVH": "HT/VH", - "GURPS.SkillQNA": "QN/A", - "GURPS.SkillQNE": "QN/E", - "GURPS.SkillQNH": "QN/H", - "GURPS.SkillQNVH": "QN/VH", - "GURPS.SkillIQA": "IQ/A", - "GURPS.SkillIQE": "IQ/E", - "GURPS.SkillIQH": "IQ/H", - "GURPS.SkillIQVH": "IQ/VH", - "GURPS.SkillPerA": "Per/A", - "GURPS.SkillPerE": "Per/E", - "GURPS.SkillPerH": "Per/H", - "GURPS.SkillPerVH": "Per/VH", - "GURPS.skills": "Skills", - "GURPS.SkillWillA": "Will/A", - "GURPS.SkillWillE": "Will/E", - "GURPS.SkillWillH": "Will/H", - "GURPS.SkillWillVH": "Will/VH", - "GURPS.sl": "SL", - "__Character Spells__": "=========", - "GURPS.spellClass": "Class", - "GURPS.spellCollege": "College", - "GURPS.spellCost": "Cost", - "GURPS.spellDuration": "Duration", - "GURPS.spellMaintain": "Maintain", - "GURPS.spells": "Spells", - "GURPS.spellTime": "Time", - "GURPS.spellResist": "Resisted By", - "GURPS.spellDifficulty": "Difficulty", - "__Character Equipment__": "=========", - "GURPS.equipment": "Equipment", - "GURPS.otherEquipment": "Other Equipment", - "GURPS.equipmentEquipped": "E", - "GURPS.equipmentQuantity": "Qty", - "GURPS.equipmentUses": "Uses", - "GURPS.equipmentCost": "Cost", - "GURPS.equipmentMaxUses": "Max Uses", - "GURPS.equipmentTechlevel": "Tech Level", - "GURPS.equipmentFoundryItem": "Foundry Item", - "__Character Encumbrance/Lift__": "=========", - "GURPS.basicLift": "Basic Lift", - "GURPS.carryOnBack": "Carry on Back", - "GURPS.dodge": "Dodge", - "GURPS.encumbranceMoveDodge": "Encumbrance, Move & Dodge", - "GURPS.liftingAndMovingThings": "Lifting & Moving Things", - "GURPS.maxload": "Max Load", - "GURPS.move": "Move", - "GURPS.oneHandLift": "One-Hand Lift", - "GURPS.runningShoveAndKnockOver": "Running Shove & Knock Over", - "GURPS.shiftSlightly": "Shift Slightly", - "GURPS.shoveAndKnockOver": "Shove & Knock Over", - "GURPS.twoHandLift": "Two-Hand Lift", - "__Character Weapons__": "=========", - "GURPS.acc": "Acc", - "GURPS.block": "Block", - "GURPS.blockbonus": "Block bonus", - "GURPS.bulk": "Bulk", - "GURPS.damage": "Damage", - "GURPS.meleeWeapons": "Melee Weapons", - "GURPS.parry": "Parry", - "GURPS.parrybonus": "Parry bonus", - "GURPS.range": "Range", - "GURPS.rangedWeapons": "Ranged Weapons", - "GURPS.rcl": "Rcl", - "GURPS.reach": "Reach", - "GURPS.rof": "RoF", - "GURPS.shots": "Shots", - "GURPS.usage": "Usage", - "__Apply Damage Dialog__": "=========", - "GURPS.addAbbrev": "Abbrev", - "GURPS.addAdditionalStackingModifier": "Additional modifier", - "GURPS.addAdjustedForHitLocation": "* - Adjusted for hit location", - "GURPS.addAdjustedForInjuryTolerance": "† - Adjusted for Injury Tolerance", - "GURPS.addApply": "Apply", - "GURPS.addApplyAndKeep": "Apply/Keep Open", - "GURPS.addApplyDamageDialog": "Apply Damage Dialog", - "GURPS.addApplyDamageOptions": "APPLY DAMAGE OPTIONS", - "GURPS.addApplyInjury": "Apply Injury", - "GURPS.addApplyInjuryAndKeep": "Apply Injury/Keep Open", - "GURPS.addApplyInjuryQuietly": "Apply Injury (Quietly)", - "GURPS.addApplyInjuryQuietlyAndKeep": "Apply Injury (Quietly)/Keep Open", - "GURPS.addApplyMultipleTimes": "Apply multiple times", - "GURPS.addApplyOptionsToAll": "These options apply to all damage", - "GURPS.addApplyQuietly": "Apply (Quietly)", - "GURPS.addApplyQuietlyAndKeep": "Apply (Quietly)/Keep Open", - "GURPS.addApplyTo": "Apply to", - "GURPS.addArmorDivisor": "Armor Divisor", - "GURPS.addBasicDamage": "Basic Damage", - "GURPS.addCalculationAndResults": "Calculation & Results", - "GURPS.addDamageReduction": "Damage Reduction", - "GURPS.addDamageType": "Damage Type", - "GURPS.addDiffuseMax": "Diffuse, max", - "GURPS.addDirectlyApply": "DIRECTLY APPLY", - "GURPS.addEnterModifier": "Enter Modifier", - "GURPS.addExplosion": "Explosion", - "GURPS.addExplosionHex": "{hex} hex from center", - "GURPS.addExplosionHexes": "{hex} hexes from center", - "GURPS.addFlexibleArmor": "Flexible Armor", - "GURPS.addHardenedDRLevel": "Hardened DR Level", - "GURPS.addHitLocationAndDR": "Hit Location & DR", - "GURPS.addHitLocationWoundModifiers": "Hit Location Wound Modifiers", - "GURPS.addInjury": "Injury", - "GURPS.addInjuryTolerance": "Injury Tolerance", - "GURPS.addInjuryToleranceDiffuse": "Diffuse", - "GURPS.addInjuryToleranceHomogenous": "Homogenous", - "GURPS.addInjuryToleranceUnliving": "Unliving", - "GURPS.addLargeAreaInjury": "Large-Area Injury", - "GURPS.addLocationMax": "Location Max", - "GURPS.addOverrideDR": "Override DR for Location", - "GURPS.addPenetrating": "Penetrating", - "GURPS.addRangedHalfDamage": "Ranged, Half Damage (1/2D)", - "GURPS.addRangedHalfDamageShort": "Ranged (1/2D)", - "GURPS.addShotgunCloseRange": "Shotgun, Extremely Close", - "GURPS.addShotgunDamage": "Shotgun Damage", - "GURPS.addShotgunRofMultiplier": "RoF Multiplier", - "GURPS.addSingleRollSelected": "Single damage roll selected", - "GURPS.addSpecialCombatSituations": "Special Situations", - "GURPS.addTacticalRules": "Tactical Rules", - "GURPS.addTacticalRulesDefaults": "Use systems settings to set defaults", - "GURPS.addTitle": "Apply {basic} point(s) of [{damage}] damage to {name}", - "GURPS.addTitleConcat0": "Apply", - "GURPS.addTitleConcat01": "point of ", - "GURPS.addTitleConcat0s": "points of ", - "GURPS.addTitleConcat1": "damage to {name}", - "GURPS.addTypeAndWoundingModifiers": "Type & Wounding Modifiers", - "GURPS.addVulnerability": "Vulnerability", - "GURPS.addWHard": "w/Hard", - "__Body Plan__": "=========", - "GURPS.BODYPLANarachnoid": "Arachnoid", - "GURPS.BODYPLANavian": "Avian", - "GURPS.BODYPLANcancroid": "Cancroid", - "GURPS.BODYPLANcentaur": "Centaur", - "GURPS.BODYPLANhexapod": "Hexapod", - "GURPS.BODYPLANhexapodWinged": "Hexapod, Winged", - "GURPS.BODYPLANhumanoid expanded": "Humanoid, Expanded (GCA)", - "GURPS.BODYPLANhumanoid": "Humanoid", - "GURPS.BODYPLANichthyoid": "Ichthyoid", - "GURPS.BODYPLANoctopod": "Octopod", - "GURPS.BODYPLANquadruped": "Quadruped", - "GURPS.BODYPLANquadrupedWinged": "Quadruped, Winged", - "GURPS.BODYPLANscorpion": "Scorpion", - "GURPS.BODYPLANsnakeman": "Snakeman", - "GURPS.BODYPLANsquid": "Squid", - "GURPS.BODYPLANvermiform": "Vermiform", - "GURPS.BODYPLANvermiformWinged": "Serpent, Winged", - "GURPS.BODYPLANwinged humanoid": "Humanoid, Winged", - "__Chat Messages__": "=========", - "GURPS.chatClearing": "Clearing", - "GURPS.chatClearingLastActor": "Clearing Last Actor", - "GURPS.chatDamageResultEnd": "to the {location}", - "GURPS.chatDamageResultMiddle": "of {type} damage", - "GURPS.chatDamageResultShowMath": "Show the math", - "GURPS.chatDamageResultStart": "injures {defender} for {injury}", - "GURPS.chatDoesNotHaveEnough": "does not have enough 'USES'", - "GURPS.chatExceededMax": "Exceeded MAX", - "GURPS.chatExceededMaxUses": "Exceeded 'MAX USES'", - "GURPS.chatFixedDamage": "[{dice} {damageTypeText}] damage.", - "GURPS.chatLightSource": "Pick the light source the selected token is holding.", - "GURPS.chatMoreThanOneActor": "More than one Actor found matching", - "GURPS.chatMoreThanOneToken": "More than one Token found matching", - "GURPS.chatMultipleOwnedFound": "You own more than one token in this scene. You can either select one and retry this command without the '@self' keyword, or use the ':name' option.", - "GURPS.chatMustBeACheck": "The On-the-Fly formula must be some kind of check", - "GURPS.chatNoActorFound": "No Actor/Token found matching", - "GURPS.chatNoEquipmentMatched": "No equipment matched", - "GURPS.chatNoResourceTracker": "No Resource Tracker matched", - "GURPS.chatNoStatusMatched": "No status matched", - "GURPS.chatNoOwnedTokenFound": "You do not own any tokens in this scene.", - "GURPS.chatNoTokens": "Your character does not have any tokens. We require a token to set statuses", - "GURPS.chatQty": "QTY", - "GURPS.chatQtySetTo": "QTY set to", - "GURPS.chatResetTo": "reset to", - "GURPS.chatResourceTracker": "Resource Tracker", - "GURPS.chatResultBelowZero": "Result below zero", - "GURPS.chatRolling": "Rolling [{dice}{desc}]", - "GURPS.chatRollingDamage": "Rolling [{dice} {damageTypeText}] damage{numtimes}.", - "GURPS.chatRollingCR": "Control Roll", - "GURPS.chatSetTo": "set to", - "GURPS.chatSelectSelfOrNameTokens": "You must select tokens, use '{self}', or use ':<token-name>' to apply status effects.", - "GURPS.chatShock": "{name} takes {modifier} points of Shock ", - "GURPS.chatSuffersCripplingInjury": "{name} suffers a crippling injury {classStart}([PDF:{pdfref}]){classEnd} to the location {location}.", - "GURPS.andHalfMove": "and half Move.", - "GURPS.chatToApplyEffects": "to apply status effects", - "GURPS.chatTokenLightPicker": "Token Light Picker", - "GURPS.chatToggling": "Toggling", - "GURPS.chatTurnOnReeling": "{name} is Reeling. Move and Dodge are halved. ([PDF:{pdfref}])", - "GURPS.chatTurnOnTired": "{name} is Tired. Move, Dodge, and ST are halved. ([PDF:{pdfref}])", - "GURPS.chatTurnOffReeling": "{name} is no longer Reeling.", - "GURPS.chatTurnOffTired": "{name} is no longer Tired.", - "GURPS.chatUnableToFindMacro": "Unable to find macro named", - "GURPS.chatUnableToFindManeuver": "Unable to find maneuver named", - "GURPS.chatNotInCombat": "You can only set the Maneuver if the token is in combat", - "GURPS.chatUnrecognizedFormat": "Unrecognized format", - "GURPS.chatUses": "'USES'", - "GURPS.chatUsesIsNaN": "'USES' is not a number", - "GURPS.chatUsesReset": "'USES' reset to 'MAX USES'", - "GURPS.chatUsesSet": "'USES' set to", - "GURPS.chatYouDoNotHaveEnough": "You do not have enough", - "GURPS.chatYouMustBeGM": "You must be a GM to execute this command", - "GURPS.chatYouMustHaveACharacterSelected": "You must have a character selected", - "GURPS.chatYouMustSelectTokens": "You must select tokens (or use", - "GURPS.chatHelpHelp": "/help chat-command OR\n\n?chat-command: to see help for that command", - "GURPS.chatHelpSound": "Play a sound in the background
parameters:\nw: wait seconds before starting sound\nv: volume\n<full path filename>
examples:\n/sound w2.5 /path/filename\n/sound v0.6 /path/filename\n/sound w3 v2 /path/filename", - "GURPS.chatHelpW": "Whisper to players or the owners of the selected tokens
parameters:\n<[player names]>\n@: whisper to the owners of the selected tokens\n
examples:\n/w [Chris] msg sent to Player Chris\n/w @ msg sent to owners of selected tokens", - "GURPS.chatHelpWait": "Wait X milliseconds before executing the next chat command
parameters:\nX: the number of milliseconds to wait\n
examples:\n/wait 500", - "GURPS.chatHelpRa": "Roll Against (or Private Roll Against)
parameters:\nX: Skill level to roll against\nSkillname-X: Roll against X, but display 'Skillname' instead of 'Default'\n
examples:\n/ra 12\n.ra 13\n/pra 11\n.pra 10\n/ra Sneak-12\n.ra Brawling-13\n/pra Trap-11\n.pra FastDraw-10", - "GURPS.chatHelpFpHp": "Apply formula to FP or HP of selected characters
parameters:\n<formula>\nreset: Reset FP or HP back to starting value
examples:\n/fp +1\n/hp -1\n/fp +1d\n/hp +1d-3!\n/fp reset\n", - "GURPS.chatHelpSelect": "Select token(s)
parameters:\n<character name (may use '*')>\n@self: select the token of the current character\n!:select across all scenes, not just current
examples:\n/select Bog\n/select @self\n/select Bog !", - "GURPS.chatHelpUses": "Modify the USES column of equipment
parameters:\n<formula>\n<equipment>\no:<equipment>: only search 'other' list\nreset: set USES to MAX_USES
examples:\n/uses +1 equipment\n/uses -2 equipment\n/uses =20 equipment\n/uses +1 o:equipment\n/uses reset equipment", - "GURPS.chatHelpQty": "Modify the QTY column of equipment
parameters:\n<formula>\n<equipment>\no:<equipment>: only search 'other' list
examples:\n/qty +1 equipment\n/qty -2 equipment\n/qty =20 equipment\n/qty +1 o:equipment", - "GURPS.chatHelpLight": "Set token's light level
parameters:\nnone|off: turn off light\nX: dim light radius\nY: bright light radius\nZ: broadcast angle of light \n#RRGGBB: color of light\nW: color intensity (0.0-1.0)\n<anim>: animation pattern (torch, pulse, chroma, wave, fog, sunburst, dome, emanation, hexa, ghost, energy, roiling, hole\nSPEED: speed of animation (1-10)\nINT: intensity of animation (1-10)
examples:\n/li 6 2\n/li 8 3 90\n/li 6 2 #ff0000\n/li 6 2 #ff1111 0.5\n/li 6 2 torch\n/li 8 4 90 #ff7777 0.5 pulse 5 5\nhttps://foundryvtt.com/article/lighting/", - "GURPS.chatHelpTracker": "Modify the Resource Tracker
command format:\n/tr0-3\n/tracker0-3\n/resource0-3\n/rt0-3\n/tr(name)\n/tracker(name)\n/resource(name)\n/rt(name)
parameters:\n<formula>\nreset: reset Tracker to starting value
examples:\n/tr0 +1\n/tr0 -2\n/tracker1 =20\n/tr(arrows) +1\n/resource(rounds) reset", - "GURPS.chatHelpStatus": "Set token's effects status
parameters:\ntoggle|t: toggle the status\non|+|set: turn on the status\noff|-|unset: turn off the status\nclear: remove all statuses\n@self OR :tokenname\nlist: display all status names\n{JSON data}: optional 'duration.combat' data
examples:\n/st on prone :Bog\n/st - shock1 @self\n/st list", - "GURPS.chatHelpRemote": "Execute an On-the-Fly formula remotely
parameters:\n[OtF]: On-the-Fly formula\n<player names>|blank: list of player names (or blank to send to all players)
examples:\n/rem [‏PER] Chris\n/rem [‏ST+2]", - "GURPS.chatHelpEveryone": "Apply formula to FP or HP of all player characters or roll On-the-Fly formula locally against all player characters
parameters:\nfp <formula>\nhp <formula>\n [OtF]: execute OtF (locally) for all player characters\nfp reset: Reset FP back to starting values\nhp reset: Reset HP back to starting values
examples:\n/ev fp +1\n/ev hp -1\n/ev fp +1d\n/ev hp +1d-3!\n/ev fp reset\n/ev [‏PER]", - "GURPS.chatHelpAnim": "Play a centered or moving animation.\n
parameters (for both)\nlist: display a list of available animations\nwX: wait X seconds before displaying animation\n<filename pattern>: pattern can contain *\nXx:Y: repeat animation X times (2x, 3x, etc.) with Y seconds delay between animations\n
parameters for centered animations:\nc: indicates a centered animation\n*X: scale animation by X\n@self: use self as center, instead of target\nThe following options can be added after 'c'\n f: flip the animation on the x axis (left to right)\n m: move the centered animation to the target\n n: do not rotate moving centered animation\n X: degrees to rotate animation\n :Y,Z: offset animation (default 0.5,0.5)\n
examples of centered animations:\n/anim <pattern> c *0.5 3x\n'centered, 1/2 scale, 3 times'\n\n/anim <pattern> cf *2 3x:4\n'centered, flipped (left-right), 2x scale, 3 times with 4 second delay\n\n/anim <pattern> cm\n'centered, move animation from self to target'\n\n/anim <pattern> cmn\n'centered, move animation from self to target, do not rotate'\n\n/anim <pattern> cfm\n'centered, flipped, move animation from self to target'\n\n/anim <pattern> c90\n'centered, rotate 90 degrees'\n\n/anim <pattern> cf180 *.333\n'centered, flipped, rotate 180 degrees, 1/3 scale'\n\n/anim <pattern> cm45\n/anim <pattern> c:0,1\n/anim <pattern> cf:0.5,1\n/anim <pattern> cmn:0.9,1 *2\n
parameters for a moving animations:\n-X: shift left (0.0-1.0) towards the start of the animation\n+X: stretch right (0.0-infinity) towards the destination\n
examples of moving animations:\n/anim <pattern> -0.1 +0.1 2x\n'moving animation, left shift 10%, right stretch 10%, 2 times'", - "GURPS.chatHelpShow": "Show various values from tokens in the scene
parameters:\n-a : sort alphabetically\n-pc : only show PCs\n-npc : only show NPCs\n<Attributes (primary and secondary)>\n<Skill names>\nparry\nblock\nwill\nfright\nper\nvision\nhearing\ntaste\nsmell\nmove\nspeed
examples:\n/show -pc HP FP IQ\n/show -a Stealth PER\n/show per move speed\n/show -npc vision hearing", - "GURPS.chatHelpManeuver": "Set the following maneuvers on the current character. You may use * to match Maneuver names, example: '/man All Out*Double'
", - "GURPS.chatHelpRepeat": "Repeat the following /anim command with a delay of X seconds in between.
examples:\n/repeat /anim 1.2 heal*blue c", - "GURPS.chatWantsToExecute": "Wants to execute {command} on {name},

Is that OK?", - "GURPS.chatSentTo": "Sent command [{cmd}] to {name}", - "__Permissions__": "=========", - "GURPS.cannotDragNonFoundryEqt": "You cannot drag non-Foundry equipment to another character.", - "GURPS.youDoNotHavePermssion": "You do not have permission to do that.", - "__Damage Types__": "=========", - "GURPS.damageAbbrevburn": "burn", - "GURPS.damageAbbrevcor": "cor", - "GURPS.damageAbbrevcr": "cr", - "GURPS.damageAbbrevcut": "cut", - "GURPS.damageAbbrevdmg": "dmg", - "GURPS.damageAbbrevfat": "fat", - "GURPS.damageAbbrevimp": "imp", - "GURPS.damageAbbrevinjury": "injury", - "GURPS.damageAbbrevpi-": "pi-", - "GURPS.damageAbbrevpi": "pi", - "GURPS.damageAbbrevpi+": "pi+", - "GURPS.damageAbbrevpi++": "pi++", - "GURPS.damageAbbrevtox": "tox", - "GURPS.damageAbbrevkb": "kb", - "GURPS.damageTypeBurning": "Burning", - "GURPS.damageTypeCorrosive": "Corrosive", - "GURPS.damageTypeCrushing": "Crushing", - "GURPS.damageTypeCutting": "Cutting", - "GURPS.damageTypeDamage": "Damage", - "GURPS.damageTypeFatigue": "Fatigue", - "GURPS.damageTypeHuge Piercing": "Huge Piercing", - "GURPS.damageTypeImpaling": "Impaling", - "GURPS.damageTypeInjury": "Injury", - "GURPS.damageTypeLarge Piercing": "Large Piercing", - "GURPS.damageTypePiercing": "Piercing", - "GURPS.damageTypeSmall Piercing": "Small Piercing", - "GURPS.damageTypeToxic": "Toxic", - "__Drag Ruler__": "=========", - "GURPS.dragrulerFly": "Fly", - "GURPS.dragrulerSprint": "Sprint", - "GURPS.dragrulerWalk": "Walk", - "__Fantastic Dungeon Grappling__": "=========", - "GURPS.grapplingControlled": "Controlled [-8 DX]", - "GURPS.grapplingControlPoints": "Control Points", - "GURPS.grapplingCPAbbrev": "ctrl", - "GURPS.grapplingGrabbed": "Grabbed [-2 DX]", - "GURPS.grapplingGrappled": "Grappled [-4 DX]", - "GURPS.grapplingPinned": "Pinned [-12 DX]", - "GURPS.grapplingRestrained": "Restrained [-6 DX]", - "GURPS.grapplingUnrestrained": "Unrestrained", - "__Hit Location__": "=========", - "GURPS.hitLocation": "Hit Location", - "GURPS.hitLocationArm 1-2": "Arm 1-2", - "GURPS.hitLocationArm 3-4": "Arm 3-4", - "GURPS.hitLocationArm 5-6": "Arm 5-6", - "GURPS.hitLocationArm 7-8": "Arm 7-8", - "GURPS.hitLocationArm, holding shield": "Arm, holding shield", - "GURPS.hitLocationArm": "Arm", - "GURPS.hitLocationArm*": "Arm", - "GURPS.hitLocationBrain": "Brain", - "GURPS.hitLocationChest": "Chest", - "GURPS.hitLocationChinks in Other": "Chinks in armor (other)", - "GURPS.hitLocationChinks in Torso": "Chinks in armor (torso)", - "GURPS.hitLocationDescChest": "*hit chest", - "GURPS.hitLocationDescFront": "front only", - "GURPS.hitLocationDescHalfDR": "½ DR", - "GURPS.hitLocationDescImp": "imp or pi(any) only", - "GURPS.hitLocationDescLimb": "*hit limb", - "GURPS.hitLocationDescNeck": "*hit neck", - "GURPS.hitLocationDR": "DR", - "GURPS.hitLocationDRWithDivisor": "Effective DR", - "GURPS.hitLocationExtremity": "Extremity", - "GURPS.hitLocationEye": "Eye", - "GURPS.hitLocationEyes": "Eyes", - "GURPS.hitLocationFace, from behind": "Face, from behind", - "GURPS.hitLocationFace": "Face", - "GURPS.hitLocationFin": "Fin", - "GURPS.hitLocationFin*": "Fin", - "GURPS.hitLocationFoot": "Foot", - "GURPS.hitLocationForeleg": "Foreleg", - "GURPS.hitLocationGroin": "Groin", - "GURPS.hitLocationHand": "Hand", - "GURPS.hitLocationHind Leg": "Hind Leg", - "GURPS.hitLocationJaw": "Jaw", - "GURPS.hitLocationLeft Arm, holding shield": "Left Arm, holding shield", - "GURPS.hitLocationLeft Arm": "Left Arm", - "GURPS.hitLocationLeft Leg": "Left Leg", - "GURPS.hitLocationLeg 1-2": "Leg 1-2", - "GURPS.hitLocationLeg 3-4": "Leg 3-4", - "GURPS.hitLocationLeg 5-6": "Leg 5-6", - "GURPS.hitLocationLeg 7-8": "Leg 7-8", - "GURPS.hitLocationLeg": "Leg", - "GURPS.hitLocationLimb Vein/Artery": "Limb Vein/Artery", - "GURPS.hitLocationMid Leg": "Mid Leg", - "GURPS.hitLocationMid Leg*": "Mid Leg", - "GURPS.hitLocationNeck Vein/Artery": "Neck Vein/Artery", - "GURPS.hitLocationNeck": "Neck", - "GURPS.hitLocationNose": "Nose", - "GURPS.hitLocationPenalty": "Penalty", - "GURPS.hitLocationRandom": "Random", - "GURPS.hitLocationRight Arm, holding shield": "Right Arm, holding shield", - "GURPS.hitLocationRight Arm": "Right Arm", - "GURPS.hitLocationRight Leg": "Right Leg", - "GURPS.hitLocationSkull, from behind": "Skull, from behind", - "GURPS.hitLocationSkull": "Skull", - "GURPS.hitLocationTail": "Tail", - "GURPS.hitLocationTorso": "Torso", - "GURPS.hitLocationTorso*": "Torso", - "GURPS.hitLocationVitals, Heart": "Vitals, Heart", - "GURPS.hitLocationVitals": "Vitals", - "GURPS.hitLocationWhere": "Where", - "GURPS.hitLocationWing": "Wing", - "__Modifier Bucket__": "=========", - "GURPS.modifier": "Modifier", - "GURPS.modifierTitle": "Modifiers", - "GURPS.modifierRangeTitle": "Speed / Range", - "GURPS.modifierRange": "for range/speed {range} yds", - "GURPS.modifierRangeMHClose": "Close range (5 yds)", - "GURPS.modifierRangeMHCloseDesc": "Can touch or strike foe", - "GURPS.modifierRangeMHShort": "Short range (20 yds)", - "GURPS.modifierRangeMHShortDesc": "Can talk to foe; pistol or muscle-powered missile range", - "GURPS.modifierRangeMHMedium": "Medium range (100 yds)", - "GURPS.modifierRangeMHMediumDesc": "Can only shout to foe; shotgun or SMG range", - "GURPS.modifierRangeMHLong": "Long range (500 yds)", - "GURPS.modifierRangeMHLongDesc": "Opponent out of earshot; rifle range", - "GURPS.modifierRangeMHExtreme": "Extreme range (500+ yds)", - "GURPS.modifierRangeMHExtremeDesc": "Rival difficult to even see; sniper range", - "GURPS.modifierAddRangeRuler": "Bucket: Add Range Ruler modifier", - "GURPS.modifierAddRangeRulerHint": "If checked, the system will automatically add the last measured Range modifier to the Modifier Bucket.", - "GURPS.modifierAimAllOutAim": "to Aiming rolls (All-Out Aim)", - "GURPS.modifierAimAllOutAimBraced": "to Aiming rolls if braced (All-Out Aim)", - "GURPS.modifierAimCommittedAim": "to Aiming rolls (Committed Aim)", - "GURPS.modifierAimCommittedAimBraced": "to Aiming rolls if braced (Committed Aim)", - "GURPS.modifierAllOutAttackRanged": "to hit (All-Out Attack (Ranged))", - "GURPS.modifierAffliction": "Afflictions", - "GURPS.modifierAfflictionCough": "-3 to DX checks (Coughing)", - "GURPS.modifierAfflictionCoughIQ": "-1 to IQ checks (Coughing)", - "GURPS.modifierAfflictionDrowsy": "-2 to IQ/DX/CR checks (Drowsy)", - "GURPS.modifierAfflictionDrunk": "-2 to IQ/DX checks (Drunk)", - "GURPS.modifierAfflictionDrunkCR": "-4 to CR checks (Drunk)", - "GURPS.modifierAfflictionEuphoria": "-3 to IQ/DX/CR checks (Euphoria)", - "GURPS.modifierAfflictionModerate": "-2 to IQ/DX/CR checks (Moderate Pain)", - "GURPS.modifierAfflictionModerateHPT": "-1 to IQ/DX/CR checks (Moderate Pain w/HPT)", - "GURPS.modifierAfflictionNausea": "-2 to all attributes (Nauseated)", - "GURPS.modifierAfflictionNauseaDef": "-1 to active defenses (Nauseated)", - "GURPS.modifierAfflictionRetch": "-5 to IQ/DX/Per checks (Retching)", - "GURPS.modifierAfflictionSevere": "-4 to IQ/DX/CR checks (Severe Pain)", - "GURPS.modifierAfflictionSevereHPT": "-2 to IQ/DX/CR checks (Severe Pain w/HPT)", - "GURPS.modifierAfflictionTerrible": "-6 to IQ/DX/CR checks (Terrible Pain)", - "GURPS.modifierAfflictionTerribleHPT": "-3 to IQ/DX/CR checks (Terrible Pain w/HPT)", - "GURPS.modifierAfflictionTipsy": "-1 to IQ/DX checks (Tipsy)", - "GURPS.modifierAfflictionTipsyCR": "-2 to CR checks (Tipsy)", - "GURPS.modifierAppearBelow": "They will appear in the Current Modifiers list below.", - "GURPS.modifierAutomatic": "Automatic", - "GURPS.modifierBlindAttack": "-10 to hit (Blind)", - "GURPS.modifierBlindDefend": "-4 to dodge (Blind -- cannot see attacker)", - "GURPS.modifierBlockRetreat": "to Block/Parry (retreat)", - "GURPS.modifierClickToAdd": "Click on modifiers above and to the right to add to your next roll.", - "GURPS.modifierCommittedAttackRanged": "to hit (Committed Attack (Ranged))", - "GURPS.modifierCommon": "Common Modifiers", - "GURPS.modifierCover": "Cover", - "GURPS.modifierCoverBehindFigure": "-4 to hit (Behind same-sized figure)", - "GURPS.modifierCoverCrouch": "-2 to hit (Crouching or Kneeling, no cover)", - "GURPS.modifierCoverHalfExposed": "-3 to hit (Body half exposed)", - "GURPS.modifierCoverHead": "-5 to hit (Head only)", - "GURPS.modifierCoverHeadShoulder": "-4 to hit (Head and shoulders)", - "GURPS.modifierCoverLight": "-2 to hit (Behind light cover)", - "GURPS.modifierCoverPosture": "Cover and Posture", - "GURPS.modifierCoverProne": "-4 to hit (Prone, no cover)", - "GURPS.modifierCoverProneHeadDown": "-7 to hit (Prone, some cover, head down)", - "GURPS.modifierCoverProneHeadUp": "-5 to hit (Prone, some cover, head up)", - "GURPS.modifierCoverThroughHex": "-4 to hit (Firing through occupied hex)", - "GURPS.modifierCurrentEffects": "Current Effects", - "GURPS.modifierCurrentModifiers": "Current Modifiers", - "GURPS.modifierDangerous": "Dangerous", - "GURPS.modifierDeceptiveAttack": "to hit (Deceptive Attack)", - "GURPS.modifierDeterminedAttack": "to hit (Determined Attack)", - "GURPS.modifierDodgeAcrobatic": "to Dodge (Acrobatics, success)", - "GURPS.modifierDodgeDive": "to Dodge (dodge and drop)", - "GURPS.modifierDodgeFailedAcro": "to Dodge (Acrobatics, failed)", - "GURPS.modifierDodgeRear": "to Dodge (attacked from rear)", - "GURPS.modifierDodgeRetreat": "to Dodge (retreat)", - "GURPS.modifierDodgeSide": "to Dodge (attacked from side)", - "GURPS.modifierEasy": "Easy", - "GURPS.modifierExtraEffort": "Extra Effort", - "GURPS.modifierFavorable": "Favorable", - "GURPS.modifierFeverishDef": "Feverish Defense", - "GURPS.modifierDefDeceptiveAttack": "to defenses due to Deceptive attack", - "GURPS.modifierDefenseCommittedAim": "to defenses due to Committed Aim", - "GURPS.modifierDefenseCommittedAttackRanged": "to defenses due to Committed Attack (Ranged)", - "GURPS.modifierMaintainConcentration": "to Will Check, to maintain concentration", - "GURPS.modifierGrappling": "-4 to DX and DX-based skills (Grappled)", - "GURPS.modifierGMBlessed": "GM blessed", - "GURPS.modifierGMDontTry": "GM don't try it", - "GURPS.modifierGMSaidSo": "GM said so", - "GURPS.modifierHard": "Hard", - "GURPS.modifierHeroicCharge": "Heroic Charge", - "GURPS.modifierHitLocation": "Hit Locations (if miss by 1, then *)", - "GURPS.modifierImpossible": "Impossible", - "GURPS.modifierJournalManager": "Modifier Bucket Journals", - "GURPS.modifierJournals": "Modifier Bucket Journal List", - "GURPS.modifierLightDim": "Large fire / torch/ sunset / sunrise", - "GURPS.modifierLightFullMoon": "Full moon", - "GURPS.modifierLightHalfMoon": "Half moon", - "GURPS.modifierLightMoonless": "Overcast moonless night", - "GURPS.modifierLightNone": "Total darkness", - "GURPS.modifierLightQuarterMoon": "Quarter moon", - "GURPS.modifierLightStarlight": "Starlight", - "GURPS.modifierLightStarlightClouds": "Starlight through clouds", - "GURPS.modifierLightTwilight": "Twilight / gaslight / flashlight", - "GURPS.modifierLightDeepTwilight": "Deep twilight / candlelight", - "GURPS.modifierMightyBlow": "damage (Mighty Blow)", - "GURPS.modifierMoveAttack": "to hit (Move and Attack)", - "GURPS.modifierOthers": "Other Modifiers", - "GURPS.modifierPosture": "Posture", - "GURPS.modifierPostureCrouchMelee": "-2 to hit with melee combat (Crouching)", - "GURPS.modifierPostureCrouchRanged": "-2 to be hit with ranged combat (Crouching/Kneeling)", - "GURPS.modifierPostureKneelDefend": "-2 to active defenses (Kneeling/Sitting)", - "GURPS.modifierPostureKneelMelee": "-2 to hit with melee combat (Kneeling/Sitting)", - "GURPS.modifierPostureProneDefend": "-3 to active defenses (Crawling/Lying Down)", - "GURPS.modifierPostureProneMelee": "-4 to hit with melee combat (Crawling/Lying Down)", - "GURPS.modifierPostureProneRanged": "-2 to be hit with ranged combat (Sitting/Crawling/Lying Down)", - "GURPS.modifierQuality": "Equipment Quality", - "GURPS.modifierQualityBest": "Best Possible", - "GURPS.modifierQualityFine": "Fine Quality (20× cost)", - "GURPS.modifierQualityGood": "Good Quality (5× cost)", - "GURPS.modifierQualityImprovised": "Improvised", - "GURPS.modifierQualityImprovTech": "Improvised (technological)", - "GURPS.modifierQualityMissing": "Missing/Damaged Components", - "GURPS.modifierQualityNone": "None", - "GURPS.modifierQualityNoneTech": "None (techological)", - "GURPS.modifierScaleLarge": "Large (110%)", - "GURPS.modifierScaleNormal": "Normal (100%)", - "GURPS.modifierScaleSmall": "Small (90%)", - "GURPS.modifierScaleVeryLarge": "Very Large (120%)", - "GURPS.modifierScaleVerySmall": "Very Small (80%)", - "GURPS.modifierSelectJournalButton": "Select Bucket Journals", - "GURPS.modifierSelectJournals": "Bucket: Journal Entries", - "GURPS.modifierSelectJournalsAside": "Only 'standard' (HTML) journals are valid to view in the Modifier Bucket. E.g., PDFs cannot be displayed.", - "GURPS.modifierSelectJournalsHint": "Select the Journal entries to display in the Modifier Bucket.", - "GURPS.modifierSelectJournalsTitle": "Select Modifier Bucket Journals", - "GURPS.modifierSendTo": "Send Modifier Bucket to:", - "GURPS.modifierShieldDB": "to Dodge (Shield DB)", - "GURPS.modifierShowOnMouseOver": "Bucket: Show on mouse over", - "GURPS.modifierShowOnMouseOverHint": "If checked, the Modifier window displays like a tooltip: when the mouse hovers over the Modifier Bucket. If this is turned off, you can bring up the Tooltip by Left Clicking on the Modifier Bucket. You must restart Foundry for this setting to take effect.", - "GURPS.modifierSize": "Size Modifier", - "GURPS.modifierSizeDetail": "Difference in Melee; Absolute in Ranged", - "GURPS.modifierSizeEntry": "{SM} Size {us} ({metric})", - "GURPS.modifierStatus": "Status", - "GURPS.modifierStatusAffliction": "Status and Afflictions", - "GURPS.modifierStatusShock1": "-1 to IQ/DX checks (Shock 1)", - "GURPS.modifierStatusShock2": "-2 to IQ/DX checks (Shock 2)", - "GURPS.modifierStatusShock3": "-3 to IQ/DX checks (Shock 3)", - "GURPS.modifierStatusShock4": "-4 to IQ/DX checks (Shock 4)", - "GURPS.modifierStatusStunned": "-4 to active defenses (Stunned)", - "GURPS.modifierStrongAttack": "damage (Strong Attack)", - "GURPS.modifierTabAside": "Use System Settings to define Journal Entries to display here.", - "GURPS.modifierTaskDifficulty": "Task Difficulty", - "GURPS.modifierTelegraphicAttack": "to hit (Telegraphic Attack)", - "GURPS.modifierToHit": "to hit", - "GURPS.modifierTrivial": "Trivial", - "GURPS.modifierUnfavorable": "Unfavorable", - "GURPS.modifierUserEntered": "Or you can enter a modifier", - "GURPS.modifierVeryEasy": "Very Easy", - "GURPS.modifierVeryFavorable": "Very Favorable", - "GURPS.modifierVeryHard": "Very Hard", - "GURPS.modifierVeryUnfavorable": "Very Unfavorable", - "GURPS.modifierViewScale": "Bucket: Scale Factor", - "GURPS.modifierViewScaleHint": "Use this to scale up or down the size of the Modifier Bucket.", - "GURPS.modifierWillCheck": "WILL check to maintain Aim", - "__PDF References__": "=========", - "GURPS.pdfAllOutAim": "PY77:25", - "GURPS.pdfAllOutAttackRanged": "PY77:26", - "GURPS.pdfAllOutDefense": "B365", - "GURPS.pdfBlockRetreat": "B377", - "GURPS.pdfCrippling": "B420", - "GURPS.pdfCommittedAim": "PY77:25", - "GURPS.pdfCommittedAttackRanged": "PY77:26", - "GURPS.pdfDeceptiveAttack": "B369", - "GURPS.pdfDeterminedAttack": "B365", - "GURPS.pdfDamageRoll": "B378", - "GURPS.pdfDodgeAcrobatic": "B374", - "GURPS.pdfDodgeDive": "B377", - "GURPS.pdfDodgeFailedAcro": "B375", - "GURPS.pdfDodgeRear": "B391", - "GURPS.pdfDodgeRetreat": "B375", - "GURPS.pdfDodgeSide": "B390", - "GURPS.pdfExtraEffort": "B357", - "GURPS.pdfGrappling": "B370", - "GURPS.pdfHazardCoughing": "B428", - "GURPS.pdfHazardDrowsy": "B428", - "GURPS.pdfHazardDrunk": "B428", - "GURPS.pdfHazardEuphoria": "B428", - "GURPS.pdfHazardNausea": "B428", - "GURPS.pdfHazardPain": "B428", - "GURPS.pdfHazardRetching": "B429", - "GURPS.pdfHazardTipsy": "B428", - "GURPS.pdfHeroicCharge": "MA131", - "GURPS.pdfHPT": "B59", - "GURPS.pdfKnockback": "B378", - "GURPS.pdfKnockdownStun": "B420", - "GURPS.pdfLPT": "B142", - "GURPS.pdfMajorWound": "B420", - "GURPS.pdfMightyBlow": "MA131", - "GURPS.pdfMoveAttack": "B365", - "GURPS.pdfPostureCrawling": "B551", - "GURPS.pdfPostureCrouching": "B551", - "GURPS.pdfPostureKneeling": "B551", - "GURPS.pdfPostureLyingDown": "B551", - "GURPS.pdfPostureSitting": "B551", - "GURPS.pdfReeling": "B419", - "GURPS.pdfShieldDB": "B374", - "GURPS.pdfShieldRush": "B372", - "GURPS.pdfShock": "B419", - "GURPS.pdfStrongAttack": "B365", - "GURPS.pdfSuffocation": "B436", - "GURPS.pdfTired": "B426", - "GURPS.pdfTelegraphicAttack": "MA113", - "GURPS.pdfTempAttribPenalties": "B421", - "GURPS.pdfVisibility": "B394", - "__Resolve Damage Dialog__": "=========", - "GURPS.RESOLVEDAMAGEMultiple": "Multiple rolls", - "GURPS.RESOLVEDAMAGEPrompt": "What do you want to do with this Damage roll?", - "GURPS.RESOLVEDAMAGEQuantity": "Number of rolls:", - "GURPS.RESOLVEDAMAGESendTo": "Send OtF to...", - "GURPS.RESOLVEDAMAGETitle": "Resolve Damage Roll", - "__Resource Trackers__": "=========", - "GURPS.resourceCopyTemplate": "Copy Template", - "GURPS.resourceCurrentValue": "Current Value", - "GURPS.resourceDamageTracker": "Damage Tracker (damage adds to value).", - "GURPS.resourceDamageType": "Use as Damage Type", - "GURPS.resourceDeleteTracker": "Delete Tracker", - "GURPS.resourceEditTracker": "Edit Tracker", - "GURPS.resourceInvalidAlias": "Invalid alias [{alias}].
Only alphabet and number characters, plus ('+', '_', and '-'), are allowed.", - "GURPS.resourceTemplateAlias": "Alias", - "GURPS.resourceTemplateButton": "View and Edit Trackers", - "GURPS.resourceTemplateClickToAdd": "Click the '+' button to add a template.", - "GURPS.resourceTemplateHint": "Use this to create, reuse, and automatically apply Resource Trackers to character sheets.", - "GURPS.resourceTemplateInitializer": "Initializer", - "GURPS.resourceTemplateManager": "Resource Tracker Manager", - "GURPS.resourceTemplateSlot": "Assigned Slot", - "GURPS.resourceTemplateTitle": "Resource Tracker Templates", - "GURPS.resourceTracker": "Tracker", - "GURPS.resourceTrackerEditor": "Resource Tracker Editor", - "GURPS.resourceTrackers": "Resource Trackers", - "GURPS.resourceUndefined": "None Defined", - "GURPS.resourceUpdateTrackerSlot": "Update Tracker Slot", - "GURPS.slotNotUnique": "There is already a tracker assigned to slot Tracker {value}.", - "GURPS.trackerNotUnique": "Tracker name ({name}) or alias ({alias}) is not unique.", - "GURPS.resourceEnforceMinimum": "Enforce Minimum", - "GURPS.resourceEnforceMaximum": "Enforce Maximum", - "GURPS.resourceTemplateName": "Template Name", - "Skill Names__": "=========", - "GURPS.skillAcrobatics": "Acrobatics", - "GURPS.skillJudo": "Judo", - "__Slam Calculator__": "=========", - "GURPS.slamAOAStrong": "All-Out Attack (Strong)", - "GURPS.slamCalculator": "Slam Calculator", - "GURPS.slamForShieldDB": "Shield DB (Shield Rush)", - "GURPS.slamRelativeVelocity": "Relative Velocity", - "GURPS.slams": "slams", - "GURPS.slamShieldDB": "Shield DB", - "GURPS.slamVelocity": "Hexes moved", - "GURPS.slamDFRPGRules": "Use the Dungeon Fantasy RPG rules", - "__Status/Conditions__": "=========", - "GURPS.STATUSAgony": "Agony", - "GURPS.STATUSAim": "Aiming", - "GURPS.STATUSBleed": "Bleeding", - "GURPS.STATUSBlind": "Blinded", - "GURPS.STATUSBurn": "Burning", - "GURPS.STATUSCoughing": "Coughing", - "GURPS.STATUSCounter": "Counter", - "GURPS.STATUSCrouch": "Crouching", - "GURPS.STATUSDeaf": "Deafened", - "GURPS.STATUSDisable": "Disabled", - "GURPS.STATUSDrowsy": "Drowsy", - "GURPS.STATUSDrunk": "Drunk", - "GURPS.STATUSEuphoria": "Euphoria", - "GURPS.STATUSExhausted": "Fatigued", - "GURPS.STATUSFall": "Falling", - "GURPS.STATUSFly": "Flying", - "GURPS.STATUSGrapple": "Grappled", - "GURPS.STATUSKneel": "Kneeling", - "GURPS.STATUSMildPain": "Mild Pain", - "GURPS.STATUSModeratePain": "Moderate Pain", - "GURPS.STATUSNauseated": "Nauseated", - "GURPS.STATUSPin": "Pinned", - "GURPS.STATUSPoison": "Poisoned", - "GURPS.STATUSReeling": "Reeling", - "GURPS.STATUSRetching": "Retching", - "GURPS.STATUSSeverePain": "Severe Pain", - "GURPS.STATUSSilence": "Silenced", - "GURPS.STATUSSit": "Sitting", - "GURPS.STATUSSleep": "Sleeping", - "GURPS.STATUSSprint": "Sprinting", - "GURPS.STATUSStealth": "Sneaking/Stealth", - "GURPS.StatusStunnedMental": "Mental Stun", - "GURPS.STATUSSuffocate": "Suffocating", - "GURPS.STATUSTerriblePain": "Terrible Pain", - "GURPS.STATUSTipsy": "Tipsy", - "GURPS.STATUSWait": "Waiting", - "GURPS.STATUSBad+1": "+1 Basic Abstract Difficulty", - "GURPS.STATUSBad+2": "+2 Basic Abstract Difficulty", - "GURPS.STATUSBad+3": "+3 Basic Abstract Difficulty", - "GURPS.STATUSBad+4": "+4 Basic Abstract Difficulty", - "GURPS.STATUSBad+5": "+5 Basic Abstract Difficulty", - "GURPS.STATUSBad-1": "-1 Basic Abstract Difficulty", - "GURPS.STATUSBad-2": "-2 Basic Abstract Difficulty", - "GURPS.STATUSBad-3": "-3 Basic Abstract Difficulty", - "GURPS.STATUSBad-4": "-4 Basic Abstract Difficulty", - "GURPS.STATUSBad-5": "-5 Basic Abstract Difficulty", - "GURPS.STATUSDisarmed": "Disarmed", - "__Maneuvers__": "=========", - "GURPS.maneuver": "Maneuver", - "GURPS.maneuverDoNothing": "Do Nothing", - "GURPS.maneuverMove": "Move", - "GURPS.maneuverAim": "Aim", - "GURPS.maneuverCommittedAim": "Committed Aim", - "GURPS.maneuverAllOutAim": "All-out Aim", - "GURPS.maneuverChangePosture": "Change Posture", - "GURPS.maneuverEvaluate": "Evaluate", - "GURPS.maneuverAttack": "Attack", - "GURPS.maneuverFeint": "Feint", - "GURPS.maneuverCommittedAttackRanged": "Committed Attack (Ranged)", - "GURPS.maneuverAllOutAttack": "All-out Attack", - "GURPS.maneuverAllOutAttackDetermined": "All-out Attack (Determined)", - "GURPS.maneuverAllOutAttackDouble": "All-out Attack (Double)", - "GURPS.maneuverAllOutAttackFeint": "All-out Attack (Feint)", - "GURPS.maneuverAllOutAttackStrong": "All-out Attack (Strong)", - "GURPS.maneuverAllOutAttackRanged": "All-out Attack (Ranged Determined)", - "GURPS.maneuverAllOutAttackSuppressFire": "All-out Attack (Suppressing Fire)", - "GURPS.maneuverMoveAttack": "Move and Attack", - "GURPS.maneuverAllOutDefense": "All-out Defense", - "GURPS.maneuverAllOutDefenseDodge": "All-out Defense (Dodge)", - "GURPS.maneuverAllOutDefenseParry": "All-out Defense (Parry)", - "GURPS.maneuverAllOutDefenseBlock": "All-out Defense (Block)", - "GURPS.maneuverAllOutDefenseDouble": "All-out Defense (Double)", - "GURPS.maneuverReady": "Ready", - "GURPS.maneuverConcentrate": "Concentrate", - "GURPS.maneuverWait": "Wait", - "__Import Messages__": "=========", - "GURPS.importCannotImportGCADirectly": "We cannot import a GCA file directly. Please export the file using the 'export to Foundry VTT.gce' script.", - "GURPS.importCannotImportGCSDirectly": "We cannot import a GCS file directly. Please export the file using the 'Foundry VTT' output template.", - "GURPS.importGCA5ImprovedInventoryHandling": "This file was created with an older version of the GCA5 export which does not handle inventory text well.", - "GURPS.importGCA5ImprovedBlock": "This file was created with an older version of the GCA5 export which does not correctly calculate block for melee weapons.", - "GURPS.importCurrentVersions": "Current Versions: '{GCAVersion}' & '{GCSVersion}'.", - "GURPS.importErrorParsingXML": "Error parsing XML: {text}.", - "GURPS.importFantasyGroundUnsupported": "We no longer support the Fantasy Grounds import.", - "GURPS.importFileVersion": "The file version: '{version}'.", - "GURPS.importGCABadBlockForDB": "This file was created with an older version of the GCA Export which incorrectly calculates Block value for items with DB (e.g. Shields).", - "GURPS.importGCANoBodyPlan": "This file was created with an older version of the GCA Export which does not contain the 'Body Plan' attribute. We will try to guess the Body Plan, but we may get it wrong.", - "GURPS.importGCANoHideFlag": "This file was created with an older version of the GCA Export which ignored the 'hide' flag for ads/disads/quirks/perks.", - "GURPS.importGCAChildrenWeights": "This file was created with an older version of the GCA Export which incorrectly calculated the weights for equipment that contain other equipment.", - "GURPS.importGCANoInnateRangedAndParent": "This file was created with an older version of the GCA Export which does not export Innate Ranged attacks and does not contain the 'Parent' Attribute for equipment. You may be missing ranged attacks or equipment may not appear in the correct container.", - "GURPS.importGCANoMeleeIfAlsoRanged": "This file was created with an older version of the GCA Export which may not export a melee attack if it also exists in ranged attacks (e.g. Spears).", - "GURPS.importGCSNoMeleeRangedNotesForSameItem": "This file was created with an older version of the GCS Export which does not export individual Melee and Ranged attack notes created by the same item.", - "GURPS.importGCANoParent": "This file was created with an older version of the GCA Export which does not contain the 'Parent' attributes for Ads/Disads, Skills or Spells.", - "GURPS.importGCANoSanitizedEquipmentPageRefs": "This file was created with an older version of the GCA Export that may incorrectly put ranged attacks in the melee list and does not sanitize equipment page refs.", - "GURPS.importGCANoSanitizeNotes": "This file was created with an older version of the GCA Export which does not sanitize Notes or Ad/Disad names.", - "GURPS.importGCSNoParent": "This file was created with an older version of the GCS Export which does not contain the 'Parent' attributes. Items will not appear in their containers.", - "GURPS.importGCSNoSelfControl": "This file was created with an older version of the GCS Export which does not contain the Self Control rolls for Disadvantages (ex: [CR: 9 Bad Temper]).", - "GURPS.importGCSNoUses": "This file was created with an older version of the GCS Export which does not contain the 'Uses' column for Equipment.", - "GURPS.importGCAAdvMods": "This file was created with an older version of the GCA Export which concatenates Advantage modifiers into the Advantage name, which can create very long Advantage names (and affect the character sheet layout)", - "GURPS.importGCAConditionalModifiers": "This file was created with an older version of the GCA Export that does not export Conditional Modifiers", - "GURPS.importGenericError": "An error occured while importing {name}, {error}:{message}.", - "GURPS.importNoCharacterFormat": "Unable to detect the 'character' format. Most likely you are trying to import the 'npc' format.", - "GURPS.importNoXMLDetected": "No XML detected. Are you importing the correct XML file?", - "GURPS.importTooManyContainers": "You have too many levels of containers. The Foundry import only supports up to 3 levels of sub-containers.", - "GURPS.importSuccessful": "{name} imported successfully.", - "GURPS.importSeeUsersGuide": "Check the Users Guide for details on where to get the latest version.", - "GURPS.importOldGCSFile": "Your character was saved with an older version of GCS, which does not output some required attributes. Update GCS to at least version 4.36, open and save your character file, then try again.", - "GURPS.importNoJSONDetected": "Cannot parse JSON. Your GCS file seems to be corrupted.", - "__System Settings__": "=========", - "GURPS.settingShowReadMe": "Show 'Read Me' on version change", - "GURPS.settingHintShowReadMe": "If checked, the system will display the 'Read Me' file every time a version change is detected.", - "GURPS.settingRangeStrategy": "Combat: Range modifier strategy", - "GURPS.settingHintRangeStrategy": "Sets the formula to use to calculate range penalties.", - "GURPS.settingRangeStrategyStandard": "Size and Speed/Range Table", - "GURPS.settingRangeStrategyRangeBands": "Monster Hunters 2 Range Bands", - "GURPS.settingRangeStrategyTenPenalties": "-1 for every 10 hexes/yards/meters", - "GURPS.settingBasicPDFs": "Basic Set PDF(s)", - "GURPS.settingHintBasicPDFs": "Select 'Combined' or 'Separate' and use the associated PDF codes when configuring PDFoundry. Note: If you select 'Separate', the Basic Set Campaigns PDF should open up to page 340 during the PDFoundry test.", - "GURPS.settingBasicPDFsCombined": "Combined Basic Set (code 'B')", - "GURPS.settingBasicPDFsSeparate": "Separate (Characters, 'B'; Campaigns, 'BX')", - "GURPS.settingImportIgnoreName": "Import: Ignore 'name' attribute", - "GURPS.settingHintImportIgnoreName": "If checked, the system will ignore the 'name' attribute of the Actor during imports. This is useful if the name that you use in Foundry differs from GCA/GCS and you don't want it overwritten on every import.", - "GURPS.settingBlockImport": "Only TRUSTED players may Import", - "GURPS.settingHintBlockImport": "If checked, the 'Import' button will only be displayed on the character sheet if the player permission level is 'Trusted', 'Assistant' or 'GameMaster'", - "GURPS.settingImportHPAndFP": "Import: Current HP and FP", - "GURPS.settingHintImportHPAndFP": "NOTE: Current HP and FP are always read from the file during the initial import.", - "GURPS.settingImportHPAndFPUseFile": "Use the import file's current HP and FP.", - "GURPS.settingImportHPAndFPIgnore": "Ignore the import file's current HP and FP.", - "GURPS.settingImportHPAndFPAsk": "Ask before overwriting during import.", - "GURPS.settingImportBodyPlan": "Import: Body Plan/Hit Locations", - "GURPS.settingImportHintBodyPlan": "NOTE: The Body Plan is always read from the file during the initial import.", - "GURPS.settingImportBodyPlanUseFile": "Use the import file's Body Plan.", - "GURPS.settingImportBodyPlanIgnore": "Ignore the import file's Body Plan.", - "GURPS.settingImportBodyPlanAsk": "Ask before overwriting during import.", - "GURPS.settingShowNavigation": "Actor: Show navigation", - "GURPS.settingHintShowNavigation": "If checked, a navigation footer will be displayed on the full GCS character sheet.", - "GURPS.settingEnhancedInput": "Actor: Enhanced numeric inputs", - "GURPS.settingHintEnhancedInput": "If checked, certain fields (such as FP) will display add and subtract shortcut buttons when they have focus.", - "GURPS.settingCalculateEnc": "Actor: Calculate Encumbrance", - "GURPS.settingHintCalculateEnc": "If checked, the Encumbrance level will be set automatically based on the carried equipment (and you cannot change the Encumbrance level manually). If this is turned off, you can change the Encumbrance level by clicking on the new level.", - "GURPS.settingUseEquipped": "Actor: Weight based on 'Equipped'", - "GURPS.settingHintUseEquipped": "If checked, ONLY 'Equipped' items will be included in the weight calculation. If unchecked, all items in the Equipment list are included in the weight calculation. Uncheck, and the players can use the 'Equipped' flag to indicate they have dropped the item.", - "GURPS.settingFlagUserCreated": "Actor: Display User-created Flag", - "GURPS.settingHintFlagUserCreated": "If checked, a small icon will appear after user created (not imported) equipment and before user created notes.", - "GURPS.settingFlagItems": "Actor: Display Foundry Item Flag", - "GURPS.settingHintFlagItems": "If checked, a small icon will appear after equipment (and features) created from Foundry Items", - "GURPS.settingQtyItems": "Actor: Display QTY/Count saved Flag", - "GURPS.settingHintQtyItems": "If checked, a small icon will appear after equipment where the QTY/Count will be saved during imports", - "GURPS.settingConvertRanged": "Actor: Convert 'x2/x5' range to yards", - "GURPS.settingHintConvertRanged": "If checked, range fields in the form 'xN' or 'xN/xM' will be multiplied by the character's ST to determine the actual range for a thrown weapon. NOTE: This only occurs during import.", - "GURPS.settingShowDiceRoller": "UI: Show 3D6 (next to Modifier Bucket)", - "GURPS.settingHintShowDiceRoller": "If checked, the system will display the dice roller shortcut to the right of the Modifier Bucket. You must reload for this change to take effect.", - "GURPS.settingCombatInitiative": "Combat: Initiative Formula", - "GURPS.settingHintCombatInitiative": "This is the formula used by Foundry to determine turn order in combat. Warning: Only change this if you know what you are doing! We do not parse this for correctness. Set this field blank to reset the formula back to the GURPS Combat Turn Sequence, B362.", - "GURPS.settingDamageRestrictADD": "Damage: Restrict ADD to GM", - "GURPS.settingHintDamageRestrictADD": "If checked, only GMs can view/use the Apply Damage Dialog. Players who drag and drop damage will just receive a message.", - "GURPS.settingDamageSimpleADD": "Damage: Simple ADD", - "GURPS.settingHintDamageSimpleADD": "If checked, only display the 'Directly Apply' option in the Apply Damage Dialog.", - "GURPS.settingDamageLocation": "Damage: Default hit location", - "GURPS.settingHintDamageLocation": "Set the default hit location used to apply damage.", - "GURPS.settingDamageLocationTorso": "Torso", - "GURPS.settingDamageLocationRandom": "Random", - "GURPS.settingDamageAD": "Damage: Armor Divisors", - "GURPS.settingHintDamageAD": "If checked, adjust the target's DR by the armor divisor on the attack.", - "GURPS.settingDamageBluntTrauma": "Damage: Blunt Trauma", - "GURPS.settingHintDamageBluntTrauma": "If checked, use Blunt Trauma rules for calculating damage on flexible armor.", - "GURPS.settingDamageLocationMods": "Damage: Location Wounding Modifiers", - "GURPS.settingHintDamageLocationMods": "If checked, modify Wounding Modifiers based on Hit Location.", - "GURPS.settingDamageMath": "Damage: Show the math", - "GURPS.settingHintDamageMath": "If checked, the 'SHOW THE MATH' section of the damage chat message will be expanded by default. If unchecked, you can click on the 'SHOW THE MATH' title to expand it. NOTE: If this is the last message in the chat log, it may expand below the bottom of the log, and you might need to scroll down to see it.", - "GURPS.settingDamageCondInjury": "Damage: Conditional Injury", - "GURPS.settingHintDamagCondInjury": "From Pyramid #3/120: Conditional Injury removes Hit Points from the game as the basis for wound tracking, and replaces them with an effects based method for injury.", - "GURPS.settingStatusWhisper": "Status Effects: Whisper", - "GURPS.settingHintStatusWhisper": "If checked, Status Effects messages (Shock, Major Wound, etc.) will be sent to the target's owner as a Whisper. Otherwise they will be sent as a Out of Character (OOC) message to everyone.", - "GURPS.settingStatusReeling": "Status Effects: Auto Reeling and Tired", - "GURPS.settingHintStatusReeling": "If checked, Reeling (1/2 move/dodge) and Tired (1/2 move/dodge/ST) will automatically be turned on when the character drops below 1/3 HP and 1/3 FP.", - "GURPS.settingPlayerBlindRoll": "Enable Blind rolls for Players", - "GURPS.settingHintPlayerBlindRoll": "If not checked, holding down the SHIFT key when you are making a roll will make a Self roll (only you can see it, no matter who you are). If checked, when players hold down the SHIFT key, it will make it a Blind Roll instead (GMs still get a Self roll).", - "GURPS.settingPlayerChatPrivate": "Player Chat commands private", - "GURPS.settingHintPlayerChatPrivate": "If checked, most of the chat commands (e.g. /hp, /fp, /qty, etc.) will display as a whisper to the player (instead of an Out Of Character message). If you trust your players, and don't like to see the chat fill up with their chat commands, turn this on.", - "GURPS.settingMookGenerator": "Mook Generator Defaults", - "GURPS.settingLabelMookGenerator": "Mook Generator Default Editor", - "GURPS.settingHintMookGenerator": "Edit the initial values of the Mook Generator", - "GURPS.settingManeuverVisibility": "Maneuver Icon Visibility", - "GURPS.settingHintManeuverVisibility": "Determines who can see a token's maneuver icon.", - "GURPS.settingManeuverNoOne": "No One", - "GURPS.settingManeuverGMOnly": "GM and Owner Only", - "GURPS.settingManeuverEveryone": "Everyone", - "GURPS.settingManeuverDetail": "Maneuver Visibility Details", - "GURPS.settingHintManeuverDetail": "Determines what maneuver is visible to players other than the GM or Owner, if any. 'Full Detail': E.g., show \"All-out Attack (Determined)\" and \"Feint\" exactly as shown. 'No Feint': As 'Full Detail' except Feint shows as \"Attack\". 'General': As 'Full, No Feint' except option is not shown -- e.g., All-out Attack (Strong) shows as \"All-out Attack\". (GM and Owner always see Full Detail.)", - "GURPS.settingManeuverDetailFull": "Full Detail", - "GURPS.settingManeuverDetailNoFeint": "No Feint", - "GURPS.settingManeuverDetailGeneral": "General", - "GURPS.settingAutoIgnoreQty": "Import: Auto save Foundry Qty/Count", - "GURPS.settingHintAutoIgnoreQty": "If checked, this will automatically set the 'Save current QTY/Count on import' flag on a peice of equipment when the user changes the QTY/Count (and it will display the little blue file icon). NOTE: This does not detect changes in 'Uses'. If you need to remember 'Uses' between imports, you will need to manually set the flag for that equipment.", - "GURPS.settingSheetDetail": "Quick Sheet", - "GURPS.settingHintSheetDetail": "Select the character sheet that you want as the 'Quick Sheet'. It will be displayed in the title bar, and the user can click between it and the 'Full (GCS)' sheet", - "GURPS.settingImportEncoding": "Import file encoding", - "GURPS.settingImportHintEncoding": "If you are importing a character and the unicode characters are not displaying correctly, change this setting to UTF-8 encoding.", - "GURPS.settingImportEncodingISO8859": "ISO-8859-1 (default)", - "GURPS.settingImportEncodingUTF8": "UTF-8", - "GURPS.settingRemoveUnequipped": "Actor: Remove Unequipped weapons from Melee and Ranged lists", - "GURPS.settingHintRemoveUnequipped": "If checked, the names of the Melee and Ranged attacks will be compared to the carried equipment list, and if a name match is found, the attack will only be listed if the equipment is Equipped", - "GURPS.settingImportBrowserImporter": "Use non-locally hosted import dialog", - "GURPS.settingImportHintBrowserImporter": "Check this if you are not hosting your Foundry instance locally (you are hosting externally, i.e. Forge). This import dialog can remember the location of your import file during the session (which means that if you import the character again, in the same session, it will not have to bring up the File dialog).", - "GURPS.settingShowChatReeling": "Display Reeling/Tired Status in Chat", - "GURPS.settingHintShowChatReeling": "When checked, changes to any actor's Reeling or Tired status will be displayed as a chat message.", - "GURPS.settingDefaultADDAction": "Set default action for Damage Dialog", - "GURPS.settingHintefaultADDAction": "When set to 'Target' it will choose 'Apply' for Player Characters and 'Apply Quietly' for NPCs.", - "GURPS.settingApplyBasedOnTarget": "'Target'", - "GURPS.settingTokenOverrideRefresh": "Override Token scaling", - "GURPS.settingHintTokenOverrideRefresh": "If \"on\", try to draw tokens to properly fit the hex grid. Overrides Foundry drawing functionality -- turn this off if there's any odd Foundry drawing behavior. Requires reloading the world.", - "__Color Settings__": "=========", - "GURPS.settingColorSheetMenuTitle": "Color Character Sheet", - "GURPS.settingColorSheetMenuHint": "Color Character Sheet Settings", - "GURPS.colorSheetMenuOverride": "Override Colors", - "GURPS.colorSheetMenuCustomColors": "Custom Colors", - "GURPS.colorSheetMenuColorAreas": "Color Areas", - "GURPS.colorSheetMenuAreasAttributesColor": "Attributes Color", - "GURPS.colorSheetMenuAreasAttributesTextColor": "Attributes Text Color", - "GURPS.colorSheetMenuAreasAttributesHoverColor": "Attributes Hover Color", - "GURPS.colorSheetMenuAreasAttributesHoverTextColor": "Attributes Hover Text Color", - "GURPS.colorSheetMenuAreasDodgeColor": "Dodge Color", - "GURPS.colorSheetMenuAreasDodgeTextColor": "Dodge Text Color", - "GURPS.colorSheetMenuAreasDodgeHoverColor": "Dodge Hover Color", - "GURPS.colorSheetMenuAreasDodgeHoverTextColor": "Dodge Hover Text Color", - "GURPS.colorSheetMenuAreasDamageColor": "Damage Color", - "GURPS.colorSheetMenuAreasDamageTextColor": "Damage Text Color", - "GURPS.colorSheetMenuAreasDamageHoverColor": "Damage Hover Color", - "GURPS.colorSheetMenuAreasDamageHoverTextColor": "Damage Hover Text Color", - "GURPS.colorSheetMenuAreasBlockColor": "Block Color", - "GURPS.colorSheetMenuAreasBlockTextColor": "Block Text Color", - "GURPS.colorSheetMenuAreasBlockHoverColor": "Block Hover Color", - "GURPS.colorSheetMenuAreasBlockHoverTextColor": "Block Hover Text Color", - "GURPS.colorSheetMenuAreasParryColor": "Parry Color", - "GURPS.colorSheetMenuAreasParryTextColor": "Parry Text Color", - "GURPS.colorSheetMenuAreasParryHoverColor": "Parry Hover Color", - "GURPS.colorSheetMenuAreasParryHoverTextColor": "Parry Hover Text Color", - "GURPS.colorSheetMenuAreasWeaponsColor": "Weapons Color", - "GURPS.colorSheetMenuAreasWeaponsTextColor": "Weapons Text Color", - "GURPS.colorSheetMenuAreasWeaponsHoverColor": "Weapons Hover Color", - "GURPS.colorSheetMenuAreasWeaponsHoverTextColor": "Weapons Hover Text Color", - "GURPS.colorSheetMenuAreasSkillsColor": "Skills Color", - "GURPS.colorSheetMenuAreasSkillsTextColor": "Skills Text Color", - "GURPS.colorSheetMenuAreasSkillsHoverColor": "Skills Hover Color", - "GURPS.colorSheetMenuAreasSkillsHoverTextColor": "Skills Hover Text Color", - "GURPS.colorSheetMenuAreasSpellsColor": "Spells Color", - "GURPS.colorSheetMenuAreasSpellsTextColor": "Spells Text Color", - "GURPS.colorSheetMenuAreasSpellsHoverColor": "Spells Hover Color", - "GURPS.colorSheetMenuAreasSpellsHoverTextColor": "Spells Hover Text Color", - "GURPS.colorSheetMenuAreasOtfNotesColor": "OtF Notes Color", - "GURPS.colorSheetMenuAreasOtfNotesTextColor": "OtF Notes Text Color", - "GURPS.colorSheetMenuAreasOtfNotesHoverColor": "OtF Notes Hover Color", - "GURPS.colorSheetMenuAreasOtfNotesHoverTextColor": "OtF Notes Hover Text Color", - "GURPS.colorSheetMenuAreasAdsDisadsColor": "Ads/Disads Color", - "GURPS.colorSheetMenuAreasAdsDisadsTextColor": "Ads/Disads Text Color", - "GURPS.colorSheetMenuAreasAdsDisadsHoverColor": "Ads/Disads Hover Color", - "GURPS.colorSheetMenuAreasAdsDisadsHoverTextColor": "Ads/Disads Hover Text Color", - "GURPS.adDisad": "Advantage/Disadvantage", - "GURPS.adDisadQuirkPerk": "Advantage/Disadvantage/Quirk/Perk", - "GURPS.conditionalModifier": "Conditional Modifier", - "GURPS.delete": "Delete", - "GURPS.fromEllipses": "from ...", - "GURPS.moveToOtherEquipment": "Move to Other Equipment", - "GURPS.sortAscending": "Sort Ascending", - "GURPS.sortContentsAscending": "Sort Contents (Ascending)", - "GURPS.sortContentsDescending": "Sort Contents (Descending)", - "GURPS.sortDescending": "Sort Descending", - "GURPS.actions": "Actions", - "GURPS.aiming": "Aiming", - "GURPS.addAdvantage": "Add an Advantage", - "GURPS.addMeleeAttack": "Add a Melee Attack", - "GURPS.addRangedAttack": "Add a Ranged Attack", - "GURPS.addRT": "Add ResourceTracker", - "GURPS.addSkill": "Add a Skill", - "GURPS.addSpell": "Add a Spell", - "GURPS.advantage": "Advantage", - "GURPS.advantages": "Advantages", - "GURPS.advantagesTab": "Advantages and Disadvantages", - "GURPS.aim": "Aim", - "GURPS.allDamage": "ALL DAMAGE", - "GURPS.allOutDefense": "All-Out Defense", - "GURPS.allTheDamage": "ALL THE DAMAGE!!", - "GURPS.applyAllToTarget": "Apply All to {name}", - "GURPS.basic": "Basic", - "GURPS.bluntTrauma": "Blunt Trauma", - "GURPS.bonuses": "Bonuses", - "GURPS.check": "Check", - "GURPS.check1": "Check #1", - "GURPS.check2": "Check #2", - "GURPS.check3": "Check #3", - "GURPS.check4": "Check #4", - "GURPS.clickToEdit": "Click to Edit", - "GURPS.clickToRemove": "click to remove", - "GURPS.collapse": "Collapse", - "GURPS.color": "Color", - "GURPS.combatTab": "Combat", - "GURPS.concentrationCheck": "Concentration check", - "GURPS.condition": "Condition", - "GURPS.conditions": "Conditions", - "GURPS.crippling": "Crippling Injury, ", - "GURPS.current": "Current", - "GURPS.currentdodge": "Dodge", - "GURPS.damageAbove": "Damage above ", - "GURPS.dead": "Dead", - "GURPS.defense": "Defense", - "GURPS.destroyed": "Destroyed", - "GURPS.Dice": "Dice", - "GURPS.during": "During", - "GURPS.dxCheckOrFallApplyProne": "{name}: roll DX or fall!", - "GURPS.dxJudoAcrobaticsCheckToRemainStanding": "Roll [DX, Judo, or Acrobatics] {modifierText} to remain standing.", - "GURPS.effectsNotApplicableDefenses": "Does not apply to Active Defenses or other defensive reactions.", - "GURPS.effectsTemporaryAttributePenalties": "See Temporary Attribute Penalties", - "GURPS.equipmentTab": "Equipment", - "GURPS.equippedblock": "Block", - "GURPS.equippedparry": "Parry", - "GURPS.fail": "Fail", - "GURPS.fallsDownApplyProne": "{name}: falls down!", - "GURPS.for": "for", - "GURPS.forHighPainThreshold": "{mod} for High Pain Threshold", - "GURPS.forLowPainThreshold": "{mod} for Low Pain Threshold", - "GURPS.forPerfectBalance": "{mod} for Perfect Balance", - "GURPS.gameAidUsersGuide": "GURPS 4e Game Aid USERS GUIDE", - "GURPS.groundCreatures": "Ground creatures", - "GURPS.groundCreaturesSuffer": "Ground creatures suffer", - "GURPS.headVitalsHit": "Head or Vitals Hit ", - "GURPS.highPainThresholdNoPenalty": "High Pain Threshold negates penalty", - "GURPS.hpIgnored": " HP ignored.", - "GURPS.htCheck": "Roll HT", - "GURPS.ID": "ID", - "GURPS.itemBonusText": "Enter On-the-Fly 'Bonus' Formulas (one per line) to modify values of attributes, skills, etc.", - "GURPS.itemEditor": "Item Editor", - "GURPS.itemFeatures": "Features", - "GURPS.itemImport": "Import Equipment Library", - "GURPS.characterImport": "Import Character Library", - "GURPS.knockback": "Knockback, {amount} {unit}", - "GURPS.knockbackCheck": "{name}: roll {dx}, {acrobatics}, or {judo} or fall!", - "GURPS.level": "Level", - "GURPS.lighting": "Lighting", - "GURPS.location": "Location", - "GURPS.lowPainThresholdDoubles": "Low Pain Threshold doubles penalty", - "GURPS.majorWound": "Major Wound", - "GURPS.majorWoundEffect": " to avoid Stun/Knockdown.", - "GURPS.majorWoundEffectLabel": "{name}: roll {htCheck} to avoid Stun/Knockdown.", - "GURPS.max": "Max", - "GURPS.maximum": "Maximum", - "GURPS.melee": "Melee", - "GURPS.meleeAttack": "Melee Attack", - "GURPS.meters": " meters", - "GURPS.minimum": "Minimum", - "GURPS.minimumDamageRule": "* — Minimum damage rule applied.", - "GURPS.name": "Name", - "GURPS.noModifier": "No Modifier", - "GURPS.normal": "Normal", - "GURPS.notAffected": "{name} is not affected.", - "GURPS.notes": "Notes", - "GURPS.ok": "OK", - "GURPS.overridden": "overridden", - "GURPS.pass": "Pass", - "GURPS.pdfPageReference": "Page Ref", - "GURPS.pdfRef": "Ref", - "GURPS.pointDamage": "{damage} point of damage", - "GURPS.pointsDamage": "{damage} points of damage.", - "GURPS.quantity": "Quantity", - "GURPS.ranged": "Ranged", - "GURPS.rangedAttack": "Ranged Attack", - "GURPS.rateOfFire": "Rate of Fire", - "GURPS.reaction": "Reaction", - "GURPS.reference": "Reference", - "GURPS.removeItem": "Remove Item", - "GURPS.resolve": "Resolve", - "GURPS.resource": "Resource", - "GURPS.roll": "Roll", - "GURPS.rolled": "Rolled", - "GURPS.rollForMe": "Roll for me", - "GURPS.selectToken": "Select Token", - "GURPS.shock": "Shock", - "GURPS.shockPenalty": "Penalty (–{amount}) to DX and IQ.", - "GURPS.shockPenaltyNextTurnOnly": "{name}: –{modifier} to DX and IQ for next turn only.", - "GURPS.showQuestion": "Show?", - "GURPS.skill": "Skill", - "GURPS.skillLevel": "Skill Level", - "GURPS.skillsTab": "Skills", - "GURPS.spell": "Spell", - "GURPS.spellsTab": "Spells", - "GURPS.statsTab": "Stats", - "GURPS.suffersAMajorWound": "{name} suffers a Major Wound", - "GURPS.suffersHeadVitalsWound": "{name} was struck in the {location} with a Shock penalty.", - "GURPS.suffersKnockback": "{name} suffers Knockback {classStart}([PDF:{pdfref}]){classEnd} of {yards} {unit}.", - "GURPS.swimmerFlyer": "Swimmer / Flyer", - "GURPS.swimmersOrFlyersSuffer": "Swimmers Flyers", - "GURPS.target": "Target", - "GURPS.targeting": "Targeting {name}", - "GURPS.noTargetSelected": "No Target selected", - "GURPS.tired": "Tired", - "GURPS.toAllDXBasedRolls": "to all DX-based rolls", - "GURPS.TransferTo": "Transfer to", - "GURPS.unconscious": "Unconscious", - "GURPS.update": "Update", - "GURPS.warning": "WARNING", - "GURPS.yard": "yard", - "GURPS.yards": "yards", - "GURPS.addTracker": "Add Resource Tracker at the end", - "GURPS.edit": "Edit", - "GURPS.moveToCarriedEquipment": "Move to Carried Equipment", - "GURPS.dragSameContainer": "Cannot add the object to this container, as it is already inside it.", - "GURPS.dropResolve": "Where do you want to drop this object?", - "GURPS.dropBefore": "Before the target", - "GURPS.dropInside": "Inside the target", - "GURPS.moveNone": "None ({reason})", - "GURPS.moveConstant": "{value} {unit}/sec ({reason})", - "GURPS.moveStep": "Step ({reason})", - "GURPS.moveTwoSteps": "Step or two steps ({reason})", - "GURPS.moveOneThird": "×1/3 ({reason})", - "GURPS.moveTwoThirds": "×2/3 ({reason})", - "GURPS.moveHalf": "Half ({reason})", - "GURPS.moveFull": "Full", - "GURPS.setManeuver": "Set Maneuver", - "GURPS.abbrevPoints": "Pts", - "GURPS.abbrevReference": "Ref", - "GURPS.attributesSecondary": "Secondary Attributes", - "GURPS.attributesPrimary": "Basic Attributes", - "GURPS.injury": "Injury", - "GURPS.serverity": "Severity", - "GURPS.days": "Days", - "GURPS.none": "None", - "GURPS.equipmentCarried": "Carried Equipment", - "GURPS.equipmentOther": "Other Equipment", - "GURPS.equipmentUserCreated": "User-created", - "GURPS.equipmentIgnoreQtyImport": "Importing does not update quantity.", - "GURPS.showFlightMove": "Show Move/Flight Move", - "GURPS.rt": "RT", - "GURPS.thresholds": "Thresholds", - "GURPS.conditionalMods": "Conditional Modifiers", - "GURPS.ignoreBodyPlan": "Ignore Imported Body Plan", - "GURPS.abbrevRef": "Ref", - "GURPS.noteBlank": "This note was intentionally left blank.", - "GURPS.pointsTotal": "Total Points", - "GURPS.severities": "Severities", - "GURPS.addAdjustedForDamageType": "‡ - Adjusted for Damage Modifier", - "GURPS.addDamageModifier": "Damage Modifier", - "GURPS.reset": "Clear Configuration", - "GURPS.resolveDiceRoll": "What Did You Roll?", - "GURPS.settingUsePhysicalDice": "Use Physical Dice", - "GURPS.settingHintUsePhysicalDice": "If enabled, TRUSTED players will be prompted for all die roll values. This allows players to roll physical dice and enter the results into Foundry.", - "GURPS.settingUseQuintessence": "Use Quintessence", - "GURPS.settingHintUseQuintessence": "If enabled, adds the Quintessence attribute, and Quintessence Points become available to use as a Resource Tracker.", - "GURPS.STATUSStanding": "Standing", - "GURPS.STATUSCrawling": "Crawling", - "GURPS.STATUSProne": "Lying Down", - "GURPS.effectHintBlind": "-6 to hit if accustomed to being blind; Hearing -2 success lowers the to hit penalty to -4.", - "GURPS.effectChatModifiedToHit": "{displayName} is
[{modifier}]", - "GURPS.effectChatRangedModifier": "{displayName} is
[-2 to be hit with ranged combat ({posture})].", - "GURPS.tokenToolsTitle": "Open Effect Modifier Popup", - "GURPS.effectModNoTokenSelected": "No token selected", - "GURPS.effectModifierPopout": "Effect Modifiers", - "GURPS.targetedModifiers": "Targeted Modifiers", - "GURPS.settingActiveEffects": "Turn on Active Effects", - "GURPS.targetModifiers": "Target:", - "GURPS.settingHintActiveEffects": "Allow the GM to create and apply Active Effects", - "GURPS.CR0": "CR: N/A (Cannot Resist)", - "GURPS.CR6": "CR: 6 (Resist Rarely)", - "GURPS.CR9": "CR: 9 (Resist Fairly Often)", - "GURPS.CR12": "CR: 12 (Resist Quite Often)", - "GURPS.CR15": "CR: 15 (Resist Almost All The Time)", - "GURPS.modifiersBlindAttack": "-10 to hit (Blind)", - "GURPS.modifiersBlindDefend": "-4 on Active Defenses (Blind)", - "GURPS.moveModeGround": "Ground", - "GURPS.moveModeAir": "Air", - "GURPS.moveModeWater": "Water", - "GURPS.moveModeSpace": "Space", - "GURPS.moveModeOther": "Other...", - "GURPS.moveModeType": "Move Type", - "GURPS.moveModeValue": "Yards/Turn", - "GURPS.effectsTermination": "Termination Condition (OtF)", - "GURPS.effectsEffect": "Effect", - "GURPS.default": "Default", - "GURPS.conditionsCombatMove": "Combat Move", - "GURPS.activeEffects": "Active Effects", - "GURPS.quicknotes": "Quick Notes", - "GURPS.language": "Language", - "GURPS.spoken": "Spoken", - "GURPS.written": "Written", - "GURPS.pdfOffset": "Page Offset", - "GURPS.pdfCode": "PDF Book Code", - "GURPS.noViableSkill": "This character does not have a viable skill (effective level 3 or higher) that can be rolled", - "__Rolling__": "=========", - "GURPS.rollVs": "Roll vs", - "GURPS.rollNewTarget": "New Target: ({target})", - "GURPS.rollCriticalSuccess": "Critical Success!", - "GURPS.rollSuccess": "Success!", - "GURPS.rollFailure": "Failure!", - "GURPS.rollCriticalFailure": "Critical Failure!", - "GURPS.rollFail17": "17 & 18 always fail.", - "GURPS.rollJustMadeIt": "Just made it", - "GURPS.rollMadeBy": "Made it by {margin}.", - "GURPS.rollMissedBy": "Missed it by {margin}.", - "GURPS.rollTotalHits": "Total possible hits ({link})
due to RoF ({rof}) & Rcl ({rcl}) is {rofrcl}.", - "GURPS.rollTotal": "Rolled ({rolls}) = {rtotal}." + "GURPS.title": "GURPS", + "GURPS.changelog": "README", + "GURPS.DontShowAgain": "Don't show README again", + "GURPS.copyrightGURPS": "GURPS is a trademark of Steve Jackson Games, and its rules and art are copyrighted by Steve Jackson Games. All rights are reserved by Steve Jackson Games. This game aid is the original creation of Chris Normand/Nose66 and is released for free distribution, and not for resale, under the permissions granted by http://www.sjgames.com/general/online_policy.html", + "GURPS.copyrightGCS": "GCS is copyrighted 1998-2020 by Richard A. Wilkes. All rights reserved ", + "__Char Sheet__": "=========", + "GURPS.portrait": "Portrait", + "__Character Sheet Identity__": "=========", + "GURPS.identity": "Identity", + "GURPS.identityName": "Name", + "GURPS.identityPlayer": "Player", + "GURPS.identityTitle": "Title", + "__Character Sheet Miscellaneous__": "=========", + "GURPS.miscellaneous": "Miscellaneous", + "GURPS.miscellaneousCreated": "Created", + "GURPS.miscellaneousModified": "Modified", + "GURPS.miscellaneousOptions": "Options", + "__Character Description__": "=========", + "GURPS.description": "Description", + "GURPS.descriptionAge": "Age", + "GURPS.descriptionAppearance": "Appearance", + "GURPS.descriptionBirthday": "Birthday", + "GURPS.descriptionBodyPlan": "Body Plan", + "GURPS.descriptionEyes": "Eyes", + "GURPS.descriptionGender": "Gender", + "GURPS.descriptionHair": "Hair", + "GURPS.descriptionHand": "Hand", + "GURPS.descriptionHeight": "Height", + "GURPS.descriptionReligion": "Religion", + "GURPS.descriptionSizeModifier": "Size Modifier (SM)", + "GURPS.descriptionSkin": "Skin", + "GURPS.descriptionTechLevel": "Tech Level (TL)", + "GURPS.weight": "Weight", + "GURPS.share": "Share", + "__Character Points__": "=========", + "GURPS.point": "Point", + "GURPS.points": "Points", + "GURPS.pointsAdvantages": "Advantages", + "GURPS.pointsAttributes": "Attributes", + "GURPS.pointsDisadvantages": "Disadvantages", + "GURPS.pointsQuirks": "Quirks", + "GURPS.pointsRace": "Race", + "GURPS.pointsSkills": "Skills", + "GURPS.pointsSpells": "Spells", + "GURPS.pointsUnspent": "Unspent", + "__Character Attributes__": "=========", + "GURPS.attributes": "Attributes", + "GURPS.attributesDX": "DX", + "GURPS.attributesDXNAME": "Dexterity", + "GURPS.attributesFPNAME": "Fatigue", + "GURPS.attributesHPNAME": "Hit Points", + "GURPS.attributesHT": "HT", + "GURPS.attributesHTNAME": "Health", + "GURPS.attributesIQ": "IQ", + "GURPS.attributesIQNAME": "Intelligence", + "GURPS.attributesPER": "Per", + "GURPS.attributesPERNAME": "Perception", + "GURPS.attributesST": "ST", + "GURPS.attributesSTNAME": "Strength", + "GURPS.attributesWILL": "Will", + "GURPS.attributesWILLNAME": "Will", + "GURPS.basicmove": "Basic Move", + "GURPS.basicspeed": "Basic Speed", + "GURPS.speed": "Speed", + "GURPS.FP": "FP", + "GURPS.frightcheck": "Fright Check", + "GURPS.hearing": "Hearing", + "GURPS.HP": "HP", + "GURPS.swing": "Basic Swing", + "GURPS.tastesmell": "Taste/Smell", + "GURPS.thrust": "Basic Thrust", + "GURPS.touch": "Touch", + "GURPS.vision": "Vision", + "GURPS.attributesQN": "QN", + "GURPS.attributesQNNAME": "Quintessence", + "__ Character AddsDisadsPerksQuirks__": "=========", + "GURPS.advDisadvPerkQuirks": "Advantages, Disadvantages, Perks & Quirks", + "GURPS.highPainThreshold": "High Pain Threshold", + "GURPS.lowPainThreshold": "Low Pain Threshold", + "GURPS.perfectBalance": "Perfect Balance", + "__ Character Skills__": "=========", + "GURPS.rsl": "RSL", + "GURPS.SkillDXA": "DX/A", + "GURPS.SkillDXE": "DX/E", + "GURPS.SkillDXH": "DX/H", + "GURPS.SkillDXVH": "DX/VH", + "GURPS.SkillHTA": "HT/A", + "GURPS.SkillHTE": "HT/E", + "GURPS.SkillHTH": "HT/H", + "GURPS.SkillHTVH": "HT/VH", + "GURPS.SkillQNA": "QN/A", + "GURPS.SkillQNE": "QN/E", + "GURPS.SkillQNH": "QN/H", + "GURPS.SkillQNVH": "QN/VH", + "GURPS.SkillIQA": "IQ/A", + "GURPS.SkillIQE": "IQ/E", + "GURPS.SkillIQH": "IQ/H", + "GURPS.SkillIQVH": "IQ/VH", + "GURPS.SkillPerA": "Per/A", + "GURPS.SkillPerE": "Per/E", + "GURPS.SkillPerH": "Per/H", + "GURPS.SkillPerVH": "Per/VH", + "GURPS.skills": "Skills", + "GURPS.SkillWillA": "Will/A", + "GURPS.SkillWillE": "Will/E", + "GURPS.SkillWillH": "Will/H", + "GURPS.SkillWillVH": "Will/VH", + "GURPS.sl": "SL", + "__Character Spells__": "=========", + "GURPS.spellClass": "Class", + "GURPS.spellCollege": "College", + "GURPS.spellCost": "Cost", + "GURPS.spellDuration": "Duration", + "GURPS.spellMaintain": "Maintain", + "GURPS.spells": "Spells", + "GURPS.spellTime": "Time", + "GURPS.spellResist": "Resisted By", + "GURPS.spellDifficulty": "Difficulty", + "__Character Equipment__": "=========", + "GURPS.equipment": "Equipment", + "GURPS.otherEquipment": "Other Equipment", + "GURPS.equipmentEquipped": "E", + "GURPS.equipmentQuantity": "Qty", + "GURPS.equipmentUses": "Uses", + "GURPS.equipmentCost": "Cost", + "GURPS.equipmentMaxUses": "Max Uses", + "GURPS.equipmentTechlevel": "Tech Level", + "GURPS.equipmentFoundryItem": "Foundry Item", + "__Character Encumbrance/Lift__": "=========", + "GURPS.basicLift": "Basic Lift", + "GURPS.carryOnBack": "Carry on Back", + "GURPS.dodge": "Dodge", + "GURPS.encumbranceMoveDodge": "Encumbrance, Move & Dodge", + "GURPS.liftingAndMovingThings": "Lifting & Moving Things", + "GURPS.maxload": "Max Load", + "GURPS.move": "Move", + "GURPS.oneHandLift": "One-Hand Lift", + "GURPS.runningShoveAndKnockOver": "Running Shove & Knock Over", + "GURPS.shiftSlightly": "Shift Slightly", + "GURPS.shoveAndKnockOver": "Shove & Knock Over", + "GURPS.twoHandLift": "Two-Hand Lift", + "__Character Weapons__": "=========", + "GURPS.acc": "Acc", + "GURPS.block": "Block", + "GURPS.blockbonus": "Block bonus", + "GURPS.bulk": "Bulk", + "GURPS.damage": "Damage", + "GURPS.meleeWeapons": "Melee Weapons", + "GURPS.parry": "Parry", + "GURPS.parrybonus": "Parry bonus", + "GURPS.range": "Range", + "GURPS.rangedWeapons": "Ranged Weapons", + "GURPS.rcl": "Rcl", + "GURPS.reach": "Reach", + "GURPS.rof": "RoF", + "GURPS.shots": "Shots", + "GURPS.usage": "Usage", + "__Apply Damage Dialog__": "=========", + "GURPS.addAbbrev": "Abbrev", + "GURPS.addAdditionalStackingModifier": "Additional modifier", + "GURPS.addAdjustedForHitLocation": "* - Adjusted for hit location", + "GURPS.addAdjustedForInjuryTolerance": "† - Adjusted for Injury Tolerance", + "GURPS.addApply": "Apply", + "GURPS.addApplyAndKeep": "Apply/Keep Open", + "GURPS.addApplyDamageDialog": "Apply Damage Dialog", + "GURPS.addApplyDamageOptions": "APPLY DAMAGE OPTIONS", + "GURPS.addApplyInjury": "Apply Injury", + "GURPS.addApplyInjuryAndKeep": "Apply Injury/Keep Open", + "GURPS.addApplyInjuryQuietly": "Apply Injury (Quietly)", + "GURPS.addApplyInjuryQuietlyAndKeep": "Apply Injury (Quietly)/Keep Open", + "GURPS.addApplyMultipleTimes": "Apply multiple times", + "GURPS.addApplyOptionsToAll": "These options apply to all damage", + "GURPS.addApplyQuietly": "Apply (Quietly)", + "GURPS.addApplyQuietlyAndKeep": "Apply (Quietly)/Keep Open", + "GURPS.addApplyTo": "Apply to", + "GURPS.addArmorDivisor": "Armor Divisor", + "GURPS.addBasicDamage": "Basic Damage", + "GURPS.addCalculationAndResults": "Calculation & Results", + "GURPS.addDamageReduction": "Damage Reduction", + "GURPS.addDamageType": "Damage Type", + "GURPS.addDiffuseMax": "Diffuse, max", + "GURPS.addDirectlyApply": "DIRECTLY APPLY", + "GURPS.addEnterModifier": "Enter Modifier", + "GURPS.addExplosion": "Explosion", + "GURPS.addExplosionHex": "{hex} hex from center", + "GURPS.addExplosionHexes": "{hex} hexes from center", + "GURPS.addFlexibleArmor": "Flexible Armor", + "GURPS.addHardenedDRLevel": "Hardened DR Level", + "GURPS.addHitLocationAndDR": "Hit Location & DR", + "GURPS.addHitLocationWoundModifiers": "Hit Location Wound Modifiers", + "GURPS.addInjury": "Injury", + "GURPS.addInjuryTolerance": "Injury Tolerance", + "GURPS.addInjuryToleranceDiffuse": "Diffuse", + "GURPS.addInjuryToleranceHomogenous": "Homogenous", + "GURPS.addInjuryToleranceUnliving": "Unliving", + "GURPS.addLargeAreaInjury": "Large-Area Injury", + "GURPS.addLocationMax": "Location Max", + "GURPS.addOverrideDR": "Override DR for Location", + "GURPS.addPenetrating": "Penetrating", + "GURPS.addRangedHalfDamage": "Ranged, Half Damage (1/2D)", + "GURPS.addRangedHalfDamageShort": "Ranged (1/2D)", + "GURPS.addShotgunCloseRange": "Shotgun, Extremely Close", + "GURPS.addShotgunDamage": "Shotgun Damage", + "GURPS.addShotgunRofMultiplier": "RoF Multiplier", + "GURPS.addSingleRollSelected": "Single damage roll selected", + "GURPS.addSpecialCombatSituations": "Special Situations", + "GURPS.addTacticalRules": "Tactical Rules", + "GURPS.addTacticalRulesDefaults": "Use systems settings to set defaults", + "GURPS.addTitle": "Apply {basic} point(s) of [{damage}] damage to {name}", + "GURPS.addTitleConcat0": "Apply", + "GURPS.addTitleConcat01": "point of ", + "GURPS.addTitleConcat0s": "points of ", + "GURPS.addTitleConcat1": "damage to {name}", + "GURPS.addTypeAndWoundingModifiers": "Type & Wounding Modifiers", + "GURPS.addVulnerability": "Vulnerability", + "GURPS.addWHard": "w/Hard", + "__Body Plan__": "=========", + "GURPS.BODYPLANarachnoid": "Arachnoid", + "GURPS.BODYPLANavian": "Avian", + "GURPS.BODYPLANcancroid": "Cancroid", + "GURPS.BODYPLANcentaur": "Centaur", + "GURPS.BODYPLANhexapod": "Hexapod", + "GURPS.BODYPLANhexapodWinged": "Hexapod, Winged", + "GURPS.BODYPLANhumanoid expanded": "Humanoid, Expanded (GCA)", + "GURPS.BODYPLANhumanoid": "Humanoid", + "GURPS.BODYPLANichthyoid": "Ichthyoid", + "GURPS.BODYPLANoctopod": "Octopod", + "GURPS.BODYPLANquadruped": "Quadruped", + "GURPS.BODYPLANquadrupedWinged": "Quadruped, Winged", + "GURPS.BODYPLANscorpion": "Scorpion", + "GURPS.BODYPLANsnakeman": "Snakeman", + "GURPS.BODYPLANsquid": "Squid", + "GURPS.BODYPLANvermiform": "Vermiform", + "GURPS.BODYPLANvermiformWinged": "Serpent, Winged", + "GURPS.BODYPLANwinged humanoid": "Humanoid, Winged", + "__Chat Messages__": "=========", + "GURPS.chatClearing": "Clearing", + "GURPS.chatClearingLastActor": "Clearing Last Actor", + "GURPS.chatDamageResultEnd": "to the {location}", + "GURPS.chatDamageResultMiddle": "of {type} damage", + "GURPS.chatDamageResultShowMath": "Show the math", + "GURPS.chatDamageResultStart": "injures {defender} for {injury}", + "GURPS.chatDoesNotHaveEnough": "does not have enough 'USES'", + "GURPS.chatExceededMax": "Exceeded MAX", + "GURPS.chatExceededMaxUses": "Exceeded 'MAX USES'", + "GURPS.chatFixedDamage": "[{dice} {damageTypeText}] damage.", + "GURPS.chatLightSource": "Pick the light source the selected token is holding.", + "GURPS.chatMoreThanOneActor": "More than one Actor found matching", + "GURPS.chatMoreThanOneToken": "More than one Token found matching", + "GURPS.chatMultipleOwnedFound": "You own more than one token in this scene. You can either select one and retry this command without the '@self' keyword, or use the ':name' option.", + "GURPS.chatMustBeACheck": "The On-the-Fly formula must be some kind of check", + "GURPS.chatNoActorFound": "No Actor/Token found matching", + "GURPS.chatNoEquipmentMatched": "No equipment matched", + "GURPS.chatNoResourceTracker": "No Resource Tracker matched", + "GURPS.chatNoStatusMatched": "No status matched", + "GURPS.chatNoOwnedTokenFound": "You do not own any tokens in this scene.", + "GURPS.chatNoTokens": "Your character does not have any tokens. We require a token to set statuses", + "GURPS.chatQty": "QTY", + "GURPS.chatQtySetTo": "QTY set to", + "GURPS.chatResetTo": "reset to", + "GURPS.chatResourceTracker": "Resource Tracker", + "GURPS.chatResultBelowZero": "Result below zero", + "GURPS.chatRolling": "Rolling [{dice}{desc}]", + "GURPS.chatRollingDamage": "Rolling [{dice} {damageTypeText}] damage{numtimes}.", + "GURPS.chatRollingCR": "Control Roll", + "GURPS.chatSetTo": "set to", + "GURPS.chatSelectSelfOrNameTokens": "You must select tokens, use '{self}', or use ':<token-name>' to apply status effects.", + "GURPS.chatShock": "{name} takes {modifier} points of Shock ", + "GURPS.chatSuffersCripplingInjury": "{name} suffers a crippling injury {classStart}([PDF:{pdfref}]){classEnd} to the location {location}.", + "GURPS.andHalfMove": "and half Move.", + "GURPS.chatToApplyEffects": "to apply status effects", + "GURPS.chatTokenLightPicker": "Token Light Picker", + "GURPS.chatToggling": "Toggling", + "GURPS.chatTurnOnReeling": "{name} is Reeling. Move and Dodge are halved. ([PDF:{pdfref}])", + "GURPS.chatTurnOnTired": "{name} is Tired. Move, Dodge, and ST are halved. ([PDF:{pdfref}])", + "GURPS.chatTurnOffReeling": "{name} is no longer Reeling.", + "GURPS.chatTurnOffTired": "{name} is no longer Tired.", + "GURPS.chatUnableToFindMacro": "Unable to find macro named", + "GURPS.chatUnableToFindManeuver": "Unable to find maneuver named", + "GURPS.chatNotInCombat": "You can only set the Maneuver if the token is in combat", + "GURPS.chatUnrecognizedFormat": "Unrecognized format", + "GURPS.chatUses": "'USES'", + "GURPS.chatUsesIsNaN": "'USES' is not a number", + "GURPS.chatUsesReset": "'USES' reset to 'MAX USES'", + "GURPS.chatUsesSet": "'USES' set to", + "GURPS.chatYouDoNotHaveEnough": "You do not have enough", + "GURPS.chatYouMustBeGM": "You must be a GM to execute this command", + "GURPS.chatYouMustHaveACharacterSelected": "You must have a character selected", + "GURPS.chatYouMustSelectTokens": "You must select tokens (or use", + "GURPS.chatHelpHelp": "/help chat-command OR\n\n?chat-command: to see help for that command", + "GURPS.chatHelpSound": "Play a sound in the background
parameters:\nw: wait seconds before starting sound\nv: volume\n<full path filename>
examples:\n/sound w2.5 /path/filename\n/sound v0.6 /path/filename\n/sound w3 v2 /path/filename", + "GURPS.chatHelpW": "Whisper to players or the owners of the selected tokens
parameters:\n<[player names]>\n@: whisper to the owners of the selected tokens\n
examples:\n/w [Chris] msg sent to Player Chris\n/w @ msg sent to owners of selected tokens", + "GURPS.chatHelpWait": "Wait X milliseconds before executing the next chat command
parameters:\nX: the number of milliseconds to wait\n
examples:\n/wait 500", + "GURPS.chatHelpRa": "Roll Against (or Private Roll Against)
parameters:\nX: Skill level to roll against\nSkillname-X: Roll against X, but display 'Skillname' instead of 'Default'\n
examples:\n/ra 12\n.ra 13\n/pra 11\n.pra 10\n/ra Sneak-12\n.ra Brawling-13\n/pra Trap-11\n.pra FastDraw-10", + "GURPS.chatHelpFpHp": "Apply formula to FP or HP of selected characters
parameters:\n<formula>\nreset: Reset FP or HP back to starting value
examples:\n/fp +1\n/hp -1\n/fp +1d\n/hp +1d-3!\n/fp reset\n", + "GURPS.chatHelpSelect": "Select token(s)
parameters:\n<character name (may use '*')>\n@self: select the token of the current character\n!:select across all scenes, not just current
examples:\n/select Bog\n/select @self\n/select Bog !", + "GURPS.chatHelpUses": "Modify the USES column of equipment
parameters:\n<formula>\n<equipment>\no:<equipment>: only search 'other' list\nreset: set USES to MAX_USES
examples:\n/uses +1 equipment\n/uses -2 equipment\n/uses =20 equipment\n/uses +1 o:equipment\n/uses reset equipment", + "GURPS.chatHelpQty": "Modify the QTY column of equipment
parameters:\n<formula>\n<equipment>\no:<equipment>: only search 'other' list
examples:\n/qty +1 equipment\n/qty -2 equipment\n/qty =20 equipment\n/qty +1 o:equipment", + "GURPS.chatHelpLight": "Set token's light level
parameters:\nnone|off: turn off light\nX: dim light radius\nY: bright light radius\nZ: broadcast angle of light \n#RRGGBB: color of light\nW: color intensity (0.0-1.0)\n<anim>: animation pattern (torch, pulse, chroma, wave, fog, sunburst, dome, emanation, hexa, ghost, energy, roiling, hole\nSPEED: speed of animation (1-10)\nINT: intensity of animation (1-10)
examples:\n/li 6 2\n/li 8 3 90\n/li 6 2 #ff0000\n/li 6 2 #ff1111 0.5\n/li 6 2 torch\n/li 8 4 90 #ff7777 0.5 pulse 5 5\nhttps://foundryvtt.com/article/lighting/", + "GURPS.chatHelpTracker": "Modify the Resource Tracker
command format:\n/tr0-3\n/tracker0-3\n/resource0-3\n/rt0-3\n/tr(name)\n/tracker(name)\n/resource(name)\n/rt(name)
parameters:\n<formula>\nreset: reset Tracker to starting value
examples:\n/tr0 +1\n/tr0 -2\n/tracker1 =20\n/tr(arrows) +1\n/resource(rounds) reset", + "GURPS.chatHelpStatus": "Set token's effects status
parameters:\ntoggle|t: toggle the status\non|+|set: turn on the status\noff|-|unset: turn off the status\nclear: remove all statuses\n@self OR :tokenname\nlist: display all status names\n{JSON data}: optional 'duration.combat' data
examples:\n/st on prone :Bog\n/st - shock1 @self\n/st list", + "GURPS.chatHelpRemote": "Execute an On-the-Fly formula remotely
parameters:\n[OtF]: On-the-Fly formula\n<player names>|blank: list of player names (or blank to send to all players)
examples:\n/rem [‏PER] Chris\n/rem [‏ST+2]", + "GURPS.chatHelpEveryone": "Apply formula to FP or HP of all player characters or roll On-the-Fly formula locally against all player characters
parameters:\nfp <formula>\nhp <formula>\n [OtF]: execute OtF (locally) for all player characters\nfp reset: Reset FP back to starting values\nhp reset: Reset HP back to starting values
examples:\n/ev fp +1\n/ev hp -1\n/ev fp +1d\n/ev hp +1d-3!\n/ev fp reset\n/ev [‏PER]", + "GURPS.chatHelpAnim": "Play a centered or moving animation.\n
parameters (for both)\nlist: display a list of available animations\nwX: wait X seconds before displaying animation\n<filename pattern>: pattern can contain *\nXx:Y: repeat animation X times (2x, 3x, etc.) with Y seconds delay between animations\n
parameters for centered animations:\nc: indicates a centered animation\n*X: scale animation by X\n@self: use self as center, instead of target\nThe following options can be added after 'c'\n f: flip the animation on the x axis (left to right)\n m: move the centered animation to the target\n n: do not rotate moving centered animation\n X: degrees to rotate animation\n :Y,Z: offset animation (default 0.5,0.5)\n
examples of centered animations:\n/anim <pattern> c *0.5 3x\n'centered, 1/2 scale, 3 times'\n\n/anim <pattern> cf *2 3x:4\n'centered, flipped (left-right), 2x scale, 3 times with 4 second delay\n\n/anim <pattern> cm\n'centered, move animation from self to target'\n\n/anim <pattern> cmn\n'centered, move animation from self to target, do not rotate'\n\n/anim <pattern> cfm\n'centered, flipped, move animation from self to target'\n\n/anim <pattern> c90\n'centered, rotate 90 degrees'\n\n/anim <pattern> cf180 *.333\n'centered, flipped, rotate 180 degrees, 1/3 scale'\n\n/anim <pattern> cm45\n/anim <pattern> c:0,1\n/anim <pattern> cf:0.5,1\n/anim <pattern> cmn:0.9,1 *2\n
parameters for a moving animations:\n-X: shift left (0.0-1.0) towards the start of the animation\n+X: stretch right (0.0-infinity) towards the destination\n
examples of moving animations:\n/anim <pattern> -0.1 +0.1 2x\n'moving animation, left shift 10%, right stretch 10%, 2 times'", + "GURPS.chatHelpShow": "Show various values from tokens in the scene
parameters:\n-a : sort alphabetically\n-pc : only show PCs\n-npc : only show NPCs\n<Attributes (primary and secondary)>\n<Skill names>\nparry\nblock\nwill\nfright\nper\nvision\nhearing\ntaste\nsmell\nmove\nspeed
examples:\n/show -pc HP FP IQ\n/show -a Stealth PER\n/show per move speed\n/show -npc vision hearing", + "GURPS.chatHelpManeuver": "Set the following maneuvers on the current character. You may use * to match Maneuver names, example: '/man All Out*Double'
", + "GURPS.chatHelpRepeat": "Repeat the following /anim command with a delay of X seconds in between.
examples:\n/repeat /anim 1.2 heal*blue c", + "GURPS.chatWantsToExecute": "Wants to execute {command} on {name},

Is that OK?", + "GURPS.chatSentTo": "Sent command [{cmd}] to {name}", + "__Permissions__": "=========", + "GURPS.cannotDragNonFoundryEqt": "You cannot drag non-Foundry equipment to another character.", + "GURPS.youDoNotHavePermssion": "You do not have permission to do that.", + "__Damage Types__": "=========", + "GURPS.damageAbbrevburn": "burn", + "GURPS.damageAbbrevcor": "cor", + "GURPS.damageAbbrevcr": "cr", + "GURPS.damageAbbrevcut": "cut", + "GURPS.damageAbbrevdmg": "dmg", + "GURPS.damageAbbrevfat": "fat", + "GURPS.damageAbbrevimp": "imp", + "GURPS.damageAbbrevinjury": "injury", + "GURPS.damageAbbrevpi-": "pi-", + "GURPS.damageAbbrevpi": "pi", + "GURPS.damageAbbrevpi+": "pi+", + "GURPS.damageAbbrevpi++": "pi++", + "GURPS.damageAbbrevtox": "tox", + "GURPS.damageAbbrevkb": "kb", + "GURPS.damageTypeBurning": "Burning", + "GURPS.damageTypeCorrosive": "Corrosive", + "GURPS.damageTypeCrushing": "Crushing", + "GURPS.damageTypeCutting": "Cutting", + "GURPS.damageTypeDamage": "Damage", + "GURPS.damageTypeFatigue": "Fatigue", + "GURPS.damageTypeHuge Piercing": "Huge Piercing", + "GURPS.damageTypeImpaling": "Impaling", + "GURPS.damageTypeInjury": "Injury", + "GURPS.damageTypeLarge Piercing": "Large Piercing", + "GURPS.damageTypePiercing": "Piercing", + "GURPS.damageTypeSmall Piercing": "Small Piercing", + "GURPS.damageTypeToxic": "Toxic", + "__Drag Ruler__": "=========", + "GURPS.dragrulerFly": "Fly", + "GURPS.dragrulerSprint": "Sprint", + "GURPS.dragrulerWalk": "Walk", + "__Fantastic Dungeon Grappling__": "=========", + "GURPS.grapplingControlled": "Controlled [-8 DX]", + "GURPS.grapplingControlPoints": "Control Points", + "GURPS.grapplingCPAbbrev": "ctrl", + "GURPS.grapplingGrabbed": "Grabbed [-2 DX]", + "GURPS.grapplingGrappled": "Grappled [-4 DX]", + "GURPS.grapplingPinned": "Pinned [-12 DX]", + "GURPS.grapplingRestrained": "Restrained [-6 DX]", + "GURPS.grapplingUnrestrained": "Unrestrained", + "__Hit Location__": "=========", + "GURPS.hitLocation": "Hit Location", + "GURPS.hitLocationArm 1-2": "Arm 1-2", + "GURPS.hitLocationArm 3-4": "Arm 3-4", + "GURPS.hitLocationArm 5-6": "Arm 5-6", + "GURPS.hitLocationArm 7-8": "Arm 7-8", + "GURPS.hitLocationArm, holding shield": "Arm, holding shield", + "GURPS.hitLocationArm": "Arm", + "GURPS.hitLocationArm*": "Arm", + "GURPS.hitLocationBrain": "Brain", + "GURPS.hitLocationChest": "Chest", + "GURPS.hitLocationChinks in Other": "Chinks in armor (other)", + "GURPS.hitLocationChinks in Torso": "Chinks in armor (torso)", + "GURPS.hitLocationDescChest": "*hit chest", + "GURPS.hitLocationDescFront": "front only", + "GURPS.hitLocationDescHalfDR": "½ DR", + "GURPS.hitLocationDescImp": "imp or pi(any) only", + "GURPS.hitLocationDescLimb": "*hit limb", + "GURPS.hitLocationDescNeck": "*hit neck", + "GURPS.hitLocationDR": "DR", + "GURPS.hitLocationDRWithDivisor": "Effective DR", + "GURPS.hitLocationExtremity": "Extremity", + "GURPS.hitLocationEye": "Eye", + "GURPS.hitLocationEyes": "Eyes", + "GURPS.hitLocationFace, from behind": "Face, from behind", + "GURPS.hitLocationFace": "Face", + "GURPS.hitLocationFin": "Fin", + "GURPS.hitLocationFin*": "Fin", + "GURPS.hitLocationFoot": "Foot", + "GURPS.hitLocationForeleg": "Foreleg", + "GURPS.hitLocationGroin": "Groin", + "GURPS.hitLocationHand": "Hand", + "GURPS.hitLocationHind Leg": "Hind Leg", + "GURPS.hitLocationJaw": "Jaw", + "GURPS.hitLocationLeft Arm, holding shield": "Left Arm, holding shield", + "GURPS.hitLocationLeft Arm": "Left Arm", + "GURPS.hitLocationLeft Leg": "Left Leg", + "GURPS.hitLocationLeg 1-2": "Leg 1-2", + "GURPS.hitLocationLeg 3-4": "Leg 3-4", + "GURPS.hitLocationLeg 5-6": "Leg 5-6", + "GURPS.hitLocationLeg 7-8": "Leg 7-8", + "GURPS.hitLocationLeg": "Leg", + "GURPS.hitLocationLimb Vein/Artery": "Limb Vein/Artery", + "GURPS.hitLocationMid Leg": "Mid Leg", + "GURPS.hitLocationMid Leg*": "Mid Leg", + "GURPS.hitLocationNeck Vein/Artery": "Neck Vein/Artery", + "GURPS.hitLocationNeck": "Neck", + "GURPS.hitLocationNose": "Nose", + "GURPS.hitLocationPenalty": "Penalty", + "GURPS.hitLocationRandom": "Random", + "GURPS.hitLocationRight Arm, holding shield": "Right Arm, holding shield", + "GURPS.hitLocationRight Arm": "Right Arm", + "GURPS.hitLocationRight Leg": "Right Leg", + "GURPS.hitLocationSkull, from behind": "Skull, from behind", + "GURPS.hitLocationSkull": "Skull", + "GURPS.hitLocationTail": "Tail", + "GURPS.hitLocationTorso": "Torso", + "GURPS.hitLocationTorso*": "Torso", + "GURPS.hitLocationVitals, Heart": "Vitals, Heart", + "GURPS.hitLocationVitals": "Vitals", + "GURPS.hitLocationWhere": "Where", + "GURPS.hitLocationWing": "Wing", + "__Modifier Bucket__": "=========", + "GURPS.modifier": "Modifier", + "GURPS.modifierTitle": "Modifiers", + "GURPS.modifierRangeTitle": "Speed / Range", + "GURPS.modifierRange": "for range/speed {range} yds", + "GURPS.modifierRangeMHClose": "Close range (5 yds)", + "GURPS.modifierRangeMHCloseDesc": "Can touch or strike foe", + "GURPS.modifierRangeMHShort": "Short range (20 yds)", + "GURPS.modifierRangeMHShortDesc": "Can talk to foe; pistol or muscle-powered missile range", + "GURPS.modifierRangeMHMedium": "Medium range (100 yds)", + "GURPS.modifierRangeMHMediumDesc": "Can only shout to foe; shotgun or SMG range", + "GURPS.modifierRangeMHLong": "Long range (500 yds)", + "GURPS.modifierRangeMHLongDesc": "Opponent out of earshot; rifle range", + "GURPS.modifierRangeMHExtreme": "Extreme range (500+ yds)", + "GURPS.modifierRangeMHExtremeDesc": "Rival difficult to even see; sniper range", + "GURPS.modifierAddRangeRuler": "Bucket: Add Range Ruler modifier", + "GURPS.modifierAddRangeRulerHint": "If checked, the system will automatically add the last measured Range modifier to the Modifier Bucket.", + "GURPS.modifierAimAllOutAim": "to Aiming rolls (All-Out Aim)", + "GURPS.modifierAimAllOutAimBraced": "to Aiming rolls if braced (All-Out Aim)", + "GURPS.modifierAimCommittedAim": "to Aiming rolls (Committed Aim)", + "GURPS.modifierAimCommittedAimBraced": "to Aiming rolls if braced (Committed Aim)", + "GURPS.modifierAllOutAttackRanged": "to hit (All-Out Attack (Ranged))", + "GURPS.modifierAffliction": "Afflictions", + "GURPS.modifierAfflictionCough": "-3 to DX checks (Coughing)", + "GURPS.modifierAfflictionCoughIQ": "-1 to IQ checks (Coughing)", + "GURPS.modifierAfflictionDrowsy": "-2 to IQ/DX/CR checks (Drowsy)", + "GURPS.modifierAfflictionDrunk": "-2 to IQ/DX checks (Drunk)", + "GURPS.modifierAfflictionDrunkCR": "-4 to CR checks (Drunk)", + "GURPS.modifierAfflictionEuphoria": "-3 to IQ/DX/CR checks (Euphoria)", + "GURPS.modifierAfflictionModerate": "-2 to IQ/DX/CR checks (Moderate Pain)", + "GURPS.modifierAfflictionModerateHPT": "-1 to IQ/DX/CR checks (Moderate Pain w/HPT)", + "GURPS.modifierAfflictionNausea": "-2 to all attributes (Nauseated)", + "GURPS.modifierAfflictionNauseaDef": "-1 to active defenses (Nauseated)", + "GURPS.modifierAfflictionRetch": "-5 to IQ/DX/Per checks (Retching)", + "GURPS.modifierAfflictionSevere": "-4 to IQ/DX/CR checks (Severe Pain)", + "GURPS.modifierAfflictionSevereHPT": "-2 to IQ/DX/CR checks (Severe Pain w/HPT)", + "GURPS.modifierAfflictionTerrible": "-6 to IQ/DX/CR checks (Terrible Pain)", + "GURPS.modifierAfflictionTerribleHPT": "-3 to IQ/DX/CR checks (Terrible Pain w/HPT)", + "GURPS.modifierAfflictionTipsy": "-1 to IQ/DX checks (Tipsy)", + "GURPS.modifierAfflictionTipsyCR": "-2 to CR checks (Tipsy)", + "GURPS.modifierAppearBelow": "They will appear in the Current Modifiers list below.", + "GURPS.modifierAutomatic": "Automatic", + "GURPS.modifierBlindAttack": "-10 to hit (Blind)", + "GURPS.modifierBlindDefend": "-4 to dodge (Blind -- cannot see attacker)", + "GURPS.modifierBlockRetreat": "to Block/Parry (retreat)", + "GURPS.modifierClickToAdd": "Click on modifiers above and to the right to add to your next roll.", + "GURPS.modifierCommittedAttackRanged": "to hit (Committed Attack (Ranged))", + "GURPS.modifierCommon": "Common Modifiers", + "GURPS.modifierCover": "Cover", + "GURPS.modifierCoverBehindFigure": "-4 to hit (Behind same-sized figure)", + "GURPS.modifierCoverCrouch": "-2 to hit (Crouching or Kneeling, no cover)", + "GURPS.modifierCoverHalfExposed": "-3 to hit (Body half exposed)", + "GURPS.modifierCoverHead": "-5 to hit (Head only)", + "GURPS.modifierCoverHeadShoulder": "-4 to hit (Head and shoulders)", + "GURPS.modifierCoverLight": "-2 to hit (Behind light cover)", + "GURPS.modifierCoverPosture": "Cover and Posture", + "GURPS.modifierCoverProne": "-4 to hit (Prone, no cover)", + "GURPS.modifierCoverProneHeadDown": "-7 to hit (Prone, some cover, head down)", + "GURPS.modifierCoverProneHeadUp": "-5 to hit (Prone, some cover, head up)", + "GURPS.modifierCoverThroughHex": "-4 to hit (Firing through occupied hex)", + "GURPS.modifierCurrentEffects": "Current Effects", + "GURPS.modifierCurrentModifiers": "Current Modifiers", + "GURPS.modifierDangerous": "Dangerous", + "GURPS.modifierDeceptiveAttack": "to hit (Deceptive Attack)", + "GURPS.modifierDeterminedAttack": "to hit (Determined Attack)", + "GURPS.modifierDodgeAcrobatic": "to Dodge (Acrobatics, success)", + "GURPS.modifierDodgeDive": "to Dodge (dodge and drop)", + "GURPS.modifierDodgeFailedAcro": "to Dodge (Acrobatics, failed)", + "GURPS.modifierDodgeRear": "to Dodge (attacked from rear)", + "GURPS.modifierDodgeRetreat": "to Dodge (retreat)", + "GURPS.modifierDodgeSide": "to Dodge (attacked from side)", + "GURPS.modifierEasy": "Easy", + "GURPS.modifierExtraEffort": "Extra Effort", + "GURPS.modifierFavorable": "Favorable", + "GURPS.modifierFeverishDef": "Feverish Defense", + "GURPS.modifierDefDeceptiveAttack": "to defenses due to Deceptive attack", + "GURPS.modifierDefenseCommittedAim": "to defenses due to Committed Aim", + "GURPS.modifierDefenseCommittedAttackRanged": "to defenses due to Committed Attack (Ranged)", + "GURPS.modifierMaintainConcentration": "to Will Check, to maintain concentration", + "GURPS.modifierGrappling": "-4 to DX and DX-based skills (Grappled)", + "GURPS.modifierGMBlessed": "GM blessed", + "GURPS.modifierGMDontTry": "GM don't try it", + "GURPS.modifierGMSaidSo": "GM said so", + "GURPS.modifierHard": "Hard", + "GURPS.modifierHeroicCharge": "Heroic Charge", + "GURPS.modifierHitLocation": "Hit Locations (if miss by 1, then *)", + "GURPS.modifierImpossible": "Impossible", + "GURPS.modifierJournalManager": "Modifier Bucket Journals", + "GURPS.modifierJournals": "Modifier Bucket Journal List", + "GURPS.modifierLightDim": "Large fire / torch/ sunset / sunrise", + "GURPS.modifierLightFullMoon": "Full moon", + "GURPS.modifierLightHalfMoon": "Half moon", + "GURPS.modifierLightMoonless": "Overcast moonless night", + "GURPS.modifierLightNone": "Total darkness", + "GURPS.modifierLightQuarterMoon": "Quarter moon", + "GURPS.modifierLightStarlight": "Starlight", + "GURPS.modifierLightStarlightClouds": "Starlight through clouds", + "GURPS.modifierLightTwilight": "Twilight / gaslight / flashlight", + "GURPS.modifierLightDeepTwilight": "Deep twilight / candlelight", + "GURPS.modifierMightyBlow": "damage (Mighty Blow)", + "GURPS.modifierMoveAttack": "to hit (Move and Attack)", + "GURPS.modifierOthers": "Other Modifiers", + "GURPS.modifierPosture": "Posture", + "GURPS.modifierPostureCrouchMelee": "-2 to hit with melee combat (Crouching)", + "GURPS.modifierPostureCrouchRanged": "-2 to be hit with ranged combat (Crouching/Kneeling)", + "GURPS.modifierPostureKneelDefend": "-2 to active defenses (Kneeling/Sitting)", + "GURPS.modifierPostureKneelMelee": "-2 to hit with melee combat (Kneeling/Sitting)", + "GURPS.modifierPostureProneDefend": "-3 to active defenses (Crawling/Lying Down)", + "GURPS.modifierPostureProneMelee": "-4 to hit with melee combat (Crawling/Lying Down)", + "GURPS.modifierPostureProneRanged": "-2 to be hit with ranged combat (Sitting/Crawling/Lying Down)", + "GURPS.modifierQuality": "Equipment Quality", + "GURPS.modifierQualityBest": "Best Possible", + "GURPS.modifierQualityFine": "Fine Quality (20× cost)", + "GURPS.modifierQualityGood": "Good Quality (5× cost)", + "GURPS.modifierQualityImprovised": "Improvised", + "GURPS.modifierQualityImprovTech": "Improvised (technological)", + "GURPS.modifierQualityMissing": "Missing/Damaged Components", + "GURPS.modifierQualityNone": "None", + "GURPS.modifierQualityNoneTech": "None (techological)", + "GURPS.modifierScaleLarge": "Large (110%)", + "GURPS.modifierScaleNormal": "Normal (100%)", + "GURPS.modifierScaleSmall": "Small (90%)", + "GURPS.modifierScaleVeryLarge": "Very Large (120%)", + "GURPS.modifierScaleVerySmall": "Very Small (80%)", + "GURPS.modifierSelectJournalButton": "Select Bucket Journals", + "GURPS.modifierSelectJournals": "Bucket: Journal Entries", + "GURPS.modifierSelectJournalsAside": "Only 'standard' (HTML) journals are valid to view in the Modifier Bucket. E.g., PDFs cannot be displayed.", + "GURPS.modifierSelectJournalsHint": "Select the Journal entries to display in the Modifier Bucket.", + "GURPS.modifierSelectJournalsTitle": "Select Modifier Bucket Journals", + "GURPS.modifierSendTo": "Send Modifier Bucket to:", + "GURPS.modifierShieldDB": "to Dodge (Shield DB)", + "GURPS.modifierShowOnMouseOver": "Bucket: Show on mouse over", + "GURPS.modifierShowOnMouseOverHint": "If checked, the Modifier window displays like a tooltip: when the mouse hovers over the Modifier Bucket. If this is turned off, you can bring up the Tooltip by Left Clicking on the Modifier Bucket. You must restart Foundry for this setting to take effect.", + "GURPS.modifierSize": "Size Modifier", + "GURPS.modifierSizeDetail": "Difference in Melee; Absolute in Ranged", + "GURPS.modifierSizeEntry": "{SM} Size {us} ({metric})", + "GURPS.modifierStatus": "Status", + "GURPS.modifierStatusAffliction": "Status and Afflictions", + "GURPS.modifierStatusShock1": "-1 to IQ/DX checks (Shock 1)", + "GURPS.modifierStatusShock2": "-2 to IQ/DX checks (Shock 2)", + "GURPS.modifierStatusShock3": "-3 to IQ/DX checks (Shock 3)", + "GURPS.modifierStatusShock4": "-4 to IQ/DX checks (Shock 4)", + "GURPS.modifierStatusStunned": "-4 to active defenses (Stunned)", + "GURPS.modifierStrongAttack": "damage (Strong Attack)", + "GURPS.modifierTabAside": "Use System Settings to define Journal Entries to display here.", + "GURPS.modifierTaskDifficulty": "Task Difficulty", + "GURPS.modifierTelegraphicAttack": "to hit (Telegraphic Attack)", + "GURPS.modifierToHit": "to hit", + "GURPS.modifierTrivial": "Trivial", + "GURPS.modifierUnfavorable": "Unfavorable", + "GURPS.modifierUserEntered": "Or you can enter a modifier", + "GURPS.modifierVeryEasy": "Very Easy", + "GURPS.modifierVeryFavorable": "Very Favorable", + "GURPS.modifierVeryHard": "Very Hard", + "GURPS.modifierVeryUnfavorable": "Very Unfavorable", + "GURPS.modifierViewScale": "Bucket: Scale Factor", + "GURPS.modifierViewScaleHint": "Use this to scale up or down the size of the Modifier Bucket.", + "GURPS.modifierWillCheck": "WILL check to maintain Aim", + "__PDF References__": "=========", + "GURPS.pdfAllOutAim": "PY77:25", + "GURPS.pdfAllOutAttackRanged": "PY77:26", + "GURPS.pdfAllOutDefense": "B365", + "GURPS.pdfBlockRetreat": "B377", + "GURPS.pdfCrippling": "B420", + "GURPS.pdfCommittedAim": "PY77:25", + "GURPS.pdfCommittedAttackRanged": "PY77:26", + "GURPS.pdfDeceptiveAttack": "B369", + "GURPS.pdfDeterminedAttack": "B365", + "GURPS.pdfDamageRoll": "B378", + "GURPS.pdfDodgeAcrobatic": "B374", + "GURPS.pdfDodgeDive": "B377", + "GURPS.pdfDodgeFailedAcro": "B375", + "GURPS.pdfDodgeRear": "B391", + "GURPS.pdfDodgeRetreat": "B375", + "GURPS.pdfDodgeSide": "B390", + "GURPS.pdfExtraEffort": "B357", + "GURPS.pdfGrappling": "B370", + "GURPS.pdfHazardCoughing": "B428", + "GURPS.pdfHazardDrowsy": "B428", + "GURPS.pdfHazardDrunk": "B428", + "GURPS.pdfHazardEuphoria": "B428", + "GURPS.pdfHazardNausea": "B428", + "GURPS.pdfHazardPain": "B428", + "GURPS.pdfHazardRetching": "B429", + "GURPS.pdfHazardTipsy": "B428", + "GURPS.pdfHeroicCharge": "MA131", + "GURPS.pdfHPT": "B59", + "GURPS.pdfKnockback": "B378", + "GURPS.pdfKnockdownStun": "B420", + "GURPS.pdfLPT": "B142", + "GURPS.pdfMajorWound": "B420", + "GURPS.pdfMightyBlow": "MA131", + "GURPS.pdfMoveAttack": "B365", + "GURPS.pdfPostureCrawling": "B551", + "GURPS.pdfPostureCrouching": "B551", + "GURPS.pdfPostureKneeling": "B551", + "GURPS.pdfPostureLyingDown": "B551", + "GURPS.pdfPostureSitting": "B551", + "GURPS.pdfReeling": "B419", + "GURPS.pdfShieldDB": "B374", + "GURPS.pdfShieldRush": "B372", + "GURPS.pdfShock": "B419", + "GURPS.pdfStrongAttack": "B365", + "GURPS.pdfSuffocation": "B436", + "GURPS.pdfTired": "B426", + "GURPS.pdfTelegraphicAttack": "MA113", + "GURPS.pdfTempAttribPenalties": "B421", + "GURPS.pdfVisibility": "B394", + "__Resolve Damage Dialog__": "=========", + "GURPS.RESOLVEDAMAGEMultiple": "Multiple rolls", + "GURPS.RESOLVEDAMAGEPrompt": "What do you want to do with this Damage roll?", + "GURPS.RESOLVEDAMAGEQuantity": "Number of rolls:", + "GURPS.RESOLVEDAMAGESendTo": "Send OtF to...", + "GURPS.RESOLVEDAMAGETitle": "Resolve Damage Roll", + "__Resource Trackers__": "=========", + "GURPS.resourceCopyTemplate": "Copy Template", + "GURPS.resourceCurrentValue": "Current Value", + "GURPS.resourceDamageTracker": "Damage Tracker (damage adds to value).", + "GURPS.resourceDamageType": "Use as Damage Type", + "GURPS.resourceDeleteTracker": "Delete Tracker", + "GURPS.resourceEditTracker": "Edit Tracker", + "GURPS.resourceInvalidAlias": "Invalid alias [{alias}].
Only alphabet and number characters, plus ('+', '_', and '-'), are allowed.", + "GURPS.resourceTemplateAlias": "Alias", + "GURPS.resourceTemplateButton": "View and Edit Trackers", + "GURPS.resourceTemplateClickToAdd": "Click the '+' button to add a template.", + "GURPS.resourceTemplateHint": "Use this to create, reuse, and automatically apply Resource Trackers to character sheets.", + "GURPS.resourceTemplateInitializer": "Initializer", + "GURPS.resourceTemplateManager": "Resource Tracker Manager", + "GURPS.resourceTemplateSlot": "Assigned Slot", + "GURPS.resourceTemplateTitle": "Resource Tracker Templates", + "GURPS.resourceTracker": "Tracker", + "GURPS.resourceTrackerEditor": "Resource Tracker Editor", + "GURPS.resourceTrackers": "Resource Trackers", + "GURPS.resourceUndefined": "None Defined", + "GURPS.resourceUpdateTrackerSlot": "Update Tracker Slot", + "GURPS.slotNotUnique": "There is already a tracker assigned to slot Tracker {value}.", + "GURPS.trackerNotUnique": "Tracker name ({name}) or alias ({alias}) is not unique.", + "GURPS.resourceEnforceMinimum": "Enforce Minimum", + "GURPS.resourceEnforceMaximum": "Enforce Maximum", + "GURPS.resourceTemplateName": "Template Name", + "Skill Names__": "=========", + "GURPS.skillAcrobatics": "Acrobatics", + "GURPS.skillJudo": "Judo", + "__Slam Calculator__": "=========", + "GURPS.slamAOAStrong": "All-Out Attack (Strong)", + "GURPS.slamCalculator": "Slam Calculator", + "GURPS.slamForShieldDB": "Shield DB (Shield Rush)", + "GURPS.slamRelativeVelocity": "Relative Velocity", + "GURPS.slams": "slams", + "GURPS.slamShieldDB": "Shield DB", + "GURPS.slamVelocity": "Hexes moved", + "GURPS.slamDFRPGRules": "Use the Dungeon Fantasy RPG rules", + "__Status/Conditions__": "=========", + "GURPS.STATUSAgony": "Agony", + "GURPS.STATUSAim": "Aiming", + "GURPS.STATUSBleed": "Bleeding", + "GURPS.STATUSBlind": "Blinded", + "GURPS.STATUSBurn": "Burning", + "GURPS.STATUSCoughing": "Coughing", + "GURPS.STATUSCounter": "Counter", + "GURPS.STATUSCrouch": "Crouching", + "GURPS.STATUSDeaf": "Deafened", + "GURPS.STATUSDisable": "Disabled", + "GURPS.STATUSDrowsy": "Drowsy", + "GURPS.STATUSDrunk": "Drunk", + "GURPS.STATUSEuphoria": "Euphoria", + "GURPS.STATUSExhausted": "Fatigued", + "GURPS.STATUSFall": "Falling", + "GURPS.STATUSFly": "Flying", + "GURPS.STATUSGrapple": "Grappled", + "GURPS.STATUSKneel": "Kneeling", + "GURPS.STATUSMildPain": "Mild Pain", + "GURPS.STATUSModeratePain": "Moderate Pain", + "GURPS.STATUSNauseated": "Nauseated", + "GURPS.STATUSPin": "Pinned", + "GURPS.STATUSPoison": "Poisoned", + "GURPS.STATUSReeling": "Reeling", + "GURPS.STATUSRetching": "Retching", + "GURPS.STATUSSeverePain": "Severe Pain", + "GURPS.STATUSSilence": "Silenced", + "GURPS.STATUSSit": "Sitting", + "GURPS.STATUSSleep": "Sleeping", + "GURPS.STATUSSprint": "Sprinting", + "GURPS.STATUSStealth": "Sneaking/Stealth", + "GURPS.StatusStunnedMental": "Mental Stun", + "GURPS.STATUSSuffocate": "Suffocating", + "GURPS.STATUSTerriblePain": "Terrible Pain", + "GURPS.STATUSTipsy": "Tipsy", + "GURPS.STATUSWait": "Waiting", + "GURPS.STATUSBad+1": "+1 Basic Abstract Difficulty", + "GURPS.STATUSBad+2": "+2 Basic Abstract Difficulty", + "GURPS.STATUSBad+3": "+3 Basic Abstract Difficulty", + "GURPS.STATUSBad+4": "+4 Basic Abstract Difficulty", + "GURPS.STATUSBad+5": "+5 Basic Abstract Difficulty", + "GURPS.STATUSBad-1": "-1 Basic Abstract Difficulty", + "GURPS.STATUSBad-2": "-2 Basic Abstract Difficulty", + "GURPS.STATUSBad-3": "-3 Basic Abstract Difficulty", + "GURPS.STATUSBad-4": "-4 Basic Abstract Difficulty", + "GURPS.STATUSBad-5": "-5 Basic Abstract Difficulty", + "GURPS.STATUSDisarmed": "Disarmed", + "__Maneuvers__": "=========", + "GURPS.maneuver": "Maneuver", + "GURPS.maneuverDoNothing": "Do Nothing", + "GURPS.maneuverMove": "Move", + "GURPS.maneuverAim": "Aim", + "GURPS.maneuverCommittedAim": "Committed Aim", + "GURPS.maneuverAllOutAim": "All-out Aim", + "GURPS.maneuverChangePosture": "Change Posture", + "GURPS.maneuverEvaluate": "Evaluate", + "GURPS.maneuverAttack": "Attack", + "GURPS.maneuverFeint": "Feint", + "GURPS.maneuverCommittedAttackRanged": "Committed Attack (Ranged)", + "GURPS.maneuverAllOutAttack": "All-out Attack", + "GURPS.maneuverAllOutAttackDetermined": "All-out Attack (Determined)", + "GURPS.maneuverAllOutAttackDouble": "All-out Attack (Double)", + "GURPS.maneuverAllOutAttackFeint": "All-out Attack (Feint)", + "GURPS.maneuverAllOutAttackStrong": "All-out Attack (Strong)", + "GURPS.maneuverAllOutAttackRanged": "All-out Attack (Ranged Determined)", + "GURPS.maneuverAllOutAttackSuppressFire": "All-out Attack (Suppressing Fire)", + "GURPS.maneuverMoveAttack": "Move and Attack", + "GURPS.maneuverAllOutDefense": "All-out Defense", + "GURPS.maneuverAllOutDefenseDodge": "All-out Defense (Dodge)", + "GURPS.maneuverAllOutDefenseParry": "All-out Defense (Parry)", + "GURPS.maneuverAllOutDefenseBlock": "All-out Defense (Block)", + "GURPS.maneuverAllOutDefenseDouble": "All-out Defense (Double)", + "GURPS.maneuverReady": "Ready", + "GURPS.maneuverConcentrate": "Concentrate", + "GURPS.maneuverWait": "Wait", + "__Import Messages__": "=========", + "GURPS.importCannotImportGCADirectly": "We cannot import a GCA file directly. Please export the file using the 'export to Foundry VTT.gce' script.", + "GURPS.importCannotImportGCSDirectly": "We cannot import a GCS file directly. Please export the file using the 'Foundry VTT' output template.", + "GURPS.importGCA5ImprovedInventoryHandling": "This file was created with an older version of the GCA5 export which does not handle inventory text well.", + "GURPS.importGCA5ImprovedBlock": "This file was created with an older version of the GCA5 export which does not correctly calculate block for melee weapons.", + "GURPS.importCurrentVersions": "Current Versions: '{GCAVersion}' & '{GCSVersion}'.", + "GURPS.importErrorParsingXML": "Error parsing XML: {text}.", + "GURPS.importFantasyGroundUnsupported": "We no longer support the Fantasy Grounds import.", + "GURPS.importFileVersion": "The file version: '{version}'.", + "GURPS.importGCABadBlockForDB": "This file was created with an older version of the GCA Export which incorrectly calculates Block value for items with DB (e.g. Shields).", + "GURPS.importGCANoBodyPlan": "This file was created with an older version of the GCA Export which does not contain the 'Body Plan' attribute. We will try to guess the Body Plan, but we may get it wrong.", + "GURPS.importGCANoHideFlag": "This file was created with an older version of the GCA Export which ignored the 'hide' flag for ads/disads/quirks/perks.", + "GURPS.importGCAChildrenWeights": "This file was created with an older version of the GCA Export which incorrectly calculated the weights for equipment that contain other equipment.", + "GURPS.importGCANoInnateRangedAndParent": "This file was created with an older version of the GCA Export which does not export Innate Ranged attacks and does not contain the 'Parent' Attribute for equipment. You may be missing ranged attacks or equipment may not appear in the correct container.", + "GURPS.importGCANoMeleeIfAlsoRanged": "This file was created with an older version of the GCA Export which may not export a melee attack if it also exists in ranged attacks (e.g. Spears).", + "GURPS.importGCSNoMeleeRangedNotesForSameItem": "This file was created with an older version of the GCS Export which does not export individual Melee and Ranged attack notes created by the same item.", + "GURPS.importGCANoParent": "This file was created with an older version of the GCA Export which does not contain the 'Parent' attributes for Ads/Disads, Skills or Spells.", + "GURPS.importGCANoSanitizedEquipmentPageRefs": "This file was created with an older version of the GCA Export that may incorrectly put ranged attacks in the melee list and does not sanitize equipment page refs.", + "GURPS.importGCANoSanitizeNotes": "This file was created with an older version of the GCA Export which does not sanitize Notes or Ad/Disad names.", + "GURPS.importGCSNoParent": "This file was created with an older version of the GCS Export which does not contain the 'Parent' attributes. Items will not appear in their containers.", + "GURPS.importGCSNoSelfControl": "This file was created with an older version of the GCS Export which does not contain the Self Control rolls for Disadvantages (ex: [CR: 9 Bad Temper]).", + "GURPS.importGCSNoUses": "This file was created with an older version of the GCS Export which does not contain the 'Uses' column for Equipment.", + "GURPS.importGCAAdvMods": "This file was created with an older version of the GCA Export which concatenates Advantage modifiers into the Advantage name, which can create very long Advantage names (and affect the character sheet layout)", + "GURPS.importGCAConditionalModifiers": "This file was created with an older version of the GCA Export that does not export Conditional Modifiers", + "GURPS.importGenericError": "An error occured while importing {name}, {error}:{message}.", + "GURPS.importNoCharacterFormat": "Unable to detect the 'character' format. Most likely you are trying to import the 'npc' format.", + "GURPS.importNoXMLDetected": "No XML detected. Are you importing the correct XML file?", + "GURPS.importTooManyContainers": "You have too many levels of containers. The Foundry import only supports up to 3 levels of sub-containers.", + "GURPS.importSuccessful": "{name} imported successfully.", + "GURPS.importSeeUsersGuide": "Check the Users Guide for details on where to get the latest version.", + "GURPS.importOldGCSFile": "Your character was saved with an older version of GCS, which does not output some required attributes. Update GCS to at least version 4.36, open and save your character file, then try again.", + "GURPS.importNoJSONDetected": "Cannot parse JSON. Your GCS file seems to be corrupted.", + "__System Settings__": "=========", + "GURPS.settingShowReadMe": "Show 'Read Me' on version change", + "GURPS.settingHintShowReadMe": "If checked, the system will display the 'Read Me' file every time a version change is detected.", + "GURPS.settingRangeStrategy": "Combat: Range modifier strategy", + "GURPS.settingHintRangeStrategy": "Sets the formula to use to calculate range penalties.", + "GURPS.settingRangeStrategyStandard": "Size and Speed/Range Table", + "GURPS.settingRangeStrategyRangeBands": "Monster Hunters 2 Range Bands", + "GURPS.settingRangeStrategyTenPenalties": "-1 for every 10 hexes/yards/meters", + "GURPS.settingBasicPDFs": "Basic Set PDF(s)", + "GURPS.settingHintBasicPDFs": "Select 'Combined' or 'Separate' and use the associated PDF codes when configuring PDFoundry. Note: If you select 'Separate', the Basic Set Campaigns PDF should open up to page 340 during the PDFoundry test.", + "GURPS.settingBasicPDFsCombined": "Combined Basic Set (code 'B')", + "GURPS.settingBasicPDFsSeparate": "Separate (Characters, 'B'; Campaigns, 'BX')", + "GURPS.settingImportIgnoreName": "Import: Ignore 'name' attribute", + "GURPS.settingHintImportIgnoreName": "If checked, the system will ignore the 'name' attribute of the Actor during imports. This is useful if the name that you use in Foundry differs from GCA/GCS and you don't want it overwritten on every import.", + "GURPS.settingBlockImport": "Only TRUSTED players may Import", + "GURPS.settingHintBlockImport": "If checked, the 'Import' button will only be displayed on the character sheet if the player permission level is 'Trusted', 'Assistant' or 'GameMaster'", + "GURPS.settingImportHPAndFP": "Import: Current HP and FP", + "GURPS.settingHintImportHPAndFP": "NOTE: Current HP and FP are always read from the file during the initial import.", + "GURPS.settingImportHPAndFPUseFile": "Use the import file's current HP and FP.", + "GURPS.settingImportHPAndFPIgnore": "Ignore the import file's current HP and FP.", + "GURPS.settingImportHPAndFPAsk": "Ask before overwriting during import.", + "GURPS.settingImportBodyPlan": "Import: Body Plan/Hit Locations", + "GURPS.settingImportHintBodyPlan": "NOTE: The Body Plan is always read from the file during the initial import.", + "GURPS.settingImportBodyPlanUseFile": "Use the import file's Body Plan.", + "GURPS.settingImportBodyPlanIgnore": "Ignore the import file's Body Plan.", + "GURPS.settingImportBodyPlanAsk": "Ask before overwriting during import.", + "GURPS.settingShowNavigation": "Actor: Show navigation", + "GURPS.settingHintShowNavigation": "If checked, a navigation footer will be displayed on the full GCS character sheet.", + "GURPS.settingEnhancedInput": "Actor: Enhanced numeric inputs", + "GURPS.settingHintEnhancedInput": "If checked, certain fields (such as FP) will display add and subtract shortcut buttons when they have focus.", + "GURPS.settingCalculateEnc": "Actor: Calculate Encumbrance", + "GURPS.settingHintCalculateEnc": "If checked, the Encumbrance level will be set automatically based on the carried equipment (and you cannot change the Encumbrance level manually). If this is turned off, you can change the Encumbrance level by clicking on the new level.", + "GURPS.settingUseEquipped": "Actor: Weight based on 'Equipped'", + "GURPS.settingHintUseEquipped": "If checked, ONLY 'Equipped' items will be included in the weight calculation. If unchecked, all items in the Equipment list are included in the weight calculation. Uncheck, and the players can use the 'Equipped' flag to indicate they have dropped the item.", + "GURPS.settingFlagUserCreated": "Actor: Display User-created Flag", + "GURPS.settingHintFlagUserCreated": "If checked, a small icon will appear after user created (not imported) equipment and before user created notes.", + "GURPS.settingFlagItems": "Actor: Display Foundry Item Flag", + "GURPS.settingHintFlagItems": "If checked, a small icon will appear after equipment (and features) created from Foundry Items", + "GURPS.settingQtyItems": "Actor: Display QTY/Count saved Flag", + "GURPS.settingHintQtyItems": "If checked, a small icon will appear after equipment where the QTY/Count will be saved during imports", + "GURPS.settingConvertRanged": "Actor: Convert 'x2/x5' range to yards", + "GURPS.settingHintConvertRanged": "If checked, range fields in the form 'xN' or 'xN/xM' will be multiplied by the character's ST to determine the actual range for a thrown weapon. NOTE: This only occurs during import.", + "GURPS.settingShowDiceRoller": "UI: Show 3D6 (next to Modifier Bucket)", + "GURPS.settingHintShowDiceRoller": "If checked, the system will display the dice roller shortcut to the right of the Modifier Bucket. You must reload for this change to take effect.", + "GURPS.settingCombatInitiative": "Combat: Initiative Formula", + "GURPS.settingHintCombatInitiative": "This is the formula used by Foundry to determine turn order in combat. Warning: Only change this if you know what you are doing! We do not parse this for correctness. Set this field blank to reset the formula back to the GURPS Combat Turn Sequence, B362.", + "GURPS.settingDamageRestrictADD": "Damage: Restrict ADD to GM", + "GURPS.settingHintDamageRestrictADD": "If checked, only GMs can view/use the Apply Damage Dialog. Players who drag and drop damage will just receive a message.", + "GURPS.settingDamageSimpleADD": "Damage: Simple ADD", + "GURPS.settingHintDamageSimpleADD": "If checked, only display the 'Directly Apply' option in the Apply Damage Dialog.", + "GURPS.settingDamageLocation": "Damage: Default hit location", + "GURPS.settingHintDamageLocation": "Set the default hit location used to apply damage.", + "GURPS.settingDamageLocationTorso": "Torso", + "GURPS.settingDamageLocationRandom": "Random", + "GURPS.settingDamageAD": "Damage: Armor Divisors", + "GURPS.settingHintDamageAD": "If checked, adjust the target's DR by the armor divisor on the attack.", + "GURPS.settingDamageBluntTrauma": "Damage: Blunt Trauma", + "GURPS.settingHintDamageBluntTrauma": "If checked, use Blunt Trauma rules for calculating damage on flexible armor.", + "GURPS.settingDamageLocationMods": "Damage: Location Wounding Modifiers", + "GURPS.settingHintDamageLocationMods": "If checked, modify Wounding Modifiers based on Hit Location.", + "GURPS.settingDamageMath": "Damage: Show the math", + "GURPS.settingHintDamageMath": "If checked, the 'SHOW THE MATH' section of the damage chat message will be expanded by default. If unchecked, you can click on the 'SHOW THE MATH' title to expand it. NOTE: If this is the last message in the chat log, it may expand below the bottom of the log, and you might need to scroll down to see it.", + "GURPS.settingDamageCondInjury": "Damage: Conditional Injury", + "GURPS.settingHintDamagCondInjury": "From Pyramid #3/120: Conditional Injury removes Hit Points from the game as the basis for wound tracking, and replaces them with an effects based method for injury.", + "GURPS.settingStatusWhisper": "Status Effects: Whisper", + "GURPS.settingHintStatusWhisper": "If checked, Status Effects messages (Shock, Major Wound, etc.) will be sent to the target's owner as a Whisper. Otherwise they will be sent as a Out of Character (OOC) message to everyone.", + "GURPS.settingStatusReeling": "Status Effects: Auto Reeling and Tired", + "GURPS.settingHintStatusReeling": "If checked, Reeling (1/2 move/dodge) and Tired (1/2 move/dodge/ST) will automatically be turned on when the character drops below 1/3 HP and 1/3 FP.", + "GURPS.settingPlayerBlindRoll": "Enable Blind rolls for Players", + "GURPS.settingHintPlayerBlindRoll": "If not checked, holding down the SHIFT key when you are making a roll will make a Self roll (only you can see it, no matter who you are). If checked, when players hold down the SHIFT key, it will make it a Blind Roll instead (GMs still get a Self roll).", + "GURPS.settingPlayerChatPrivate": "Player Chat commands private", + "GURPS.settingHintPlayerChatPrivate": "If checked, most of the chat commands (e.g. /hp, /fp, /qty, etc.) will display as a whisper to the player (instead of an Out Of Character message). If you trust your players, and don't like to see the chat fill up with their chat commands, turn this on.", + "GURPS.settingMookGenerator": "Mook Generator Defaults", + "GURPS.settingLabelMookGenerator": "Mook Generator Default Editor", + "GURPS.settingHintMookGenerator": "Edit the initial values of the Mook Generator", + "GURPS.settingManeuverVisibility": "Maneuver Icon Visibility", + "GURPS.settingHintManeuverVisibility": "Determines who can see a token's maneuver icon.", + "GURPS.settingManeuverNoOne": "No One", + "GURPS.settingManeuverGMOnly": "GM and Owner Only", + "GURPS.settingManeuverEveryone": "Everyone", + "GURPS.settingManeuverDetail": "Maneuver Visibility Details", + "GURPS.settingHintManeuverDetail": "Determines what maneuver is visible to players other than the GM or Owner, if any. 'Full Detail': E.g., show \"All-out Attack (Determined)\" and \"Feint\" exactly as shown. 'No Feint': As 'Full Detail' except Feint shows as \"Attack\". 'General': As 'Full, No Feint' except option is not shown -- e.g., All-out Attack (Strong) shows as \"All-out Attack\". (GM and Owner always see Full Detail.)", + "GURPS.settingManeuverDetailFull": "Full Detail", + "GURPS.settingManeuverDetailNoFeint": "No Feint", + "GURPS.settingManeuverDetailGeneral": "General", + "GURPS.settingAutoIgnoreQty": "Import: Auto save Foundry Qty/Count", + "GURPS.settingHintAutoIgnoreQty": "If checked, this will automatically set the 'Save current QTY/Count on import' flag on a peice of equipment when the user changes the QTY/Count (and it will display the little blue file icon). NOTE: This does not detect changes in 'Uses'. If you need to remember 'Uses' between imports, you will need to manually set the flag for that equipment.", + "GURPS.settingSheetDetail": "Quick Sheet", + "GURPS.settingHintSheetDetail": "Select the character sheet that you want as the 'Quick Sheet'. It will be displayed in the title bar, and the user can click between it and the 'Full (GCS)' sheet", + "GURPS.settingImportEncoding": "Import file encoding", + "GURPS.settingImportHintEncoding": "If you are importing a character and the unicode characters are not displaying correctly, change this setting to UTF-8 encoding.", + "GURPS.settingImportEncodingISO8859": "ISO-8859-1 (default)", + "GURPS.settingImportEncodingUTF8": "UTF-8", + "GURPS.settingRemoveUnequipped": "Actor: Remove Unequipped weapons from Melee and Ranged lists", + "GURPS.settingHintRemoveUnequipped": "If checked, the names of the Melee and Ranged attacks will be compared to the carried equipment list, and if a name match is found, the attack will only be listed if the equipment is Equipped", + "GURPS.settingImportBrowserImporter": "Use non-locally hosted import dialog", + "GURPS.settingImportHintBrowserImporter": "Check this if you are not hosting your Foundry instance locally (you are hosting externally, i.e. Forge). This import dialog can remember the location of your import file during the session (which means that if you import the character again, in the same session, it will not have to bring up the File dialog).", + "GURPS.settingShowChatReeling": "Display Reeling/Tired Status in Chat", + "GURPS.settingHintShowChatReeling": "When checked, changes to any actor's Reeling or Tired status will be displayed as a chat message.", + "GURPS.settingDefaultADDAction": "Set default action for Damage Dialog", + "GURPS.settingHintefaultADDAction": "When set to 'Target' it will choose 'Apply' for Player Characters and 'Apply Quietly' for NPCs.", + "GURPS.settingApplyBasedOnTarget": "'Target'", + "GURPS.settingTokenOverrideRefresh": "Override Token scaling", + "GURPS.settingHintTokenOverrideRefresh": "If \"on\", try to draw tokens to properly fit the hex grid. Overrides Foundry drawing functionality -- turn this off if there's any odd Foundry drawing behavior. Requires reloading the world.", + "__Color Settings__": "=========", + "GURPS.settingColorSheetMenuTitle": "Color Character Sheet", + "GURPS.settingColorSheetMenuHint": "Color Character Sheet Settings", + "GURPS.colorSheetMenuOverride": "Override Colors", + "GURPS.colorSheetMenuCustomColors": "Custom Colors", + "GURPS.colorSheetMenuColorAreas": "Color Areas", + "GURPS.colorSheetMenuAreasAttributesColor": "Attributes Color", + "GURPS.colorSheetMenuAreasAttributesTextColor": "Attributes Text Color", + "GURPS.colorSheetMenuAreasAttributesHoverColor": "Attributes Hover Color", + "GURPS.colorSheetMenuAreasAttributesHoverTextColor": "Attributes Hover Text Color", + "GURPS.colorSheetMenuAreasDodgeColor": "Dodge Color", + "GURPS.colorSheetMenuAreasDodgeTextColor": "Dodge Text Color", + "GURPS.colorSheetMenuAreasDodgeHoverColor": "Dodge Hover Color", + "GURPS.colorSheetMenuAreasDodgeHoverTextColor": "Dodge Hover Text Color", + "GURPS.colorSheetMenuAreasDamageColor": "Damage Color", + "GURPS.colorSheetMenuAreasDamageTextColor": "Damage Text Color", + "GURPS.colorSheetMenuAreasDamageHoverColor": "Damage Hover Color", + "GURPS.colorSheetMenuAreasDamageHoverTextColor": "Damage Hover Text Color", + "GURPS.colorSheetMenuAreasBlockColor": "Block Color", + "GURPS.colorSheetMenuAreasBlockTextColor": "Block Text Color", + "GURPS.colorSheetMenuAreasBlockHoverColor": "Block Hover Color", + "GURPS.colorSheetMenuAreasBlockHoverTextColor": "Block Hover Text Color", + "GURPS.colorSheetMenuAreasParryColor": "Parry Color", + "GURPS.colorSheetMenuAreasParryTextColor": "Parry Text Color", + "GURPS.colorSheetMenuAreasParryHoverColor": "Parry Hover Color", + "GURPS.colorSheetMenuAreasParryHoverTextColor": "Parry Hover Text Color", + "GURPS.colorSheetMenuAreasWeaponsColor": "Weapons Color", + "GURPS.colorSheetMenuAreasWeaponsTextColor": "Weapons Text Color", + "GURPS.colorSheetMenuAreasWeaponsHoverColor": "Weapons Hover Color", + "GURPS.colorSheetMenuAreasWeaponsHoverTextColor": "Weapons Hover Text Color", + "GURPS.colorSheetMenuAreasSkillsColor": "Skills Color", + "GURPS.colorSheetMenuAreasSkillsTextColor": "Skills Text Color", + "GURPS.colorSheetMenuAreasSkillsHoverColor": "Skills Hover Color", + "GURPS.colorSheetMenuAreasSkillsHoverTextColor": "Skills Hover Text Color", + "GURPS.colorSheetMenuAreasSpellsColor": "Spells Color", + "GURPS.colorSheetMenuAreasSpellsTextColor": "Spells Text Color", + "GURPS.colorSheetMenuAreasSpellsHoverColor": "Spells Hover Color", + "GURPS.colorSheetMenuAreasSpellsHoverTextColor": "Spells Hover Text Color", + "GURPS.colorSheetMenuAreasOtfNotesColor": "OtF Notes Color", + "GURPS.colorSheetMenuAreasOtfNotesTextColor": "OtF Notes Text Color", + "GURPS.colorSheetMenuAreasOtfNotesHoverColor": "OtF Notes Hover Color", + "GURPS.colorSheetMenuAreasOtfNotesHoverTextColor": "OtF Notes Hover Text Color", + "GURPS.colorSheetMenuAreasAdsDisadsColor": "Ads/Disads Color", + "GURPS.colorSheetMenuAreasAdsDisadsTextColor": "Ads/Disads Text Color", + "GURPS.colorSheetMenuAreasAdsDisadsHoverColor": "Ads/Disads Hover Color", + "GURPS.colorSheetMenuAreasAdsDisadsHoverTextColor": "Ads/Disads Hover Text Color", + "GURPS.adDisad": "Advantage/Disadvantage", + "GURPS.adDisadQuirkPerk": "Advantage/Disadvantage/Quirk/Perk", + "GURPS.conditionalModifier": "Conditional Modifier", + "GURPS.delete": "Delete", + "GURPS.fromEllipses": "from ...", + "GURPS.moveToOtherEquipment": "Move to Other Equipment", + "GURPS.sortAscending": "Sort Ascending", + "GURPS.sortContentsAscending": "Sort Contents (Ascending)", + "GURPS.sortContentsDescending": "Sort Contents (Descending)", + "GURPS.sortDescending": "Sort Descending", + "GURPS.actions": "Actions", + "GURPS.aiming": "Aiming", + "GURPS.addAdvantage": "Add an Advantage", + "GURPS.addMeleeAttack": "Add a Melee Attack", + "GURPS.addRangedAttack": "Add a Ranged Attack", + "GURPS.addRT": "Add ResourceTracker", + "GURPS.addSkill": "Add a Skill", + "GURPS.addSpell": "Add a Spell", + "GURPS.advantage": "Advantage", + "GURPS.advantages": "Advantages", + "GURPS.advantagesTab": "Advantages and Disadvantages", + "GURPS.aim": "Aim", + "GURPS.allDamage": "ALL DAMAGE", + "GURPS.allOutDefense": "All-Out Defense", + "GURPS.allTheDamage": "ALL THE DAMAGE!!", + "GURPS.applyAllToTarget": "Apply All to {name}", + "GURPS.basic": "Basic", + "GURPS.bluntTrauma": "Blunt Trauma", + "GURPS.bonuses": "Bonuses", + "GURPS.check": "Check", + "GURPS.check1": "Check #1", + "GURPS.check2": "Check #2", + "GURPS.check3": "Check #3", + "GURPS.check4": "Check #4", + "GURPS.clickToEdit": "Click to Edit", + "GURPS.clickToRemove": "click to remove", + "GURPS.collapse": "Collapse", + "GURPS.color": "Color", + "GURPS.combatTab": "Combat", + "GURPS.concentrationCheck": "Concentration check", + "GURPS.condition": "Condition", + "GURPS.conditions": "Conditions", + "GURPS.crippling": "Crippling Injury, ", + "GURPS.current": "Current", + "GURPS.currentdodge": "Dodge", + "GURPS.damageAbove": "Damage above ", + "GURPS.dead": "Dead", + "GURPS.defense": "Defense", + "GURPS.destroyed": "Destroyed", + "GURPS.Dice": "Dice", + "GURPS.during": "During", + "GURPS.dxCheckOrFallApplyProne": "{name}: roll DX or fall!", + "GURPS.dxJudoAcrobaticsCheckToRemainStanding": "Roll [DX, Judo, or Acrobatics] {modifierText} to remain standing.", + "GURPS.effectsNotApplicableDefenses": "Does not apply to Active Defenses or other defensive reactions.", + "GURPS.effectsTemporaryAttributePenalties": "See Temporary Attribute Penalties", + "GURPS.equipmentTab": "Equipment", + "GURPS.equippedblock": "Block", + "GURPS.equippedparry": "Parry", + "GURPS.fail": "Fail", + "GURPS.fallsDownApplyProne": "{name}: falls down!", + "GURPS.for": "for", + "GURPS.forHighPainThreshold": "{mod} for High Pain Threshold", + "GURPS.forLowPainThreshold": "{mod} for Low Pain Threshold", + "GURPS.forPerfectBalance": "{mod} for Perfect Balance", + "GURPS.gameAidUsersGuide": "GURPS 4e Game Aid USERS GUIDE", + "GURPS.groundCreatures": "Ground creatures", + "GURPS.groundCreaturesSuffer": "Ground creatures suffer", + "GURPS.headVitalsHit": "Head or Vitals Hit ", + "GURPS.highPainThresholdNoPenalty": "High Pain Threshold negates penalty", + "GURPS.hpIgnored": " HP ignored.", + "GURPS.htCheck": "Roll HT", + "GURPS.ID": "ID", + "GURPS.itemBonusText": "Enter On-the-Fly 'Bonus' Formulas (one per line) to modify values of attributes, skills, etc.", + "GURPS.itemEditor": "Item Editor", + "GURPS.itemFeatures": "Features", + "GURPS.itemImport": "Import Equipment Library", + "GURPS.characterImport": "Import Character Library", + "GURPS.knockback": "Knockback, {amount} {unit}", + "GURPS.knockbackCheck": "{name}: roll {dx}, {acrobatics}, or {judo} or fall!", + "GURPS.level": "Level", + "GURPS.lighting": "Lighting", + "GURPS.location": "Location", + "GURPS.lowPainThresholdDoubles": "Low Pain Threshold doubles penalty", + "GURPS.majorWound": "Major Wound", + "GURPS.majorWoundEffect": " to avoid Stun/Knockdown.", + "GURPS.majorWoundEffectLabel": "{name}: roll {htCheck} to avoid Stun/Knockdown.", + "GURPS.max": "Max", + "GURPS.maximum": "Maximum", + "GURPS.melee": "Melee", + "GURPS.meleeAttack": "Melee Attack", + "GURPS.meters": " meters", + "GURPS.minimum": "Minimum", + "GURPS.minimumDamageRule": "* — Minimum damage rule applied.", + "GURPS.name": "Name", + "GURPS.noModifier": "No Modifier", + "GURPS.normal": "Normal", + "GURPS.notAffected": "{name} is not affected.", + "GURPS.notes": "Notes", + "GURPS.ok": "OK", + "GURPS.overridden": "overridden", + "GURPS.pass": "Pass", + "GURPS.pdfPageReference": "Page Ref", + "GURPS.pdfRef": "Ref", + "GURPS.pointDamage": "{damage} point of damage", + "GURPS.pointsDamage": "{damage} points of damage.", + "GURPS.quantity": "Quantity", + "GURPS.ranged": "Ranged", + "GURPS.rangedAttack": "Ranged Attack", + "GURPS.rateOfFire": "Rate of Fire", + "GURPS.reaction": "Reaction", + "GURPS.reference": "Reference", + "GURPS.removeItem": "Remove Item", + "GURPS.resolve": "Resolve", + "GURPS.resource": "Resource", + "GURPS.roll": "Roll", + "GURPS.rolled": "Rolled", + "GURPS.rollForMe": "Roll for me", + "GURPS.selectToken": "Select Token", + "GURPS.shock": "Shock", + "GURPS.shockPenalty": "Penalty (–{amount}) to DX and IQ.", + "GURPS.shockPenaltyNextTurnOnly": "{name}: –{modifier} to DX and IQ for next turn only.", + "GURPS.showQuestion": "Show?", + "GURPS.skill": "Skill", + "GURPS.skillLevel": "Skill Level", + "GURPS.skillsTab": "Skills", + "GURPS.spell": "Spell", + "GURPS.spellsTab": "Spells", + "GURPS.statsTab": "Stats", + "GURPS.suffersAMajorWound": "{name} suffers a Major Wound", + "GURPS.suffersHeadVitalsWound": "{name} was struck in the {location} with a Shock penalty.", + "GURPS.suffersKnockback": "{name} suffers Knockback {classStart}([PDF:{pdfref}]){classEnd} of {yards} {unit}.", + "GURPS.swimmerFlyer": "Swimmer / Flyer", + "GURPS.swimmersOrFlyersSuffer": "Swimmers Flyers", + "GURPS.target": "Target", + "GURPS.targeting": "Targeting {name}", + "GURPS.noTargetSelected": "No Target selected", + "GURPS.tired": "Tired", + "GURPS.toAllDXBasedRolls": "to all DX-based rolls", + "GURPS.TransferTo": "Transfer to", + "GURPS.unconscious": "Unconscious", + "GURPS.update": "Update", + "GURPS.warning": "WARNING", + "GURPS.yard": "yard", + "GURPS.yards": "yards", + "GURPS.addTracker": "Add Resource Tracker at the end", + "GURPS.edit": "Edit", + "GURPS.moveToCarriedEquipment": "Move to Carried Equipment", + "GURPS.dragSameContainer": "Cannot add the object to this container, as it is already inside it.", + "GURPS.dropResolve": "Where do you want to drop this object?", + "GURPS.dropBefore": "Before the target", + "GURPS.dropInside": "Inside the target", + "GURPS.moveNone": "None ({reason})", + "GURPS.moveConstant": "{value} {unit}/sec ({reason})", + "GURPS.moveStep": "Step ({reason})", + "GURPS.moveTwoSteps": "Step or two steps ({reason})", + "GURPS.moveOneThird": "×1/3 ({reason})", + "GURPS.moveTwoThirds": "×2/3 ({reason})", + "GURPS.moveHalf": "Half ({reason})", + "GURPS.moveFull": "Full", + "GURPS.setManeuver": "Set Maneuver", + "GURPS.abbrevPoints": "Pts", + "GURPS.abbrevReference": "Ref", + "GURPS.attributesSecondary": "Secondary Attributes", + "GURPS.attributesPrimary": "Basic Attributes", + "GURPS.injury": "Injury", + "GURPS.serverity": "Severity", + "GURPS.days": "Days", + "GURPS.none": "None", + "GURPS.equipmentCarried": "Carried Equipment", + "GURPS.equipmentOther": "Other Equipment", + "GURPS.equipmentUserCreated": "User-created", + "GURPS.equipmentIgnoreQtyImport": "Importing does not update quantity.", + "GURPS.showFlightMove": "Show Move/Flight Move", + "GURPS.rt": "RT", + "GURPS.thresholds": "Thresholds", + "GURPS.conditionalMods": "Conditional Modifiers", + "GURPS.ignoreBodyPlan": "Ignore Imported Body Plan", + "GURPS.abbrevRef": "Ref", + "GURPS.noteBlank": "This note was intentionally left blank.", + "GURPS.pointsTotal": "Total Points", + "GURPS.severities": "Severities", + "GURPS.addAdjustedForDamageType": "‡ - Adjusted for Damage Modifier", + "GURPS.addDamageModifier": "Damage Modifier", + "GURPS.reset": "Clear Configuration", + "GURPS.resolveDiceRoll": "What Did You Roll?", + "GURPS.settingUsePhysicalDice": "Use Physical Dice", + "GURPS.settingHintUsePhysicalDice": "If enabled, TRUSTED players will be prompted for all die roll values. This allows players to roll physical dice and enter the results into Foundry.", + "GURPS.settingUseQuintessence": "Use Quintessence", + "GURPS.settingHintUseQuintessence": "If enabled, adds the Quintessence attribute, and Quintessence Points become available to use as a Resource Tracker.", + "GURPS.STATUSStanding": "Standing", + "GURPS.STATUSCrawling": "Crawling", + "GURPS.STATUSProne": "Lying Down", + "GURPS.effectHintBlind": "-6 to hit if accustomed to being blind; Hearing -2 success lowers the to hit penalty to -4.", + "GURPS.effectChatModifiedToHit": "{displayName} is
[{modifier}]", + "GURPS.effectChatRangedModifier": "{displayName} is
[-2 to be hit with ranged combat ({posture})].", + "GURPS.tokenToolsTitle": "Open Effect Modifier Popup", + "GURPS.effectModNoTokenSelected": "No token selected", + "GURPS.effectModifierPopout": "Effect Modifiers", + "GURPS.targetedModifiers": "Targeted Modifiers", + "GURPS.settingActiveEffects": "Turn on Active Effects", + "GURPS.targetModifiers": "Target:", + "GURPS.settingHintActiveEffects": "Allow the GM to create and apply Active Effects", + "GURPS.CR0": "CR: N/A (Cannot Resist)", + "GURPS.CR6": "CR: 6 (Resist Rarely)", + "GURPS.CR9": "CR: 9 (Resist Fairly Often)", + "GURPS.CR12": "CR: 12 (Resist Quite Often)", + "GURPS.CR15": "CR: 15 (Resist Almost All The Time)", + "GURPS.modifiersBlindAttack": "-10 to hit (Blind)", + "GURPS.modifiersBlindDefend": "-4 on Active Defenses (Blind)", + "GURPS.moveModeGround": "Ground", + "GURPS.moveModeAir": "Air", + "GURPS.moveModeWater": "Water", + "GURPS.moveModeSpace": "Space", + "GURPS.moveModeOther": "Other...", + "GURPS.moveModeType": "Move Type", + "GURPS.moveModeValue": "Yards/Turn", + "GURPS.effectsTermination": "Termination Condition (OtF)", + "GURPS.effectsEffect": "Effect", + "GURPS.default": "Default", + "GURPS.conditionsCombatMove": "Combat Move", + "GURPS.activeEffects": "Active Effects", + "GURPS.quicknotes": "Quick Notes", + "GURPS.language": "Language", + "GURPS.spoken": "Spoken", + "GURPS.written": "Written", + "GURPS.pdfOffset": "Page Offset", + "GURPS.pdfCode": "PDF Book Code", + "GURPS.noViableSkill": "This character does not have a viable skill (effective level 3 or higher) that can be rolled", + "__Rolling__": "=========", + "GURPS.rollVs": "Roll vs", + "GURPS.rollNewTarget": "New Target: ({target})", + "GURPS.rollCriticalSuccess": "Critical Success!", + "GURPS.rollSuccess": "Success!", + "GURPS.rollFailure": "Failure!", + "GURPS.rollCriticalFailure": "Critical Failure!", + "GURPS.rollFail17": "17 & 18 always fail.", + "GURPS.rollJustMadeIt": "Just made it", + "GURPS.rollMadeBy": "Made it by {margin}.", + "GURPS.rollMissedBy": "Missed it by {margin}.", + "GURPS.rollTotalHits": "Total possible hits ({link})
due to RoF ({rof}) & Rcl ({rcl}) is {rofrcl}.", + "GURPS.rollTotal": "Rolled ({rolls}) = {rtotal}." } diff --git a/lang/pt_br.json b/lang/pt_br.json index 2c3671d1a..c2e940487 100644 --- a/lang/pt_br.json +++ b/lang/pt_br.json @@ -1,1132 +1,1132 @@ { - "__NOTE TO TRANSLATOR__": "If a given text is the same as the English (en.json), there is no need to include it here. It will fallback to en.json.", - "GURPS.title": "GURPS", - "GURPS.changelog": "LEIA-ME", - "GURPS.DontShowAgain": "Não exibir LEIA-ME novamente", - "GURPS.copyrightGURPS": "GURPS é marca registrada da Steve Jackson Games, que também detém direitos autorais sobre suas regras e arte. Todos os direitos reservados pela Steve Jackson Games. Este auxílio de jogo é criação original de Chris Normand/Nose66 e é distribuído gratuitamente, sendo vetada a venda, ver permissões em http://www.sjgames.com/general/online_policy.html", - "GURPS.copyrightGCS": "GCS© Todos os Direitos Reservados 1998-2020 Richard A. Wilkes.", - "__Char Sheet__": "=========", - "GURPS.portrait": "Retrato", - "__Character Sheet Identity__": "=========", - "GURPS.identity": "Identidade", - "GURPS.identityName": "Nome", - "GURPS.identityPlayer": "Jogador(a)", - "GURPS.identityTitle": "Título", - "__Character Sheet Miscellaneous__": "=========", - "GURPS.miscellaneous": "Diversos", - "GURPS.miscellaneousCreated": "Criação", - "GURPS.miscellaneousModified": "Modificação", - "GURPS.miscellaneousOptions": "Opções", - "__Character Description__": "=========", - "GURPS.description": "Descrição", - "GURPS.descriptionAge": "Idade", - "GURPS.descriptionAppearance": "Aparência", - "GURPS.descriptionBirthday": "Nascimento", - "GURPS.descriptionBodyPlan": "Tipo de Corpo", - "GURPS.descriptionEyes": "Olhos", - "GURPS.descriptionGender": "Gênero", - "GURPS.descriptionHair": "Cabelos", - "GURPS.descriptionHand": "Mão Hábil", - "GURPS.descriptionHeight": "Altura", - "GURPS.descriptionReligion": "Religião", - "GURPS.descriptionSizeModifier": "Mod. de Tamanho (MT)", - "GURPS.descriptionSkin": "Pele", - "GURPS.descriptionTechLevel": "Nível Tecnológico (NT)", - "GURPS.weight": "Peso", - "GURPS.share": "Compartilhar", - "__Character Points__": "=========", - "GURPS.point": "Ponto", - "GURPS.points": "Pontos", - "GURPS.pointsAdvantages": "Vantagens", - "GURPS.pointsAttributes": "Atributos", - "GURPS.pointsDisadvantages": "Desvantagens", - "GURPS.pointsQuirks": "Peculiaridades", - "GURPS.pointsRace": "Raça", - "GURPS.pointsSkills": "Perícias", - "GURPS.pointsSpells": "Magias", - "GURPS.pointsUnspent": "A Gastar", - "__Character Attributes__": "=========", - "GURPS.attributes": "Atributos", - "GURPS.attributesDX": "DX", - "GURPS.attributesDXNAME": "Destreza", - "GURPS.attributesFPNAME": "Pontos de Fadiga", - "GURPS.attributesHPNAME": "Pontos de Vida", - "GURPS.attributesHT": "HT", - "GURPS.attributesHTNAME": "Vitalidade", - "GURPS.attributesIQ": "IQ", - "GURPS.attributesIQNAME": "Inteligência", - "GURPS.attributesPER": "Per", - "GURPS.attributesPERNAME": "Percepção", - "GURPS.attributesST": "ST", - "GURPS.attributesSTNAME": "Força", - "GURPS.attributesWILL": "Vont", - "GURPS.attributesWILLNAME": "Vontade", - "GURPS.basicmove": "Desl. Básico", - "GURPS.basicspeed": "Vel. Básica", - "GURPS.speed": "Velocidade", - "GURPS.FP": "PF", - "GURPS.frightcheck": "Verif. de Pânico", - "GURPS.hearing": "Audição", - "GURPS.HP": "PV", - "GURPS.swing": "Golpe em Balanço", - "GURPS.tastesmell": "Paladar/Olfato", - "GURPS.thrust": "Golpe de Ponta", - "GURPS.touch": "Tato", - "GURPS.vision": "Visão", - "GURPS.attributesQN": "QN", - "GURPS.attributesQNNAME": "Quintessência", - "__ Character AddsDisadsPerksQuirks__": "=========", - "GURPS.advDisadvPerkQuirks": "Vantagens, Desvantagens, Qualidades e Peculiaridades", - "GURPS.highPainThreshold": "Hipoalgia", - "GURPS.lowPainThreshold": "Hiperalgia", - "GURPS.perfectBalance": "Equilíbrio Perfeito", - "__ Character Skills__": "=========", - "GURPS.rsl": "NH Rltv.", - "GURPS.SkillDXA": "DX/M", - "GURPS.SkillDXE": "DX/F", - "GURPS.SkillDXH": "DX/D", - "GURPS.SkillDXVH": "DX/MD", - "GURPS.SkillHTA": "HT/M", - "GURPS.SkillHTE": "HT/F", - "GURPS.SkillHTH": "HT/D", - "GURPS.SkillHTVH": "HT/MD", - "GURPS.SkillQNA": "QN/M", - "GURPS.SkillQNE": "QN/F", - "GURPS.SkillQNH": "QN/D", - "GURPS.SkillQNVH": "QN/MD", - "GURPS.SkillIQA": "IQ/M", - "GURPS.SkillIQE": "IQ/F", - "GURPS.SkillIQH": "IQ/D", - "GURPS.SkillIQVH": "IQ/MD", - "GURPS.SkillPerA": "Per/M", - "GURPS.SkillPerE": "Per/F", - "GURPS.SkillPerH": "Per/D", - "GURPS.SkillPerVH": "Per/MD", - "GURPS.skills": "Perícias", - "GURPS.SkillWillA": "Vont/M", - "GURPS.SkillWillE": "Vont/F", - "GURPS.SkillWillH": "Vont/D", - "GURPS.SkillWillVH": "Vont/MD", - "GURPS.sl": "NH", - "__Character Spells__": "=========", - "GURPS.spellClass": "Classe", - "GURPS.spellCollege": "Escola", - "GURPS.spellCost": "Custo", - "GURPS.spellDuration": "Duração", - "GURPS.spellMaintain": "Manutenção", - "GURPS.spells": "Mágicas", - "GURPS.spellTime": "Tempo", - "GURPS.spellResist": "Resistido Por", - "GURPS.spellDifficulty": "Dificuldade", - "__Character Equipment__": "=========", - "GURPS.equipment": "Equipamento", - "GURPS.otherEquipment": "Outros Equipamentos", - "GURPS.equipmentEquipped": "Eqpd", - "GURPS.equipmentQuantity": "Qtd", - "GURPS.equipmentUses": "Usos", - "GURPS.equipmentCost": "Custo", - "GURPS.equipmentMaxUses": "Máx de Usos", - "GURPS.equipmentTechlevel": "Nível Tecnológico", - "GURPS.equipmentFoundryItem": "Item do Foundry", - "__Character Encumbrance/Lift__": "=========", - "GURPS.basicLift": "Base de Carga", - "GURPS.carryOnBack": "Carregar nas Costas", - "GURPS.dodge": "Esquiva", - "GURPS.encumbranceMoveDodge": "BC, Deslocamento e Esquiva", - "GURPS.liftingAndMovingThings": "Levantar e Mover Objetos", - "GURPS.maxload": "Carga Máx", - "GURPS.move": "Desl.", - "GURPS.oneHandLift": "Levantar com UMA mão", - "GURPS.runningShoveAndKnockOver": "Encontrão e Derrubar", - "GURPS.shiftSlightly": "Mover Ligeiramente", - "GURPS.shoveAndKnockOver": "Empurrar e Derrubar", - "GURPS.twoHandLift": "Levantar com DUAS mãos", - "__Character Weapons__": "=========", - "GURPS.acc": "Prec", - "GURPS.block": "Bloqueio", - "GURPS.blockbonus": "Bônus de Bloqueio", - "GURPS.bulk": "Magnitude", - "GURPS.damage": "Dano", - "GURPS.meleeWeapons": "Armas de Combate Corpo a Corpo", - "GURPS.parry": "Aparar", - "GURPS.parrybonus": "Bônus de Aparar", - "GURPS.range": "Distância", - "GURPS.rangedWeapons": "Armas de Combate à Distância", - "GURPS.rcl": "Rco", - "GURPS.reach": "Alcance", - "GURPS.rof": "CdT", - "GURPS.shots": "Tiros", - "GURPS.usage": "Uso", - "__Apply Damage Dialog__": "=========", - "GURPS.addAbbrev": "Abrev", - "GURPS.addAdditionalStackingModifier": "Modificadores adicionais", - "GURPS.addAdjustedForHitLocation": "* - Ajustado para Ponto de Impacto", - "GURPS.addAdjustedForInjuryTolerance": "† - Ajustado para Tolerância a Ferimentos", - "GURPS.addApply": "Aplicar", - "GURPS.addApplyAndKeep": "Aplicar/Manter Aberto", - "GURPS.addApplyDamageDialog": "Janela de Avaliação de Dano", - "GURPS.addApplyDamageOptions": "OPÇÕES DE APLICAÇÃO DANO", - "GURPS.addApplyInjury": "Aplicar Dano", - "GURPS.addApplyInjuryAndKeep": "Aplicar Dano/Manter Aberto", - "GURPS.addApplyInjuryQuietly": "Aplicar Dano (Discretamente)", - "GURPS.addApplyInjuryQuietlyAndKeep": "Aplicar Dano (Discretamente)/Manter Aberto", - "GURPS.addApplyMultipleTimes": "Aplicar múltiplas vezes", - "GURPS.addApplyOptionsToAll": "Estas opções se aplicam a todo dano", - "GURPS.addApplyQuietly": "Aplicar (Discretamente)", - "GURPS.addApplyQuietlyAndKeep": "Aplicar (Discretamente)/Manter Aberto", - "GURPS.addApplyTo": "Aplicar em", - "GURPS.addArmorDivisor": "Divisor de Armadura", - "GURPS.addBasicDamage": "Dano Básico", - "GURPS.addCalculationAndResults": "Cálculos e Resultados", - "GURPS.addDamageReduction": "Redução de Dano", - "GURPS.addDamageType": "Tipo de Dano", - "GURPS.addDiffuseMax": "Difuso, dano máximo", - "GURPS.addDirectlyApply": "APLICAR DIRETAMENTE", - "GURPS.addEnterModifier": "Informe modificador", - "GURPS.addExplosion": "Explosão", - "GURPS.addExplosionHex": "{hex} hexágono do centro", - "GURPS.addExplosionHexes": "{hex} hexágonos do centro", - "GURPS.addFlexibleArmor": "Armadura Flexível", - "GURPS.addHardenedDRLevel": "RD para Enrijecido", - "GURPS.addHitLocationAndDR": "Ponto de Impacto e RD", - "GURPS.addHitLocationWoundModifiers": "Modificadores de Lesão conforme Ponto de Impacto", - "GURPS.addInjury": "Lesão", - "GURPS.addInjuryTolerance": "Tolerância a Ferimentos", - "GURPS.addInjuryToleranceDiffuse": "Difuso", - "GURPS.addInjuryToleranceHomogenous": "Homogêneo", - "GURPS.addInjuryToleranceUnliving": "Não-vivo", - "GURPS.addLargeAreaInjury": "Lesão em Grande Escala", - "GURPS.addLocationMax": "Dano máximo ao ponto", - "GURPS.addOverrideDR": "Desprezar a RD para o Ponto", - "GURPS.addPenetrating": "Penetrante", - "GURPS.addRangedHalfDamage": "Atq. à Distância, Metade do Dano (1/2D)", - "GURPS.addRangedHalfDamageShort": "Atq. à Distância (1/2D)", - "GURPS.addShotgunCloseRange": "Espingarda, à Queima-Roupa", - "GURPS.addShotgunDamage": "Dano de Espingarda", - "GURPS.addShotgunRofMultiplier": "Multiplicador por CdT", - "GURPS.addSingleRollSelected": "Uma avaliação de dano selecionada", - "GURPS.addSpecialCombatSituations": "Situações Esp. de Combate", - "GURPS.addTacticalRules": "Regras Táticas", - "GURPS.addTacticalRulesDefaults": "Usar definições do sistema como padrão", - "GURPS.addTitle": "Aplicar {basic} ponto(s) de dano [{damage}] a {name}", - "GURPS.addTitleConcat0": "Aplicar", - "GURPS.addTitleConcat01": "ponto de ", - "GURPS.addTitleConcat0s": "pontos de ", - "GURPS.addTitleConcat1": "dano a {name}", - "GURPS.addTypeAndWoundingModifiers": "Mod. de Ferimento e Lesão", - "GURPS.addVulnerability": "Vulnerabilidade", - "GURPS.addWHard": "c/ Rígido", - "__Body Plan__": "=========", - "GURPS.BODYPLANarachnoid": "Aracnídeo", - "GURPS.BODYPLANavian": "Aviário", - "GURPS.BODYPLANcancroid": "Cancroide", - "GURPS.BODYPLANcentaur": "Centauro", - "GURPS.BODYPLANhexapod": "Hexápode", - "GURPS.BODYPLANhexapodWinged": "Hexápode Alado", - "GURPS.BODYPLANhumanoid expanded": "Humanoide, Expandido (GCA)", - "GURPS.BODYPLANhumanoid": "Humanoide", - "GURPS.BODYPLANichthyoid": "Ictioide", - "GURPS.BODYPLANoctopod": "Octópode", - "GURPS.BODYPLANquadruped": "Quadrúpede", - "GURPS.BODYPLANquadrupedWinged": "Quadrúpede Alado", - "GURPS.BODYPLANscorpion": "Escorpião", - "GURPS.BODYPLANsnakeman": "Homem-Cobra", - "GURPS.BODYPLANsquid": "Cefalópode", - "GURPS.BODYPLANvermiform": "Vermiforme", - "GURPS.BODYPLANvermiformWinged": "Vermiforme Alado", - "GURPS.BODYPLANwinged humanoid": "Humanoide Alado", - "__Chat Messages__": "=========", - "GURPS.chatClearing": "Limpando", - "GURPS.chatClearingLastActor": "Limpando Último Ator", - "GURPS.chatDamageResultEnd": "em {location}", - "GURPS.chatDamageResultMiddle": "pontos de dano por {type}", - "GURPS.chatDamageResultShowMath": "Exibir cálculos", - "GURPS.chatDamageResultStart": "inflige {injury} em {defender}", - "GURPS.chatDoesNotHaveEnough": "não há 'USES' suficientes", - "GURPS.chatExceededMax": "MAX excedido", - "GURPS.chatExceededMaxUses": "'MAX USES' excedidos.", - "GURPS.chatFixedDamage": "[{dice} {damageTypeText}] dano.", - "GURPS.chatLightSource": "Selecione a fonte de luz que a miniatura selecionada está segurando.", - "GURPS.chatMoreThanOneActor": "Mais de um Ator encontrado nesses parâmetros", - "GURPS.chatMoreThanOneToken": "Mais de uma Miniatura encontrada nesses parâmetros", - "GURPS.chatMultipleOwnedFound": "Você possui mais de uma miniatura nesta cena. Você pode ou selecionar uma delas e tentar este comando novamente sem a palavra-chave '@self', ou usar a opção ':name'.", - "GURPS.chatMustBeACheck": "A fórmula On-the-Fly deve ser algum tipo de teste", - "GURPS.chatNoActorFound": "Não foram encontrados nenhum Ator/Miniatura que correspondam", - "GURPS.chatNoEquipmentMatched": "Nenhum equipamento corresponde", - "GURPS.chatNoResourceTracker": "Não há Controle de Recursos correspondente", - "GURPS.chatNoStatusMatched": "Nenhuma condição correspondente", - "GURPS.chatNoOwnedTokenFound": "Você não possui miniaturas nesta cena.", - "GURPS.chatNoTokens": "Seu personagem não possui miniatura. É necessária uma miniatura para aplicar uma condição", - "GURPS.chatQty": "QTD", - "GURPS.chatQtySetTo": "QTD definido para", - "GURPS.chatResetTo": "redefinido para", - "GURPS.chatResourceTracker": "Controle de Recursos", - "GURPS.chatResultBelowZero": "Resultado abaixo de zero", - "GURPS.chatRolling": "Rolando [{dice}{desc}]", - "GURPS.chatRollingDamage": "Jogando [{dice} {damageTypeText}] dano.", - "GURPS.chatRollingCR": "Teste de Autocontrole", - "GURPS.chatSetTo": "definido para", - "GURPS.chatSelectSelfOrNameTokens": "Você deve selecionar uma miniatura ou utilizar '{self}', ou ':<token-name>' para aplicar efeitos de condição.", - "GURPS.chatShock": "{name} sofre {modifier} pontos de Choque ", - "GURPS.chatSuffersCripplingInjury": "{name} sofre um ferimento incapacitante {classStart}([PDF:{pdfref}]){classEnd} no ponto de impacto {location}.", - "GURPS.andHalfMove": "e metade do Deslocamento.", - "GURPS.chatToApplyEffects": "para aplicar efeito de condição", - "GURPS.chatTokenLightPicker": "Seletor de Iluminação de Miniatura", - "GURPS.chatToggling": "Alternando", - "GURPS.chatTurnOnReeling": "{name} está Cambaleando. Deslocamento e Esquiva caem pela metade. {classStart}([PDF:{pdfref}]){classEnd}", - "GURPS.chatTurnOnTired": "{name} está Cansado(a). Deslocamento, Esquiva e ST caem pela metade. {classStart}([PDF:{pdfref}]){classEnd}", - "GURPS.chatTurnOffReeling": "{name} não está mais Cambaleando.", - "GURPS.chatTurnOffTired": "{name} não está mais Cansado(a).", - "GURPS.chatUnableToFindMacro": "Incapaz de encontrar macro chamada", - "GURPS.chatUnableToFindManeuver": "Incapaz de encontrar manobra chamada", - "GURPS.chatNotInCombat": "Você só pode configurar a Manobra se a miniatura estiver em combate", - "GURPS.chatUnrecognizedFormat": "Formato não reconhecido", - "GURPS.chatUses": "'USES'", - "GURPS.chatUsesIsNaN": "'USES' não é um número", - "GURPS.chatUsesReset": "'USES' redefinidos para 'MAX USES'", - "GURPS.chatUsesSet": "'USES' definidos para", - "GURPS.chatYouDoNotHaveEnough": "Você não tem o suficiente", - "GURPS.chatYouMustBeGM": "Você precisa ser MJ para executar esse comando", - "GURPS.chatYouMustHaveACharacterSelected": "Você precisa selecionar um personagem", - "GURPS.chatYouMustSelectTokens": "É preciso selecionar uma miniatura (ou usar", - "GURPS.chatHelpHelp": "/help comando de chat: para ver a ajuda para esse cmd\n\n?comando de chat: para ver a ajuda para esse comando", - "GURPS.chatHelpSound": "Tocar um som no fundo
parâmetros:\nw: esperar segundos antes de começar o som\nv: volume\n<caminho completo e nome do arquivo>
exemplos:\n/sound w2.5 /caminho/nome-do-arquivo\n/sound v0.6 /caminho/nome-do-arquivo\n/sound w3 v2 /caminho/nome-do-arquivo", - "GURPS.chatHelpW": "Sussurrar aos jogadores ou aos donos das miniaturas selecionadas
parâmetros:\n<[nomes de jogadores]>\n@: sussurrar aos donos das miniaturas selecionadas\n
exemplos:\n/w [Cris] msg enviada ao jogador Cris\n/w @ msg enviadas aos donos das miniaturas selecionadas", - "GURPS.chatHelpWait": "Aguarde X milissegundos antes de executar o próximo comando de chat
parâmetros:\nX: o número de milissegundos a aguardar\n
exemplos:\n/wait 500", - "GURPS.chatHelpRa": "Fazer Um Teste (ou Fazer Um Teste Particular)
parâmetros:\nX: NH do teste\nNomeDaPerícia-X: Fazer um teste de X, mas exibir 'NomeDaPerícia' ao invés de 'Predefinido'\n
exemplos:\n/ra 12\n.ra 13\n/pra 11\n.pra 10\n/ra Furtividade-12\n.ra Briga-13\n/pra Armadilhas-11\n.pra SacarRápido-10", - "GURPS.chatHelpFpHp": "Aplicar fórmula aos PF ou PV dos personagens selecionados
parâmetros:\n<fórmula>\nreset: Redefinir PF(FP) ou PV(HP) de volta ao valor inicial
exemplos:\n/fp +1\n/hp -1\n/fp +1d\n/hp +1d-3!\n/fp reset\n", - "GURPS.chatHelpSelect": "Selecionar miniatura(s)
parâmetros:\n<nome do personagem>\n@self: selecionar a miniatura do personagem selecionado\n!:selecionar em todas as cenas, não apenas na atual
exemplos:\n/select Bog\n/select @self\n/select Bog !", - "GURPS.chatHelpUses": "Modificar a coluna USOS de um equipamento
parâmetros:\n<formula>\n<equipamento>\no:<equipamento>: buscar apenas na lista 'outros'\nreset: definir os USOS para o MÁX_USOS
exemplos:\n/uses +1 equipamento\n/uses -2 equipamento\n/uses =20 equipamento\n/uses +1 o:equipamento\n/uses reset equipamento", - "GURPS.chatHelpQty": "Modificar a coluna QTD de um equipamento
parâmetros:\n<fórmula>\n<equipamento>\no:<equipamento>: buscar apenas na lista 'outros'
exemplos:\n/qty +1 equipamento\n/qty -2 equipamento\n/qty =20 equipamento\n/qty +1 o:equipamento", - "GURPS.chatHelpLight": "Configurar o nível de luz de uma miniatura
parâmetros:\nnone|off: desligar a luz\nX: raio de baixa luminosidade\nY: raio de luz plena\nZ: transmitir ângulo de luz \n#RRGGBB: cor da luz\nW: intensidade da cor (0.0-1.0)\n<anim>: padrão de animação (torch (tocha), pulse (pulso), chroma (colorido), wave (onda), fog (névoa), sunburst (clarão de sol), dome (domo), emanation (emanação), hexa (hexagonal), ghost (fantasmagórico), energy (energia), roiling (turvo), hole (buraco)\nSPEED: velocidade da animação (1-10)\nINT: intensidade da animação (1-10)
exemplos:\n/li 6 2\n/li 8 3 90\n/li 6 2 #ff0000\n/li 6 2 #ff1111 0.5\n/li 6 2 torch\n/li 8 4 90 #ff7777 0.5 pulse 5 5\nhttps://foundryvtt.com/article/lighting/", - "GURPS.chatHelpTracker": "Modificar o Controle de Recursos
formato do comando:\n/tr0-3\n/tracker0-3\n/resource0-3\n/rt0-3\n/tr(nome)\n/tracker(nome)\n/resource(nome)\n/rt(nome)
parâmetros:\n<fórmula>\nreset: redefine o Controle ao valor inicial
exemplos:\n/tr0 +1\n/tr0 -2\n/tracker1 =20\n/tr(arrows) +1\n/resource(rounds) reset", - "GURPS.chatHelpStatus": "Configurar o efeito de status de uma miniatura
parâmetros:\ntoggle|t: alterna o status\non|+|set: aciona o status\noff|-|unset: desliga o status\nclear: remove todos os status\n@self / :nome da miniatura\nlist: exibe todos os nomes de status\n{JSON data}: dados opcionais de 'duration.combat' (duração de combate)
exemplos:\n/st on prone Bog\n/st - shock1 @self\n/st list", - "GURPS.chatHelpRemote": "Executar uma fórmula On-the-Fly remotamente
parâmetros:\n[OtF]: fórmula On-the-Fly\n<player names>|blank: list of player names (or blank to send to all players)
examples:\n/rem [‏PER] Chris\n/rem [‏ST+2]", - "GURPS.chatHelpEveryone": "Aplicar fórmula aos PF(FP) ou PV(HP) de todos os personagens dos jogadores ou executar uma fórmula On-the-Fly localmente contra todos os personagens dos jogadores
parâmetros:\nfp <fórmula>\nhp <fórmula>\n [OtF]: executar fórmula OtF (localmente) para todos os personagens dos jogadores\nfp reset: Redefinir os PF de volta ao valor inicial\nhp reset: Redefinir os PV de volta ao valor inicial
exemplos:\n/ev fp +1\n/ev hp -1\n/ev fp +1d\n/ev hp +1d-3!\n/ev fp reset\n/ev [‏PER]", - "GURPS.chatHelpAnim": "Tocar uma animação centralizada ou que se move.\n
parâmetros (para ambos)\nlist: exibir uma lista de animações disponíveis\nwX: aguardar X segundos antes de exibir a animação\n<NomeDoArquivo pattern>: 'pattern' pode conter *\nXx:Y: repetir animação X vezes (2x, 3x, etc.) com Y segundos de atraso entre as animações\n
parâmetros para animações centralizadas:\nc: indica uma animação centralizada\n*X: mudar a escala da animação em X\n@self: utilizar a si mesmo como centro, ao invés do alvo\nA opção a seguir pode ser adicionada após o 'c'\n f: vira a animação no eixo x (esquerda para a direita)\n m: desloca a animação centralizada até o alvo\n n: não rotaciona a animação centralizada em deslocamento\n X: número de graus a rotacionar a animação\n :Y,Z: compensar posição da animação (padrão 0.5,0.5)\n
exemples de animações centralizadas:\n/anim <pattern> c *0.5 3x\n'centralizada, escala: 1/2, 3 vezes'\n\n/anim <pattern> cf *2 3x:4\n'centralizada, virada (esquerda-direita), escala: 2x, 3 vezes com atraso de 4 segundos\n\n/anim <pattern> cm\n'centralizada, animação se desloca de si mesmo até o alvo'\n\n/anim <pattern> cmn\n'centralizada, animação se desloca de si mesmo até o alvo, sem rotacionar'\n\n/anim <pattern> cfm\n'centralizada, virada, animação se desloca de si mesmo até o alvo'\n\n/anim <pattern> c90\n'centralizada, rotacionada 90 graus'\n\n/anim <pattern> cf180 *.333\n'centralizada, virada, rotacionada 180 graus, escala: 1/3'\n\n/anim <pattern> cm45\n/anim <pattern> c:0,1\n/anim <pattern> cf:0.5,1\n/anim <pattern> cmn:0.9,1 *2\n
parâmetros para uma animação que se move:\n-X: mover-se à esquerda (0.0-1.0) em direção ao início da animação\n+X: esticar para a direita (0.0-infinito) em direção ao destino\n
exemplos de animações que se movem:\n/anim <pattern> -0.1 +0.1 2x\n'animação que se move, mover-se à esquerda 10%, esticar à direita 10%, 2 vezes'", - "GURPS.chatHelpShow": "Exibe vários valores de miniaturas na cena
parâmetros:\n<Atributos (primários e secundários)>\n<Nome de perícias>\nparry (aparar)\nblock (bloqueio)\nwill (vont)\nfright (verif. de pânico)\nper\nvision (visão)\nhearing (audição)\ntaste (paladar)\nsmell (olfato)\nmove (deslocamento)\nspeed (velocidade)
exemplos:\n/show HP FP IQ\n/show Furtividade PER\n/show per move speed\n/show vision hearing", - "GURPS.chatHelpManeuver": "Configurar as seguintes manobras ao personagem selecionado. Você pode usar * para ligar nomes de Manobras, por exemplo: '/man All Out*Double'
", - "GURPS.chatHelpRepeat": "Repetir o seguinte comando /anim com um atraso de X segundos entre cada execução.
exemplos:\n/repeat /anim 1.2 heal*blue c", - "GURPS.chatWantsToExecute": "Deseja executar {command} em {name},

Você aceita?", - "__Permissions__": "=========", - "GURPS.cannotDragNonFoundryEqt": "Você não pode arrastar equipamento que não é do Foundry para outro personagem.", - "GURPS.youDoNotHavePermssion": "Você não tem permissão para fazer isso.", - "__Damage Types__": "=========", - "GURPS.damageAbbrevburn": "qmd", - "GURPS.damageAbbrevcor": "cor", - "GURPS.damageAbbrevcr": "cont", - "GURPS.damageAbbrevcut": "corte", - "GURPS.damageAbbrevdmg": "dano", - "GURPS.damageAbbrevfat": "fad", - "GURPS.damageAbbrevimp": "perf", - "GURPS.damageAbbrevinjury": "lesão", - "GURPS.damageAbbrevpi-": "pa-", - "GURPS.damageAbbrevpi": "pa", - "GURPS.damageAbbrevpi+": "pa+", - "GURPS.damageAbbrevpi++": "pa++", - "GURPS.damageAbbrevtox": "tox", - "GURPS.damageTypeBurning": "Queimadura", - "GURPS.damageTypeCorrosive": "Corrosão", - "GURPS.damageTypeCrushing": "Contusão", - "GURPS.damageTypeCutting": "Corte", - "GURPS.damageTypeDamage": "Dano", - "GURPS.damageTypeFatigue": "Fadiga", - "GURPS.damageTypeHuge Piercing": "Extremamente Perfurante", - "GURPS.damageTypeImpaling": "Perfuração", - "GURPS.damageTypeInjury": "Lesão", - "GURPS.damageTypeLarge Piercing": "Muito Perfurante", - "GURPS.damageTypePiercing": "Perfurante", - "GURPS.damageTypeSmall Piercing": "Pouco Perfurante", - "GURPS.damageTypeToxic": "Toxina", - "__Drag Ruler__": "=========", - "GURPS.dragrulerFly": "Voo", - "GURPS.dragrulerSprint": "Disparada", - "GURPS.dragrulerWalk": "Caminhada", - "__Fantastic Dungeon Grappling__": "=========", - "GURPS.grapplingControlled": "Sendo controlado(a)", - "GURPS.grapplingControlPoints": "Pontos de Controle", - "GURPS.grapplingCPAbbrev": "ctrle", - "GURPS.grapplingGrabbed": "Sendo segurado(a)", - "GURPS.grapplingGrappled": "Agarrado(a)", - "GURPS.grapplingPinned": "Imobilizado(a)", - "GURPS.grapplingRestrained": "Preso(a)", - "GURPS.grapplingUnrestrained": "Livre", - "__Hit Location__": "=========", - "GURPS.hitLocation": "Ponto de Impacto", - "GURPS.hitLocationArm 1-2": "Braço 1-2", - "GURPS.hitLocationArm 3-4": "Braço 3-4", - "GURPS.hitLocationArm 5-6": "Braço 5-6", - "GURPS.hitLocationArm 7-8": "Braço 7-8", - "GURPS.hitLocationArm, holding shield": "Braço, com escudo", - "GURPS.hitLocationArm": "Braço", - "GURPS.hitLocationArm*": "Braço", - "GURPS.hitLocationBrain": "Cérebro", - "GURPS.hitLocationChest": "Peito", - "GURPS.hitLocationChinks in Torso": "Fendas em armadura (tronco)", - "GURPS.hitLocationChinks in Other": "Fendas em armadura (outros)", - "GURPS.hitLocationDescChest": "*acerto no peito", - "GURPS.hitLocationDescFront": "apenas frente", - "GURPS.hitLocationDescHalfDR": "½ RD", - "GURPS.hitLocationDescImp": "perf or pa(qualquer) apenas", - "GURPS.hitLocationDescLimb": "*acerto em membro", - "GURPS.hitLocationDescNeck": "*acerto no pescoço", - "GURPS.hitLocationDR": "RD", - "GURPS.hitLocationDRWithDivisor": "RD Efetiva", - "GURPS.hitLocationExtremity": "Extremidade", - "GURPS.hitLocationEye": "Olho", - "GURPS.hitLocationEyes": "Olhos", - "GURPS.hitLocationFace, from behind": "Rosto, pelas costas", - "GURPS.hitLocationFace": "Rosto", - "GURPS.hitLocationFin": "Nadadeira", - "GURPS.hitLocationFin*": "Nadadeira", - "GURPS.hitLocationFoot": "Pé", - "GURPS.hitLocationForeleg": "Perna Dianteira ", - "GURPS.hitLocationGroin": "Virilha", - "GURPS.hitLocationHand": "Mão", - "GURPS.hitLocationHind Leg": "Perna Traseira", - "GURPS.hitLocationJaw": "Maxilar", - "GURPS.hitLocationLeft Arm, holding shield": "Braço Esq., com escudo", - "GURPS.hitLocationLeft Arm": "Braço Esq", - "GURPS.hitLocationLeft Leg": "Perna Esq", - "GURPS.hitLocationLeg 1-2": "Perna 1-2", - "GURPS.hitLocationLeg 3-4": "Perna 3-4", - "GURPS.hitLocationLeg 5-6": "Perna 5-6", - "GURPS.hitLocationLeg 7-8": "Perna 7-8", - "GURPS.hitLocationLeg": "Perna", - "GURPS.hitLocationLimb Vein/Artery": "Veia/Artéria de Braço ou Perna", - "GURPS.hitLocationMid Leg": "Perna Central", - "GURPS.hitLocationMid Leg*": "Perna Central", - "GURPS.hitLocationNeck Vein/Artery": "Jugular/Carótida", - "GURPS.hitLocationNeck": "Pescoço", - "GURPS.hitLocationNose": "Nariz", - "GURPS.hitLocationPenalty": "Mod.", - "GURPS.hitLocationRandom": "Aleatório", - "GURPS.hitLocationRight Arm, holding shield": "Braço Dir., com escudo", - "GURPS.hitLocationRight Arm": "Braço Dir", - "GURPS.hitLocationRight Leg": "Perna Dir", - "GURPS.hitLocationSkull, from behind": "Crânio, pelas costas", - "GURPS.hitLocationSkull": "Crânio", - "GURPS.hitLocationTail": "Cauda", - "GURPS.hitLocationTorso": "Tronco", - "GURPS.hitLocationTorso*": "Tronco", - "GURPS.hitLocationVitals, Heart": "Órg. Vitais, Coração", - "GURPS.hitLocationVitals": "Órg. Vitais", - "GURPS.hitLocationWhere": "Onde", - "GURPS.hitLocationWing": "Asa", - "__Modifier Bucket__": "=========", - "GURPS.modifier": "Mod.", - "GURPS.modifierTitle": "Modificadores", - "GURPS.modifierRangeTitle": "Velocidade/Distância", - "GURPS.modifierRange": "para veloc/dist de {range} m", - "GURPS.modifierRangeMHClose": "Próximo (5 m)", - "GURPS.modifierRangeMHCloseDesc": "É possível encostar ou atingir o oponente", - "GURPS.modifierRangeMHShort": "Distância curta (20 m)", - "GURPS.modifierRangeMHShortDesc": "É possível falar com o oponente; alcance de pistolas ou armas/projéteis lançados a mão", - "GURPS.modifierRangeMHMedium": "Distância média (100 m)", - "GURPS.modifierRangeMHMediumDesc": "Só é possível se comunicar gritando; alcance de espingardas ou submetralhadoras", - "GURPS.modifierRangeMHLong": "Distância longa (500 m)", - "GURPS.modifierRangeMHLongDesc": "Oponente longe demais para escutar; alcance de rifles", - "GURPS.modifierRangeMHExtreme": "Distância extrema (500+ m)", - "GURPS.modifierRangeMHExtremeDesc": "Difícil de sequer ver o oponente; alcance de rifles de atirador", - "GURPS.modifierAddRangeRuler": "Balde: Adicionar modificador da Régua", - "GURPS.modifierAddRangeRulerHint": "Se selecionado, o sistema automaticamente vai adicionar o último modificador medido pela Régua ao Balde de Modificadores.", - "GURPS.modifierAffliction": "Atribulações", - "GURPS.modifierAfflictionCough": "-3 para testes de DX (Tossindo)", - "GURPS.modifierAfflictionCoughIQ": "-1 para testes de IQ (Tossindo)", - "GURPS.modifierAfflictionDrowsy": "-2 para testes de IQ/DX/autocontrole (Sonolento)", - "GURPS.modifierAfflictionDrunk": "-2 para testes de IQ/DX (Bêbado)", - "GURPS.modifierAfflictionDrunkCR": "-4 para testes de autocontrole (Bêbado)", - "GURPS.modifierAfflictionEuphoria": "-3 para testes de IQ/DX/autocontrole (Euforia)", - "GURPS.modifierAfflictionModerate": "-2 para testes de IQ/DX/autocontrole (Dor Moderada)", - "GURPS.modifierAfflictionModerateHPT": "-1 para testes de IQ/DX/autocontrole (Dor Moderada c/ Hipoalgia)", - "GURPS.modifierAfflictionNausea": "-2 para todos os atributos (Nauseado)", - "GURPS.modifierAfflictionNauseaDef": "-1 em defesas ativas (Nauseado)", - "GURPS.modifierAfflictionRetch": "-5 para testes de IQ/DX/Per (Ânsia)", - "GURPS.modifierAfflictionSevere": "-4 para testes de IQ/DX/autocontrole (Dor Severa)", - "GURPS.modifierAfflictionSevereHPT": "-2 para testes de IQ/DX/autocontrole (Dor Severa c/ Hipoalgia)", - "GURPS.modifierAfflictionTerrible": "-6 para testes de IQ/DX/autocontrole (Dor Terrível)", - "GURPS.modifierAfflictionTerribleHPT": "-3 para testes de IQ/DX/autocontrole (Dor Terrível c/ Hipoalgia)", - "GURPS.modifierAfflictionTipsy": "-1 para testes de IQ/DX (Embriagado)", - "GURPS.modifierAfflictionTipsyCR": "-2 para testes de autocontrole (Embriagado)", - "GURPS.modifierAppearBelow": "Eles vão aparecer na lista Modificadores Selecionados, abaixo.", - "GURPS.modifierAutomatic": "Automática", - "GURPS.modifierBlindAttack": "-10 na jogada de ataque (Cego)", - "GURPS.modifierBlindDefend": "-4 na esquiva (Cego -- incapaz de ver o atacante)", - "GURPS.modifierBlockRetreat": "para Esquiva/Aparar (Retirada)", - "GURPS.modifierClickToAdd": "Clique nos modificadores acima e à direita para adicioná-los ao seu próximo teste.", - "GURPS.modifierCommon": "Modificadores Comuns", - "GURPS.modifierCover": "Cobertura", - "GURPS.modifierCoverBehindFigure": "-4 no ataque (Atrás de outra pessoa do mesmo tamanho)", - "GURPS.modifierCoverCrouch": "-2 no ataque (Agachado or Ajoelhado, sem cobertura)", - "GURPS.modifierCoverHalfExposed": "-3 no ataque (Metade do corpo exposta)", - "GURPS.modifierCoverHead": "-5 no ataque (Apenas Cabeça)", - "GURPS.modifierCoverHeadShoulder": "-4 no ataque (Cabeça e ombros)", - "GURPS.modifierCoverLight": "-2 no ataque (Atrás de cobertura leve)", - "GURPS.modifierCoverPosture": "Cobertura e Posição", - "GURPS.modifierCoverProne": "-4 no ataque (Deitado, sem cobertura)", - "GURPS.modifierCoverProneHeadDown": "-7 no ataque (Deitado, pouca cobertura, cabeça abaixada)", - "GURPS.modifierCoverProneHeadUp": "-5 no ataque (Deitado, pouca cobertura, cabeça erguida)", - "GURPS.modifierCoverThroughHex": "-4 no ataque (Disparando através de hexágono ocupado)", - "GURPS.modifierCurrentEffects": "Efeitos Selecionados", - "GURPS.modifierCurrentModifiers": "Modificadores Selecionados", - "GURPS.modifierDangerous": "Perigosa", - "GURPS.modifierDeceptiveAttack": "ao ataque (Ataque Enganoso)", - "GURPS.modifierDeterminedAttack": "ao ataque (Ataque Determinado)", - "GURPS.modifierDodgeAcrobatic": "para Esquiva (Acrobática, sucesso)", - "GURPS.modifierDodgeDive": "para Esquiva (Esquiva e Queda)", - "GURPS.modifierDodgeFailedAcro": "para Esquiva (Acrobática, fracasso)", - "GURPS.modifierDodgeRear": "para Esquiva (ataque pelas costas)", - "GURPS.modifierDodgeRetreat": "para Esquiva (Retirada)", - "GURPS.modifierDodgeSide": "para Esquiva (ataque lateral)", - "GURPS.modifierEasy": "Fácil", - "GURPS.modifierExtraEffort": "Esforço Adicional", - "GURPS.modifierFavorable": "Favorável", - "GURPS.modifierFeverishDef": "Defesa Exaltada", - "GURPS.modifierDefDeceptiveAttack": "às defesas devido a um ataque Enganoso", - "GURPS.modifierMaintainConcentration": "para Teste de Vont, para manter concentração", - "GURPS.modifierGrappling": "-4 à DX e perícias baseadas em DX (Agarrado)", - "GURPS.modifierGMBlessed": "Bênção do MJ", - "GURPS.modifierGMDontTry": "MJ: nem pense nisso", - "GURPS.modifierGMSaidSo": "Porque o MJ quer", - "GURPS.modifierHard": "Difícil", - "GURPS.modifierHeroicCharge": "Investida Heroica", - "GURPS.modifierHitLocation": "Pontos de Impacto (se a margem de fracasso for 1, então *)", - "GURPS.modifierImpossible": "Impossível", - "GURPS.modifierJournalManager": "Registro de Balde de Modificadores", - "GURPS.modifierJournals": "Lista de Registro de Balde de Modificadores", - "GURPS.modifierLightDim": "Fogueira grande / tocha / pôr-do-sol / nascer do sol", - "GURPS.modifierLightFullMoon": "Lua cheia", - "GURPS.modifierLightHalfMoon": "Meia lua", - "GURPS.modifierLightMoonless": "Noite de lua nova com céu encoberto", - "GURPS.modifierLightNone": "Escuridão total", - "GURPS.modifierLightQuarterMoon": "Um quarto de lua", - "GURPS.modifierLightStarlight": "Luz das estrelas", - "GURPS.modifierLightStarlightClouds": "Luz das estrelas através das nuvens", - "GURPS.modifierLightTwilight": "Crepúsculo / luz de gás / lanterna", - "GURPS.modifierLightDeepTwilight": "Crepúsculo profundo / luz de velas", - "GURPS.modifierMightyBlow": "dano (Golpe Poderoso)", - "GURPS.modifierMoveAttack": "ao ataque (Avançar e Atacar)", - "GURPS.modifierOthers": "Outros Modificadores", - "GURPS.modifierPosture": "Posição", - "GURPS.modifierPostureCrouchMelee": "-2 no ataque em combate corpo a corpo (Agachado)", - "GURPS.modifierPostureCrouchRanged": "-2 no ataque em combate à distância (Agachado)", - "GURPS.modifierPostureKneelDefend": "-2 em defesas ativas (Ajoelhado/Sentado)", - "GURPS.modifierPostureKneelMelee": "-2 no ataque em combate corpo a corpo (Ajoelhado/Sentado)", - "GURPS.modifierPostureProneDefend": "-3 em defesas ativas (Deitado)", - "GURPS.modifierPostureProneMelee": "-4 no ataque em combate corpo a corpo (Deitado)", - "GURPS.modifierPostureProneRanged": "-2 no ataque em combate à distância (Deitado)", - "GURPS.modifierQuality": "Qualidade de Equipamento", - "GURPS.modifierQualityBest": "Melhor Possível", - "GURPS.modifierQualityFine": "Qualidade Superior (20× o custo)", - "GURPS.modifierQualityGood": "Qualidade Boa (5× o custo)", - "GURPS.modifierQualityImprovised": "Improvisado", - "GURPS.modifierQualityImprovTech": "Improvisado (tecnológica)", - "GURPS.modifierQualityMissing": "Partes Faltando/Danificadas", - "GURPS.modifierQualityNone": "Nenhuma", - "GURPS.modifierQualityNoneTech": "Nenhuma (tecnológica)", - "GURPS.modifierScaleLarge": "Grande (110%)", - "GURPS.modifierScaleNormal": "Normal (100%)", - "GURPS.modifierScaleSmall": "Pequeno (90%)", - "GURPS.modifierScaleVeryLarge": "Muito Grande (120%)", - "GURPS.modifierScaleVerySmall": "Muito Pequeno (80%)", - "GURPS.modifierSelectJournalButton": "Selecionar Registro de Balde", - "GURPS.modifierSelectJournals": "Balde: Registros", - "GURPS.modifierSelectJournalsAside": "Apenas registros 'padrão' (HTML) são válidos para visualização no Balde de Modificadores. Ex: PDFs não podem ser exibidos.", - "GURPS.modifierSelectJournalsHint": "Seleciona os registros de Diário para exibir no Balde de Modificadores.", - "GURPS.modifierSelectJournalsTitle": "Selecionar Registros de Balde de Modificadores", - "GURPS.modifierSendTo": "Enviar Balde de Modificadores para:", - "GURPS.modifierShieldDB": "para Esquiva (BD de Escudo)", - "GURPS.modifierShowOnMouseOver": "Balde: Exibir ao passar o mouse", - "GURPS.modifierShowOnMouseOverHint": "Se selecionado, a janela de Modificadores será exibida como uma dica de contexto: quando o cursor do mouse passar por cima do Balde de Modificadores. Se esta opção for desligada, você pode abrir a janela de modificadores clicando no ícone do Balde de Modificadores. Para esta configuração fazer efeito, é necessário reiniciar o Foundry.", - "GURPS.modifierSize": "Modificador de Tamanho", - "GURPS.modifierSizeDetail": "Diferença no Corpo a Corpo; Absoluta à Distância", - "GURPS.modifierSizeEntry": "{SM} Tamanho {us} ({metric})", - "GURPS.modifierStatus": "Estado", - "GURPS.modifierStatusAffliction": "Estado e Atribulações", - "GURPS.modifierStatusShock1": "-1 para testes de IQ/DX (Choque 1)", - "GURPS.modifierStatusShock2": "-2 para testes de IQ/DX (Choque 2)", - "GURPS.modifierStatusShock3": "-3 para testes de IQ/DX (Choque 3)", - "GURPS.modifierStatusShock4": "-4 para testes de IQ/DX (Choque 4)", - "GURPS.modifierStatusStunned": "-4 em defesas ativas (Atordoado)", - "GURPS.modifierStrongAttack": "dano (Ataque forte)", - "GURPS.modifierTabAside": "Utilizar Configurações de Sistema para definir os Registros de Diário a serem exibidos aqui.", - "GURPS.modifierTaskDifficulty": "Dificuldade da Tarefa", - "GURPS.modifierTelegraphicAttack": "ao ataque (Ataque Telegráfico)", - "GURPS.modifierToHit": "ao ataque", - "GURPS.modifierTrivial": "Trivial", - "GURPS.modifierUnfavorable": "Desfavorável", - "GURPS.modifierUserEntered": "Ou você pode inserir um Modificador", - "GURPS.modifierVeryEasy": "Muito Fácil", - "GURPS.modifierVeryFavorable": "Muito Favorável", - "GURPS.modifierVeryHard": "Muito Difícil", - "GURPS.modifierVeryUnfavorable": "Muito Desfavorável", - "GURPS.modifierViewScale": "Balde: Fator de Escala (EXPERIMENTAL)", - "GURPS.modifierViewScaleHint": "Utilize esta opção para aumentar ou diminuir o tamanho do Balde de Modificadores.", - "GURPS.modifierWillCheck": "Teste de VONT para manter bônus de Apontar", - "__PDF References__": "=========", - "GURPS.pdfAllOutDefense": "B366", - "GURPS.pdfBlockRetreat": "B377", - "GURPS.pdfCrippling": "B420", - "GURPS.pdfDeceptiveAttack": "B369", - "GURPS.pdfDeterminedAttack": "B365", - "GURPS.pdfDamageRoll": "B378", - "GURPS.pdfDodgeAcrobatic": "B374", - "GURPS.pdfDodgeDive": "B377", - "GURPS.pdfDodgeFailedAcro": "B375", - "GURPS.pdfDodgeRear": "B390", - "GURPS.pdfDodgeRetreat": "B375", - "GURPS.pdfDodgeSide": "B390", - "GURPS.pdfExtraEffort": "B356", - "GURPS.pdfGrappling": "B370", - "GURPS.pdfHazardCoughing": "B428", - "GURPS.pdfHazardDrowsy": "B428", - "GURPS.pdfHazardDrunk": "B428", - "GURPS.pdfHazardEuphoria": "B428", - "GURPS.pdfHazardNausea": "B428", - "GURPS.pdfHazardPain": "B428", - "GURPS.pdfHazardRetching": "B428", - "GURPS.pdfHazardTipsy": "B428", - "GURPS.pdfHeroicCharge": "MA131", - "GURPS.pdfHPT": "B63", - "GURPS.pdfKnockback": "B378", - "GURPS.pdfKnockdownStun": "B420", - "GURPS.pdfLPT": "B144", - "GURPS.pdfMajorWound": "B420", - "GURPS.pdfMightyBlow": "MA131", - "GURPS.pdfMoveAttack": "B365", - "GURPS.pdfPostureCrawling": "B551", - "GURPS.pdfPostureCrouching": "B551", - "GURPS.pdfPostureKneeling": "B551", - "GURPS.pdfPostureLyingDown": "B551", - "GURPS.pdfPostureSitting": "B551", - "GURPS.pdfReeling": "B419", - "GURPS.pdfShieldDB": "B374", - "GURPS.pdfShieldRush": "B372", - "GURPS.pdfShock": "B419", - "GURPS.pdfStrongAttack": "B365", - "GURPS.pdfSuffocation": "B437", - "GURPS.pdfTired": "B426", - "GURPS.pdfTelegraphicAttack": "MA113", - "GURPS.pdfTempAttribPenalties": "B421", - "GURPS.pdfVisibility": "B394", - "__Resolve Damage Dialog__": "=========", - "GURPS.RESOLVEDAMAGEMultiple": "Avaliações múltiplas", - "GURPS.RESOLVEDAMAGEPrompt": "O que você quer fazer com esta Avaliação de Dano?", - "GURPS.RESOLVEDAMAGEQuantity": "Número de avaliações:", - "GURPS.RESOLVEDAMAGESendTo": "Enviar Fórmula para...", - "GURPS.RESOLVEDAMAGETitle": "Explicar Avaliação de Dano", - "__Resource Trackers__": "=========", - "GURPS.resourceCopyTemplate": "Copiar Modelo", - "GURPS.resourceCurrentValue": "Valor Atual", - "GURPS.resourceDamageTracker": "Controle de Dano (dano é adicionado ao valor).", - "GURPS.resourceDamageType": "Usar como Tipo de Dano", - "GURPS.resourceDeleteTracker": "Apagar Controle", - "GURPS.resourceEditTracker": "Editar Controle", - "GURPS.resourceInvalidAlias": "Alias inválido: [{alias}].
São permitidos somente caracteres alfanuméricos e '+', '_', and '-'.", - "GURPS.resourceTemplateAlias": "Alias", - "GURPS.resourceTemplateButton": "Exibir e Editar Controles", - "GURPS.resourceTemplateClickToAdd": "Clique no botão '+', acima, para adicionar um modelo.", - "GURPS.resourceTemplateHint": "Use esta opção para criar, reutilizar e aplicar automaticamente Controles de Recursos a planilhas de personagem.", - "GURPS.resourceTemplateInitializer": "Inicializador", - "GURPS.resourceTemplateManager": "Configurar Controle de Recursos", - "GURPS.resourceTemplateSlot": "Posição Atribuída", - "GURPS.resourceTemplateTitle": "Modelos de Controle de Recursos", - "GURPS.resourceTracker": "Controle", - "GURPS.resourceTrackerEditor": "Editar Controle de Recursos", - "GURPS.resourceTrackers": "Controles de Recursos", - "GURPS.resourceUndefined": "Nenhum Definido", - "GURPS.resourceUpdateTrackerSlot": "Atualizar Posição de Controle", - "GURPS.slotNotUnique": "Já existe um controle designado para a posição Controle {value}.", - "GURPS.trackerNotUnique": "Nome do controle ({name}) ou alias ({alias}) não é único.", - "GURPS.resourceEnforceMinimum": "Forçar Mínimo", - "GURPS.resourceEnforceMaximum": "Forçar Máximo", - "GURPS.resourceTemplateName": "Nome do Modelo", - "Skill Names__": "=========", - "GURPS.skillAcrobatics": "Acrobacia", - "GURPS.skillJudo": "Judô", - "__Slam Calculator__": "=========", - "GURPS.slamAOAStrong": "Ataque Total (Forte)", - "GURPS.slamCalculator": "Calculadora de Encontrão", - "GURPS.slamForShieldDB": "BD de Escudo (Arremetida com Escudo)", - "GURPS.slamRelativeVelocity": "Velocidade Relativa", - "GURPS.slams": "dá um encontrão em", - "GURPS.slamShieldDB": "BD de Escudo", - "GURPS.slamVelocity": "Velocidade", - "__Status/Conditions__": "=========", - "GURPS.STATUSAgony": "Agonia", - "GURPS.STATUSAim": "Mirando", - "GURPS.STATUSBleed": "Sangrando", - "GURPS.STATUSBlind": "Cego(a)", - "GURPS.STATUSBurn": "Queimando", - "GURPS.STATUSCoughing": "Tossindo", - "GURPS.STATUSCounter": "Contra-ataque", - "GURPS.STATUSCrouch": "Agachado(a)", - "GURPS.STATUSDeaf": "Ensurdecido(a)", - "GURPS.STATUSDisable": "Desabilitado(a)", - "GURPS.STATUSDrowsy": "Sonolento(a)", - "GURPS.STATUSDrunk": "Bêbado(a)", - "GURPS.STATUSEuphoria": "Eufórico(a)", - "GURPS.STATUSExhausted": "Exausto(a)", - "GURPS.STATUSFall": "Caindo", - "GURPS.STATUSFly": "Voando", - "GURPS.STATUSGrapple": "Agarrado(a)", - "GURPS.STATUSKneel": "Ajoelhado(a)", - "GURPS.STATUSMildPain": "Dor Leve", - "GURPS.STATUSModeratePain": "Dor Moderada", - "GURPS.STATUSNauseated": "Nauseado(a)", - "GURPS.STATUSPin": "Fixado(a)", - "GURPS.STATUSPoison": "Envenenado(a)", - "GURPS.STATUSReeling": "Cambaleando", - "GURPS.STATUSRetching": "Vomitando", - "GURPS.STATUSSeverePain": "Dor Severa", - "GURPS.STATUSSilence": "Silenciado(a)", - "GURPS.STATUSSit": "Sentado(a)", - "GURPS.STATUSSleep": "Dormindo", - "GURPS.STATUSSprint": "Correndo em disparada", - "GURPS.STATUSStealth": "Furtivo(a)", - "GURPS.StatusStunnedMental": "Atordoamento Mental", - "GURPS.STATUSSuffocate": "Sufocando", - "GURPS.STATUSTerriblePain": "Dor Terrível", - "GURPS.STATUSTipsy": "Embriagado(a)", - "GURPS.STATUSWait": "Aguardando", - "__Maneuvers__": "=========", - "GURPS.maneuver": "Manobra", - "GURPS.maneuverDoNothing": "Fazer Nada", - "GURPS.maneuverMove": "Deslocamento", - "GURPS.maneuverAim": "Apontar", - "GURPS.maneuverChangePosture": "Mudança de Posição", - "GURPS.maneuverEvaluate": "Avaliar", - "GURPS.maneuverAttack": "Ataque", - "GURPS.maneuverFeint": "Fintar", - "GURPS.maneuverAllOutAttack": "Ataque Total", - "GURPS.maneuverAllOutAttackDetermined": "Ataque Total (Determinado)", - "GURPS.maneuverAllOutAttackDouble": "Ataque Total (Duplo)", - "GURPS.maneuverAllOutAttackFeint": "Ataque Total (Fintar)", - "GURPS.maneuverAllOutAttackStrong": "Ataque Total (Forte)", - "GURPS.maneuverAllOutAttackSuppressFire": "Ataque Total (Fogo de Retenção)", - "GURPS.maneuverMoveAttack": "Avançar e Atacar", - "GURPS.maneuverAllOutDefense": "Defesa Total", - "GURPS.maneuverAllOutDefenseDodge": "Defesa Total (Esquiva)", - "GURPS.maneuverAllOutDefenseParry": "Defesa Total (Aparar)", - "GURPS.maneuverAllOutDefenseBlock": "Defesa Total (Bloqueio)", - "GURPS.maneuverAllOutDefenseDouble": "Defesa Total (Dupla)", - "GURPS.maneuverReady": "Preparar", - "GURPS.maneuverConcentrate": "Concentrar", - "GURPS.maneuverWait": "Aguardar", - "__Import Messages__": "=========", - "GURPS.importCannotImportGCADirectly": "Não é possível importar um arquivo GCA diretamente. Por favor, exporte o arquivo utilizando a opção 'export to Foundry VTT.gce'.", - "GURPS.importCannotImportGCSDirectly": "Não é possível importar um arquivo GCS diretamente. Por favor, exporte o arquivo utilizando o modelo de saída para o 'Foundry VTT'.", - "GURPS.importGCA5ImprovedInventoryHandling": "Este arquivo foi criado por uma versão mais antiga do GCA5 Export que não lida bem com o texto do inventário.", - "GURPS.importCurrentVersions": "Versões Atualizadas: '{GCAVersion}' & '{GCSVersion}'.", - "GURPS.importErrorParsingXML": "Erro ao analisar o XML: {text}.", - "GURPS.importFantasyGroundUnsupported": "Não é mais possível importar um arquivo de Fantasy Grounds.", - "GURPS.importFileVersion": "Versão do arquivo: '{version}'.", - "GURPS.importGCABadBlockForDB": "Este arquivo foi criado por uma versão mais antiga do GCA Export que calcula incorretamente o valor de Bloqueio para itens com BD (como os Escudos).", - "GURPS.importGCANoBodyPlan": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não contém o atributo 'Tipo de Corpo'. Tentaremos adivinhar o Tipo de Corpo, mas pode ser que algo saia errado.", - "GURPS.importGCANoHideFlag": "Este arquivo foi criado por uma versão mais antiga do GCA Export que ignora a marcação de ocultação para vant/desv/qual/pecul.", - "GURPS.importGCAChildrenWeights": "Este arquivo for criado por uma versão mais antiga do GCA Export, que calculava incorretamente os pesos de equipamentos que continham outros equipamentos.", - "GURPS.importGCANoInnateRangedAndParent": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não exporta Ataques Inatos à distância e contém o Atributo 'Pai' para equipamento. Você pode errar ataques à distância ou certos equipamentos podem não aparecer no contêiner correto.", - "GURPS.importGCANoMeleeIfAlsoRanged": "Este arquivo foi criado por uma versão mais antiga do GCA Export que que pode não exportar um ataque corpo a corpo se ele também existir nos ataques à distância (como a Lança).", - "GURPS.importGCSNoMeleeRangedNotesForSameItem": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não exporta notas individuais nos ataques criadas pelo mesmo item.", - "GURPS.importGCANoParent": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não contém os atributos 'Pais' para Vants/Desvants, Perícias ou Mágicas.", - "GURPS.importGCANoSanitizedEquipmentPageRefs": "Este arquivo foi criado por uma versão mais antiga do GCA Export que pode, de maneira equívoca, colocar ataques à distância na lista de ataques corpo a corpo e não limpa as refs da página de equipamentos.", - "GURPS.importGCANoSanitizeNotes": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não limpa as Notas ou nomes de Vants/Desvants.", - "GURPS.importGCSNoParent": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não contém os atributos 'Pais'. Os itens não aparecerão em seus contêineres.", - "GURPS.importGCSNoSelfControl": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não contém os testes de Autocontrole para Desvantagens (ex: [CR: 9 Irritabilidade]).", - "GURPS.importGCSNoUses": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não contém a coluna 'USOS' na parte de Equipamentos.", - "GURPS.importGCAAdvMods": "Este arquivo foi criado por uma versão mais antiga do GCA Export que concatena os modificadores de Vantagens com os nomes das Vantagens, algo que pode resultar em nomes muito longos de Vantagens (e afetar o leiaute da planilha de personagem)", - "GURPS.importGCAConditionalModifiers": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não exporta Modificadores Condicionais", - "GURPS.importGenericError": "Houve um erro ao importar {name}, {error}:{message}.", - "GURPS.importNoCharacterFormat": "Incapaz de detectar o formato de 'personagem'. É possível que você esteja tentando importar o formato 'npc'.", - "GURPS.importNoXMLDetected": "Nenhum XML detectado. Você está importando o arquivo XML correto?", - "GURPS.importTooManyContainers": "Há níveis de contêineres em demasia. A importação do Foundry só suporta até 3 níveis de sub-contêineres.", - "GURPS.importSuccessful": "{name} importado com sucesso.", - "GURPS.importSeeUsersGuide": "Verifique o Manual do Usuário para detalhes de onde conseguir a última versão.", - "GURPS.importOldGCSFile": "Seu personagem foi salvo com uma versão mais antiga do GCS, que não exporta alguns dos atributos necessários. Atualize o GCS para no mínimo a versão 4.36, abra e salve o arquivo de personagem e então tente novamente.", - "GURPS.importNoJSONDetected": "Incapaz de analisar JSON. Seu arquivo do GCS aparenta estar corrompido.", - "__System Settings__": "=========", - "GURPS.settingShowReadMe": "Exibir 'Leia-Me' quando houver atualização", - "GURPS.settingHintShowReadMe": "Se marcado, o sistema vai exibir o arquivo 'Leia-Me' sempre que uma mudança de versão for detectada.", - "GURPS.settingRangeStrategy": "Combate: Estratégia de modificador de Distância", - "GURPS.settingHintRangeStrategy": "Configura a fórmula a ser utilizada para calcular as penalidades de distância.", - "GURPS.settingRangeStrategyStandard": "Tabela de Tamanho e Velocidade/Distância", - "GURPS.settingRangeStrategyRangeBands": "Bandas de Distância de Monster Hunters 2", - "GURPS.settingRangeStrategyTenPenalties": "-1 para cada 10 hexágonos/jardas/metros", - "GURPS.settingBasicPDFs": "PDF(s) do Módulo Básico", - "GURPS.settingHintBasicPDFs": "Selecione 'Combinado' ou 'Separado' e utilize os códigos de PDF associados quando for configurar o PDFoundry. Nota: Se você selecionar 'Separado', o PDF do Módulo Básico Campanhas deve abrir a partir da página 340 ao executar os testes do PDFoundry.", - "GURPS.settingBasicPDFsCombined": "Módulo Básico Combinado (código 'B')", - "GURPS.settingBasicPDFsSeparate": "Separado (Personagens, 'B'; Campanhas, 'BX')", - "GURPS.settingImportIgnoreName": "Importação: Ignorar atributo 'nome'", - "GURPS.settingHintImportIgnoreName": "Se marcado, o sistema vai ignorar o atributo 'nome' do Ator durante a importação. Isso é útil caso o nome que você utiliza no Foundry for diferente daquele que consta no GCA/GCS e se você não quiser ter que modificá-lo cada vez que fizer uma importação.", - "GURPS.settingBlockImport": "Apenas jogadores CONFIÁVEIS podem Importar", - "GURPS.settingHintBlockImport": "Se marcado, o botão 'Importar' só será exibido na planilha de personagem caso o jogador em questão possuir o nível de permissão 'Confiável', 'Assistente' ou 'GameMaster'", - "GURPS.settingImportHPAndFP": "Importação: PV e FP Atuais", - "GURPS.settingHintImportHPAndFP": "NOTA: Os PV e PF Atuais sempre serão copiados do arquivo durante a primeira importação.", - "GURPS.settingImportHPAndFPUseFile": "Utilizar os valores de PV e FP atuais do arquivo.", - "GURPS.settingImportHPAndFPIgnore": "Ignorar os valores de PV e FP atuais do arquivo.", - "GURPS.settingImportHPAndFPAsk": "Perguntar antes de sobrescrever durante a importação.", - "GURPS.settingImportBodyPlan": "Importar: Tipo de Corpo/Pontos de Impacto", - "GURPS.settingImportHintBodyPlan": "NOTA: O Tipo de Corpo sempre é copiado do arquivo durante a primeira importação.", - "GURPS.settingImportBodyPlanUseFile": "Utilizar o Tipo de Corpo que consta no arquivo de importação.", - "GURPS.settingImportBodyPlanIgnore": "Ignorar o Tipo de Corpo que consta no arquivo de importação.", - "GURPS.settingImportBodyPlanAsk": "Perguntar antes de sobrescrever durante a importação.", - "GURPS.settingShowNavigation": "Ator: Exibir navegação", - "GURPS.settingHintShowNavigation": "Se marcado, o rodapé de navegação será exibido na planilha de personagem completa do GCS.", - "GURPS.settingEnhancedInput": "Ator: Entradas numéricas melhoradas", - "GURPS.settingHintEnhancedInput": "Se marcado, certos campos (como PF) exibirão botões atalho de adição e subtração quando selecionados.", - "GURPS.settingCalculateEnc": "Ator: Calcular Base de Carga", - "GURPS.settingHintCalculateEnc": "Se marcado, o nível de Base de Carga será configurado automaticamente baseado no equipamento portado (e você não poderá modificar o nível de Base de Carga manualmente). Se desmarcado, você pode modificar o nível de Base de Carga clicando no nível desejado.", - "GURPS.settingUseEquipped": "Ator: Peso baseado no que estiver 'Equipado'", - "GURPS.settingHintUseEquipped": "Se marcado, APENAS itens 'Equipados' serão incluídos no cálculo de peso. Se desmarcado, todos os itens na lista de Equipamentos serão incluídos no cálculo de peso. Desmarque e os jogadores poderão utilizar a marcação de 'Equipado' para indicar que largaram o item.", - "GURPS.settingFlagUserCreated": "Ator: Marcar criações do Usuário", - "GURPS.settingHintFlagUserCreated": "Se marcado, um pequeno ícone vai aparecer na frente de equipamento criado pelo usuário (não importado) e antes de notas criadas pelo usuário.", - "GURPS.settingFlagItems": "Ator: Marcar Itens do Foundry", - "GURPS.settingHintFlagItems": "Se marcado, um pequeno ícone vai aparecer na frente de equipamento (e características) criadas a partir dos Itens do Foundry", - "GURPS.settingQtyItems": "Ator: Marcar QTD/Contagem salva", - "GURPS.settingHintQtyItems": "Se marcado, um pequeno ícone vai aparecer na frente de equipamento cuja QTD/Contagem será mantida durante importações", - "GURPS.settingConvertRanged": "Ator: Converter distância 'x2/x5' para jardas", - "GURPS.settingHintConvertRanged": "Se marcado, os campos de distância na forma 'xN' ou 'xN/xM' serão multiplicados pela ST do personagem para determinar a distância real para uma arma de arremesso. NOTA: Isto só acontece numa importação.", - "GURPS.settingShowDiceRoller": "IU: Exibir 3D6 (Próximo ao Balde de Modificadores)", - "GURPS.settingHintShowDiceRoller": "Se marcado, o sistema vai exibir o atalho de rolagem de dados à direita do Balde de Modificadores. Você deve recarregar o Foundry para essa configuração entrar em efeito.", - "GURPS.settingCombatInitiative": "Combate: Fórmula de Iniciativa", - "GURPS.settingHintCombatInitiative": "Trata-se da fórmula utilizada pelo Foundry para determinar a ordem dos turnos no combate. Aviso: Só mude isto se você souber o que está fazendo! Nós não avaliamos o que está aqui para determinar se está correto ou não. Deixe este campo em branco para redefinir a fórmula para a Sequência de Combate do GURPS, B362.", - "GURPS.settingDamageRestrictADD": "Dano: Restringir JAD para o MJ", - "GURPS.settingHintDamageRestrictADD": "Se marcado, só o MJ pode visualizar/utilizar a Janela de Avaliação de Dano. Jogadores de arrastarem e soltarem dano receberão uma mensagem.", - "GURPS.settingDamageSimpleADD": "Dano: JAD Simples", - "GURPS.settingHintDamageSimpleADD": "Se marcado, só exibirá a opção de 'Aplicar Diretamente' na Janela de Avaliação de Dano.", - "GURPS.settingDamageLocation": "Dano: Ponto de impacto padrão", - "GURPS.settingHintDamageLocation": "Configura o ponto de impacto padrão a ser utilizada nas avaliações de dano.", - "GURPS.settingDamageLocationTorso": "Tronco", - "GURPS.settingDamageLocationRandom": "Aleatório", - "GURPS.settingDamageAD": "Dano: Divisores de Armadura", - "GURPS.settingHintDamageAD": "Se marcado, ajusta a RD do alvo de acordo com o divisor de armadura do ataque.", - "GURPS.settingDamageBluntTrauma": "Dano: Trauma por Impacto", - "GURPS.settingHintDamageBluntTrauma": "Se marcado, serão utilizadas as regras de de Trauma por Impacto para cálculo de dano em armadura flexível.", - "GURPS.settingDamageLocationMods": "Dano: Mod. de Ferimento de acordo com Ponto de Impacto", - "GURPS.settingHintDamageLocationMods": "Se marcado, os Modificadores de Ferimento serão alterados baseados no Ponto de Impacto.", - "GURPS.settingDamageMath": "Dano: Exibir cálculos", - "GURPS.settingHintDamageMath": "Se marcado, a seção de 'EXIBIR CÁLCULOS' da mensagem de chat será, por padrão, expandida. Se desmarcado, você pode clicar no título 'EXIBIR CÁLCULOS' para expandi-lo. NOTA: Se ela for a última mensagem do chat, pode ser que ela se expanda para baixo do limite inferior da janela de chat, e pode ser que você precise rolar para baixo para visualizá-la.", - "GURPS.settingDamageCondInjury": "Dano: Lesão Condicional", - "GURPS.settingHintDamagCondInjury": "Da Pyramid #3/120: Lesão Condicional retira os Pontos de Vida do jogo como base para acompanhar as lesões, e os substitui por método baseado em efeitos, para fins de lesão.", - "GURPS.settingStatusWhisper": "Efeitos de Estado: Sussurro", - "GURPS.settingHintStatusWhisper": "Se marcado, mensagens de Efeitos de Estado (Choque, Ferimento Grave, etc.) serão enviadas ao dono do alvo como um Sussurro. De outra forma, elas serão enviadas como mensagens em off para todos.", - "GURPS.settingStatusReeling": "Efeitos de Estado: Cambaleando e Cansado Automáticos", - "GURPS.settingHintStatusReeling": "Se marcado, Cambaleando (1/2 deslocamento/esquiva) e Cansado (1/2 deslocamento/esquiva) serão automaticamente ativados quando o personagem ficar com PV e/ou FP abaixo de 1/3.", - "GURPS.settingPlayerBlindRoll": "Permitir rolagens às cegas para os Jogadores", - "GURPS.settingHintPlayerBlindRoll": "Se não estiver marcado, segurar a tecla SHIFT quando for fazer uma rolagem de dados resultará numa rolagem Oculta (só você pode ver, não importa quem você seja). Se marcado, quando os jogadores segurarem a tecla SHIFT eles farão uma Rolagem às Cegas (O MJ vê como uma Rolagem Oculta).", - "GURPS.settingPlayerChatPrivate": "Comandos privados no Chat de Jogadores", - "GURPS.settingHintPlayerChatPrivate": "Se marcado, a maioria dos comandos de chat (ex.: /hp, /fp, /qty, etc.) serão exibidas como sussurros para o jogador (ao invés de uma mensagem pública). Se você confia nos seus jogadores e não gosta de ver o chat repleto de comandos de chat, desative isto.", - "GURPS.settingMookGenerator": "Padrões do Gerador de Mook", - "GURPS.settingLabelMookGenerator": "Editor Padrão do Gerador de Mook", - "GURPS.settingHintMookGenerator": "Editar os valores iniciais do Gerador de Mook", - "GURPS.settingManeuverVisibility": "Visibilidade de Ícones de Manobra", - "GURPS.settingHintManeuverVisibility": "Determina quem pode ver o ícone de manobra de uma miniatura.", - "GURPS.settingManeuverNoOne": "Ninguém", - "GURPS.settingManeuverGMOnly": "Apenas MJ e Dono", - "GURPS.settingManeuverEveryone": "Todos", - "GURPS.settingManeuverDetail": "Detalhes de Visibilidade de Manobra", - "GURPS.settingHintManeuverDetail": "Determina qual manobra é visível para os jogadores que não sejam o MJ ou o Dono, se houver algum. 'Todos os Detalhes': Ex.:, mostrar \"Ataque Total (Determinado)\" e \"Fintar\" exatamente como exibidos. 'Sem Fintar': Como 'Todos os Detalhes', exceto que Fintar aparece como \"Ataque\". 'Geral': Como 'Completo, Sem Fintar' exceto que a opção não é exibida -- ex.:, Ataque Total (Forte) aparece como \"Ataque Total\". (O MJ e o Dono sempre veem Todos os Detalhes)", - "GURPS.settingManeuverDetailFull": "Todos os Detalhes", - "GURPS.settingManeuverDetailNoFeint": "Sem Fintar", - "GURPS.settingManeuverDetailGeneral": "Geral", - "GURPS.settingAutoIgnoreQty": "Importar: Salvar automaticamente a Qtd/Contagem do Foundry", - "GURPS.settingHintAutoIgnoreQty": "Se marcada, esta opção vai configurar automaticamente a opção 'Salvar QTD/Contagem atual na importação' em um determinado equipamento quando o usuário mudar a QTD/Contagem (e vai exibir um pequeno ícone azul de arquivo). NOTA: Isto não detecta mudanças nos 'Usos'. Se você precisar se lembrar dos 'Usos' entre as importações, você precisa configurar manualmente isso no equipamento.", - "GURPS.settingSheetDetail": "Planilha Rápida", - "GURPS.settingHintSheetDetail": "Seleciona a planilha de personagem que você deseja que seja a 'Planilha Rápida'. Ela será exibida na barra de título e o usuário pode escolher entre ela e a 'Planilha completa'", - "GURPS.settingImportEncoding": "Importar codificação de arquivo", - "GURPS.settingImportHintEncoding": "Se você estiver importando um personagem e caracteres unicode não estiverem sendo exibidos, modifique esta configuração para codificação UTF-8.", - "GURPS.settingImportEncodingISO8859": "ISO-8859-1 (default)", - "GURPS.settingImportEncodingUTF8": "UTF-8", - "GURPS.settingRemoveUnequipped": "Ator: Remover armas Não-Equipadas das listas de armas Corpo a Corpo e à Distância", - "GURPS.settingHintRemoveUnequipped": "Se marcado, os nomes dos ataques Corpo a Corpo e à Distância serão comparados à lista de equipamentos portados, e se for encontrada alguma equivalência, o ataque será listado somente se estiver Equipado", - "GURPS.settingImportBrowserImporter": "Utilizar janela de importação para não hospedado localmente", - "GURPS.settingImportHintBrowserImporter": "Marque isso se você NÃO estiver hospedando localmente sua instância do Foundry (você está hospedando externamente, como por exemplo na Oracle Cloud). Dessa forma, a janela de importação se lembrará da localização dos arquivos importados durante a sessão (o que significa que se você importar o personagem novamente, na mesma sessão, a janela de Arquivo não precisará ser aberta).", - "GURPS.settingShowChatReeling": "Exibir estado de Cambaleando/Cansado no Chat", - "GURPS.settingHintShowChatReeling": "Quando marcado, quaisquer mudanças no status de algum ator em relação ao estado de Cambaleando ou Cansado será exibida como mensagem de chat.", - "GURPS.settingDefaultADDAction": "Definir ação padrão para a Janela de Dano", - "GURPS.settingHintefaultADDAction": "Quando configurado para 'Alvo' o sistema vai escolher 'Aplicar' para PdJs e 'Aplicar Discretamente' para PdMs.", - "GURPS.settingApplyBasedOnTarget": "'Alvo'", - "GURPS.settingTokenOverrideRefresh": "Desconsiderar dimensionamento de miniatura", - "GURPS.settingHintTokenOverrideRefresh": "Se estiver \"ativado\", tentará desenhar as miniaturas para que se encaixem adequadamente na grade hexagonal. Ignora as funções de desenho do Foundry -- desative esta opção se houver qualquer comportamento inadequado nos desenhos do Foundry. Será necessário recarregar o mundo.", - "__Color Settings__": "=========", - "GURPS.settingColorSheetMenuTitle": "Cor da Planilha de Personagem", - "GURPS.settingColorSheetMenuHint": "Configuração de Cor da Planilha de Personagem", - "GURPS.colorSheetMenuOverride": "Desconsiderar Cores", - "GURPS.colorSheetMenuCustomColors": "Cores Personalizadas", - "GURPS.colorSheetMenuColorAreas": "Áreas de Cor", - "GURPS.colorSheetMenuAreasAttributesColor": "Cor dos Atributos", - "GURPS.colorSheetMenuAreasAttributesTextColor": "Cor do Texto dos Atributos", - "GURPS.colorSheetMenuAreasAttributesHoverColor": "Cor ao Passar o Mouse sobre os Atributos", - "GURPS.colorSheetMenuAreasAttributesHoverTextColor": "Cor do Texto ao Passar o Mouse sobre os Atributos", - "GURPS.colorSheetMenuAreasDodgeColor": "Cor da Esquiva", - "GURPS.colorSheetMenuAreasDodgeTextColor": "Cor do Texto da Esquiva", - "GURPS.colorSheetMenuAreasDodgeHoverColor": "Cor ao Passar o Mouse sobre a Esquiva", - "GURPS.colorSheetMenuAreasDodgeHoverTextColor": "Cor do Texto ao Passar o Mouse sobre a Esquiva", - "GURPS.colorSheetMenuAreasDamageColor": "Cor do Dano", - "GURPS.colorSheetMenuAreasDamageTextColor": "Cor do Texto do Dano", - "GURPS.colorSheetMenuAreasDamageHoverColor": "Cor ao Passar o Mouse sobre o Dano", - "GURPS.colorSheetMenuAreasDamageHoverTextColor": "Cor do Texto ao Passar o Mouse sobre o Dano", - "GURPS.colorSheetMenuAreasBlockColor": "Cor do Bloqueio", - "GURPS.colorSheetMenuAreasBlockTextColor": "Cor do Texto do Bloqueio", - "GURPS.colorSheetMenuAreasBlockHoverColor": "Cor ao Passar o Mouse sobre o Bloqueio", - "GURPS.colorSheetMenuAreasBlockHoverTextColor": "Cor do Texto ao Passar o Mouse sobre o Bloqueio", - "GURPS.colorSheetMenuAreasParryColor": "Cor de Aparar", - "GURPS.colorSheetMenuAreasParryTextColor": "Cor to Texto de Aparar", - "GURPS.colorSheetMenuAreasParryHoverColor": "Cor ao Passar o Mouse sobre Aparar", - "GURPS.colorSheetMenuAreasParryHoverTextColor": "Cor do Texto ao Passar o Mouse sobre Aparar", - "GURPS.colorSheetMenuAreasWeaponsColor": "Cor das Armas", - "GURPS.colorSheetMenuAreasWeaponsTextColor": "Cor do Texto das Armas", - "GURPS.colorSheetMenuAreasWeaponsHoverColor": "Cor ao Passar o Mouse sobre as Armas", - "GURPS.colorSheetMenuAreasWeaponsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Armas", - "GURPS.colorSheetMenuAreasSkillsColor": "Cor das Perícias", - "GURPS.colorSheetMenuAreasSkillsTextColor": "Cor do Texto das Perícias", - "GURPS.colorSheetMenuAreasSkillsHoverColor": "Cor ao Passar o Mouse sobre as Perícias", - "GURPS.colorSheetMenuAreasSkillsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Perícias", - "GURPS.colorSheetMenuAreasSpellsColor": "Cor das Mágicas", - "GURPS.colorSheetMenuAreasSpellsTextColor": "Cor do Texto das Mágicas", - "GURPS.colorSheetMenuAreasSpellsHoverColor": "Cor ao Passar o Mouse sobre as Mágicas", - "GURPS.colorSheetMenuAreasSpellsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Mágicas", - "GURPS.colorSheetMenuAreasOtfNotesColor": "Cor das Notas OtF", - "GURPS.colorSheetMenuAreasOtfNotesTextColor": "Cor do Texto das Notas OtF", - "GURPS.colorSheetMenuAreasOtfNotesHoverColor": "Cor ao Passar o Mouse sobre as Notas OtF", - "GURPS.colorSheetMenuAreasOtfNotesHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Notas OtF", - "GURPS.colorSheetMenuAreasAdsDisadsColor": "Cor das Vants/Desvants", - "GURPS.colorSheetMenuAreasAdsDisadsTextColor": "Cor do Texto das Vants/Desvants", - "GURPS.colorSheetMenuAreasAdsDisadsHoverColor": "Cor ao Passar o Mouse sobre as Vants/Desvants", - "GURPS.colorSheetMenuAreasAdsDisadsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Vants/Desvants", - "GURPS.adDisad": "Vantagem/Desvantagem", - "GURPS.adDisadQuirkPerk": "Vantagem/Desvantagem/Peculiaridade/Qualidade", - "GURPS.conditionalModifier": "Modificador Condicional", - "GURPS.delete": "Apagar", - "GURPS.fromEllipses": "de ...", - "GURPS.moveToOtherEquipment": "Mover para Outros Equipamentos", - "GURPS.sortAscending": "Organizar Crescente", - "GURPS.sortContentsAscending": "Organizar Conteúdo (Crescente)", - "GURPS.sortContentsDescending": "Organizar Conteúdo (Decrescente)", - "GURPS.sortDescending": "Organizar Decrescente", - "GURPS.actions": "Ações", - "GURPS.addAdvantage": "Adicionar Vantagem", - "GURPS.addMeleeAttack": "Adicionar Ataque Corpo a Corpo", - "GURPS.addRangedAttack": "Adicionar Ataque à Distância", - "GURPS.addRT": "Adicionar Controle de Recurso", - "GURPS.addSkill": "Adicionar Perícia", - "GURPS.addSpell": "Adicionar Mágica", - "GURPS.advantage": "Vantagem", - "GURPS.advantages": "Vantagens", - "GURPS.advantagesTab": "Vantagens e Desvantagens", - "GURPS.aim": "Apontar", - "GURPS.allDamage": "TODO DANO", - "GURPS.allOutDefense": "Defesa Total", - "GURPS.allTheDamage": "TODO O DANO!!", - "GURPS.applyAllToTarget": "Aplicar Tudo em {name}", - "GURPS.basic": "Básico", - "GURPS.bluntTrauma": "Trauma por Impacto", - "GURPS.bonuses": "Bônus", - "GURPS.check": "Teste", - "GURPS.check1": "Teste #1", - "GURPS.check2": "Teste #2", - "GURPS.check3": "Teste #3", - "GURPS.check4": "Teste #4", - "GURPS.clickToEdit": "Clique para Editar", - "GURPS.clickToRemove": "clique para remover", - "GURPS.collapse": "Desmaio", - "GURPS.color": "Cor", - "GURPS.combatTab": "Combate", - "GURPS.concentrationCheck": "Teste de Concentração", - "GURPS.condition": "Condição", - "GURPS.conditions": "Condições", - "GURPS.crippling": "Lesão incapacitante, ", - "GURPS.current": "Atual", - "GURPS.currentdodge": "Esquiva", - "GURPS.damageAbove": "Dano acima de ", - "GURPS.dead": "Morto(a)", - "GURPS.defense": "Defesa", - "GURPS.destroyed": "Destruído(a)", - "GURPS.Dice": "Dados", - "GURPS.during": "Durante", - "GURPS.dxCheckOrFallApplyProne": "{name}: faça um teste de DX ou sofra uma queda!", - "GURPS.dxJudoAcrobaticsCheckToRemainStanding": "Faça um teste de [DX, Judô, ou Acrobacia] {modifierText} para permanecer de pé.", - "GURPS.effectsNotApplicableDefenses": "Não se aplica a Defesas Ativas ou outras reações defensivas.", - "GURPS.effectsTemporaryAttributePenalties": "Ver Penalidades de Atributo Temporárias", - "GURPS.equipmentTab": "Equipamento", - "GURPS.equippedblock": "Bloqueio", - "GURPS.equippedparry": "Aparar", - "GURPS.fail": "Fracasso", - "GURPS.fallsDownApplyProne": "{name}: se deita!", - "GURPS.for": "para", - "GURPS.forHighPainThreshold": "{mod} para Hipoalgia", - "GURPS.forLowPainThreshold": "{mod} para Hiperalgia", - "GURPS.forPerfectBalance": "{mod} para Equilíbrio Perfeito", - "GURPS.chatGameAidUsersGuide": "GUIA DE USUÁRIO do Auxílio para GURPS 4e", - "GURPS.groundCreatures": "Criaturas Terrestres", - "GURPS.groundCreaturesSuffer": "Criaturas terrestres recebem", - "GURPS.headVitalsHit": "Acerto na cabeça ou orgãos vitais ", - "GURPS.highPainThresholdNoPenalty": "Hipoalgia ignora, sem penalidades", - "GURPS.hpIgnored": " PV são ignorados.", - "GURPS.htCheck": "Teste de HT", - "GURPS.ID": "ID", - "GURPS.itemBonusText": "Insira Fórmulas 'Bônus' On-the-Fly (uma por linha) para modificar valores de atributos, perícias, etc.", - "GURPS.itemEditor": "Editor de Itens", - "GURPS.itemFeatures": "Características", - "GURPS.itemImport": "Importar Biblioteca de Equipamentos", - "GURPS.knockback": "Projeção, {amount} {unit}", - "GURPS.knockbackCheck": "{name}: teste de {dx}, {acrobacia}, ou {judô} ou sofra uma queda!", - "GURPS.level": "Nív.", - "GURPS.lighting": "Iluminação", - "GURPS.location": "Ponto", - "GURPS.lowPainThresholdDoubles": "Hiperalgia duplica a penalidade", - "GURPS.majorWound": "Ferimento Grave", - "GURPS.majorWoundEffect": " para evitar Atordoamento ou Nocaute.", - "GURPS.majorWoundEffectLabel": "{name}: teste de {htCheck} para evitar Atordoamento/Nocaute.", - "GURPS.max": "Máx", - "GURPS.maximum": "Máximo", - "GURPS.melee": "Corpo a Corpo", - "GURPS.meleeAttack": "Ataque Corpo a Corpo", - "GURPS.meters": " metros", - "GURPS.minimum": "Mínimo", - "GURPS.minimumDamageRule": "* — Regra de dano mínimo aplicada.", - "GURPS.name": "Nome", - "GURPS.noModifier": "Sem Modificador", - "GURPS.normal": "Normal", - "GURPS.notAffected": "não é afetado(a).", - "GURPS.notes": "Notas", - "GURPS.ok": "OK", - "GURPS.overridden": "substituído", - "GURPS.pass": "Sucesso", - "GURPS.pdfPageReference": "Ref de Pág", - "GURPS.pdfRef": "Ref", - "GURPS.pointDamage": "{damage} ponto de dano", - "GURPS.pointsDamage": "{damage} pontos de dano.", - "GURPS.quantity": "Quantidade", - "GURPS.ranged": "À Distância", - "GURPS.rangedAttack": "Ataque à Distância", - "GURPS.rateOfFire": "Cadência de Tiro", - "GURPS.reaction": "Reação", - "GURPS.reference": "Referência", - "GURPS.removeItem": "Remover Item", - "GURPS.resolve": "Determinação", - "GURPS.resource": "Recurso", - "GURPS.roll": "Teste", - "GURPS.rolled": "Resultado", - "GURPS.rollForMe": "Rolar para mim", - "GURPS.selectToken": "Selecionar Miniatura", - "GURPS.shock": "Choque", - "GURPS.shockPenalty": "Penalidade (–{amount}) para DX e IQ.", - "GURPS.shockPenaltyNextTurnOnly": "{name}: –{modifier} para DX e IQ apenas no próximo turno.", - "GURPS.showQuestion": "Exibir?", - "GURPS.skill": "Perícia", - "GURPS.skillLevel": "Nível de Habilidade", - "GURPS.skillsTab": "Perícias", - "GURPS.spell": "Mágica", - "GURPS.spellsTab": "Mágicas", - "GURPS.statsTab": "Características", - "GURPS.suffersAMajorWound": "{name} sofre um Ferimento Grave", - "GURPS.suffersHeadVitalsWound": "{name} foi atingido(a) no(a) {location} com uma Penalidade de Choque.", - "GURPS.suffersKnockback": "{name} sofre uma Projeção {classStart}([PDF:{pdfref}]){classEnd} de {yards} {unit}.", - "GURPS.swimmerFlyer": "Nadador/Voador", - "GURPS.swimmersOrFlyersSuffer": "Nadadores ou voadores sofrem", - "GURPS.target": "Alvo", - "GURPS.targeting": "{name} é o alvo", - "GURPS.noTargetSelected": "Nenhum Alvo selecionado", - "GURPS.tired": "Cansado(a)", - "GURPS.toAllDXBasedRolls": " para todos os testes baseados em DX", - "GURPS.TransferTo": "Transferir para", - "GURPS.unconscious": "Inconsciente", - "GURPS.update": "Atualização", - "GURPS.warning": "AVISO", - "GURPS.yard": "jarda", - "GURPS.yards": "jardas", - "GURPS.addTracker": "Adicionar Controle de Recurso no final", - "GURPS.edit": "Editar", - "GURPS.moveToCarriedEquipment": "Mover para Equipamento Portado", - "GURPS.dragSameContainer": "Não é possível adicionar o objeto e este contêiner, pois ele já está dentro dele.", - "GURPS.dropResolve": "Onde você quer soltar este objeto?", - "GURPS.dropBefore": "Antes do alvo", - "GURPS.dropInside": "Dentro do alvo", - "GURPS.moveNone": "Nenhum ({reason})", - "GURPS.moveConstant": "{value} {unit}/seg ({reason})", - "GURPS.moveStep": "Passo ({reason})", - "GURPS.moveOneThird": "×1/3 ({reason})", - "GURPS.moveTwoThirds": "×2/3 ({reason})", - "GURPS.moveHalf": "Metade ({reason})", - "GURPS.moveFull": "Cheio", - "GURPS.setManeuver": "Configurar Manobra", - "GURPS.abbrevPoints": "Ptos", - "GURPS.abbrevReference": "Ref", - "GURPS.attributesSecondary": "Atributos Secundários", - "GURPS.attributesPrimary": "Atributos Básicos", - "GURPS.injury": "Lesão", - "GURPS.serverity": "Severidade", - "GURPS.days": "Dias", - "GURPS.none": "Nenhum", - "GURPS.equipmentCarried": "Equipamento Portado", - "GURPS.equipmentOther": "Outros Equipamentos", - "GURPS.equipmentUserCreated": "Criado pelo Usuário", - "GURPS.equipmentIgnoreQtyImport": "Importar não atualiza a quantidade.", - "GURPS.showFlightMove": "Exibir Desloc./Desloc. Aéreo", - "GURPS.rt": "CR", - "GURPS.thresholds": "Limites", - "GURPS.conditionalMods": "Modificadores Condicionais", - "GURPS.ignoreBodyPlan": "Ignorar Tipo de Corpo Importado", - "GURPS.abbrevRef": "Ref", - "GURPS.noteBlank": "Esta nota foi intencionalmente deixada em branco.", - "GURPS.pointsTotal": "Total de Pontos", - "GURPS.severities": "Severidades", - "GURPS.addAdjustedForDamageType": "‡ - Ajustado devido ao Modificador de Dano", - "GURPS.addDamageModifier": "Modificador de Dano", - "GURPS.reset": "Limpar Configuração", - "GURPS.resolveDiceRoll": "Qual Foi a Jogada?", - "GURPS.settingUsePhysicalDice": "Usar Dados Físicos", - "GURPS.settingHintUsePhysicalDice": "Se ativado, personagens de CONFIANÇA receberão uma notificação para todas as jogadas de dados. Dessa forma eles podem jogar dados físicos e inserir os resultados no Foundry.", - "GURPS.STATUSStanding": "Em Pé", - "GURPS.STATUSCrawling": "Rastejando", - "GURPS.STATUSProne": "Deitado", - "GURPS.effectHintBlind": "-6 na jogada de ataque se acostumado à cegueira; Audição -2 um sucesso reduz a penalidade na jogada de ataque para -4.", - "GURPS.effectChatModifiedToHit": "{displayName} :
[{modifier}]", - "GURPS.effectChatRangedModifier": "{displayName} :
[-2 nas jogadas de ataque feitas contra você com armas de combate à distância ({posture})].", - "GURPS.tokenToolsTitle": "Abrir Janela de Modificadores de Efeitos", - "GURPS.effectModifierPopout": "Modificadores de Efeitos", - "GURPS.effectModNoTokenSelected": "Nenhuma miniatura selecionada", - "GURPS.targetedModifiers": "Modificadores Escolhidos", - "GURPS.settingActiveEffects": "Acionar Efeitos Ativos", - "GURPS.targetModifiers": "Alvo:", - "GURPS.settingHintActiveEffects": "Permitir ao Mestre criar e aplicar Efeitos Ativos", - "GURPS.CR0": "CR: N/D (Incapaz de Resistir)", - "GURPS.CR6": "CR: 6 (Resiste Raramente)", - "GURPS.CR9": "CR: 9 (Resiste Com Alguma Frequência)", - "GURPS.CR12": "CR: 12 (Resiste Com Muita Frequência)", - "GURPS.CR15": "CR: 15 (Resiste Quase Sempre)", - "GURPS.modifiersBlindAttack": "-10 na jogada de ataque (Cego)", - "GURPS.modifiersBlindDefend": "-4 nas Defesas Ativas (Cego)", - "GURPS.moveModeGround": "Solo", - "GURPS.moveModeAir": "Ar", - "GURPS.moveModeWater": "Água", - "GURPS.moveModeSpace": "Espaço", - "GURPS.moveModeOther": "Outro...", - "GURPS.moveModeType": "Tipo de Deslocamento", - "GURPS.moveModeValue": "Metros/Turno", - "GURPS.effectsTermination": "Condição para Finalizar (OtF)", - "GURPS.effectsEffect": "Efeito", - "GURPS.default": "Predefinido", - "GURPS.conditionsCombatMove": "Deslocamento em Combate", - "GURPS.activeEffects": "Efeitos Ativos", - "GURPS.quicknotes": "Notas Rápidas", - "GURPS.language": "Idioma", - "GURPS.spoken": "Falado", - "GURPS.written": "Escrito", - "GURPS.pdfOffset": "Ajuste de página", - "GURPS.pdfCode": "Código do PDF", - "__Rolling__": "=========", - "GURPS.rollVs": "Rolagem contra", - "GURPS.rollNewTarget": "Novo alvo: ({target})", - "GURPS.rollCriticalSuccess": "Sucesso decisivo!", - "GURPS.rollSuccess": "Sucesso!", - "GURPS.rollFailure": "Falha!", - "GURPS.rollCriticalFailure": "Falha crítica!", - "GURPS.rollFail17": "17 e 18 sempre falham.", - "GURPS.rollJustMadeIt": "Por um triz", - "GURPS.rollMadeBy": "Margem de acerto {margin}.", - "GURPS.rollMissedBy": "Margem de fracasso {margin}.", - "GURPS.rollTotalHits": "{rofrcl} acertos possíveis ({link})
devido à CdT ({rof}) e o RCO ({rcl}).", - "GURPS.rollTotal": "Resultado da rolagem ({rolls}) = {rtotal}." + "__NOTE TO TRANSLATOR__": "If a given text is the same as the English (en.json), there is no need to include it here. It will fallback to en.json.", + "GURPS.title": "GURPS", + "GURPS.changelog": "LEIA-ME", + "GURPS.DontShowAgain": "Não exibir LEIA-ME novamente", + "GURPS.copyrightGURPS": "GURPS é marca registrada da Steve Jackson Games, que também detém direitos autorais sobre suas regras e arte. Todos os direitos reservados pela Steve Jackson Games. Este auxílio de jogo é criação original de Chris Normand/Nose66 e é distribuído gratuitamente, sendo vetada a venda, ver permissões em http://www.sjgames.com/general/online_policy.html", + "GURPS.copyrightGCS": "GCS© Todos os Direitos Reservados 1998-2020 Richard A. Wilkes.", + "__Char Sheet__": "=========", + "GURPS.portrait": "Retrato", + "__Character Sheet Identity__": "=========", + "GURPS.identity": "Identidade", + "GURPS.identityName": "Nome", + "GURPS.identityPlayer": "Jogador(a)", + "GURPS.identityTitle": "Título", + "__Character Sheet Miscellaneous__": "=========", + "GURPS.miscellaneous": "Diversos", + "GURPS.miscellaneousCreated": "Criação", + "GURPS.miscellaneousModified": "Modificação", + "GURPS.miscellaneousOptions": "Opções", + "__Character Description__": "=========", + "GURPS.description": "Descrição", + "GURPS.descriptionAge": "Idade", + "GURPS.descriptionAppearance": "Aparência", + "GURPS.descriptionBirthday": "Nascimento", + "GURPS.descriptionBodyPlan": "Tipo de Corpo", + "GURPS.descriptionEyes": "Olhos", + "GURPS.descriptionGender": "Gênero", + "GURPS.descriptionHair": "Cabelos", + "GURPS.descriptionHand": "Mão Hábil", + "GURPS.descriptionHeight": "Altura", + "GURPS.descriptionReligion": "Religião", + "GURPS.descriptionSizeModifier": "Mod. de Tamanho (MT)", + "GURPS.descriptionSkin": "Pele", + "GURPS.descriptionTechLevel": "Nível Tecnológico (NT)", + "GURPS.weight": "Peso", + "GURPS.share": "Compartilhar", + "__Character Points__": "=========", + "GURPS.point": "Ponto", + "GURPS.points": "Pontos", + "GURPS.pointsAdvantages": "Vantagens", + "GURPS.pointsAttributes": "Atributos", + "GURPS.pointsDisadvantages": "Desvantagens", + "GURPS.pointsQuirks": "Peculiaridades", + "GURPS.pointsRace": "Raça", + "GURPS.pointsSkills": "Perícias", + "GURPS.pointsSpells": "Magias", + "GURPS.pointsUnspent": "A Gastar", + "__Character Attributes__": "=========", + "GURPS.attributes": "Atributos", + "GURPS.attributesDX": "DX", + "GURPS.attributesDXNAME": "Destreza", + "GURPS.attributesFPNAME": "Pontos de Fadiga", + "GURPS.attributesHPNAME": "Pontos de Vida", + "GURPS.attributesHT": "HT", + "GURPS.attributesHTNAME": "Vitalidade", + "GURPS.attributesIQ": "IQ", + "GURPS.attributesIQNAME": "Inteligência", + "GURPS.attributesPER": "Per", + "GURPS.attributesPERNAME": "Percepção", + "GURPS.attributesST": "ST", + "GURPS.attributesSTNAME": "Força", + "GURPS.attributesWILL": "Vont", + "GURPS.attributesWILLNAME": "Vontade", + "GURPS.basicmove": "Desl. Básico", + "GURPS.basicspeed": "Vel. Básica", + "GURPS.speed": "Velocidade", + "GURPS.FP": "PF", + "GURPS.frightcheck": "Verif. de Pânico", + "GURPS.hearing": "Audição", + "GURPS.HP": "PV", + "GURPS.swing": "Golpe em Balanço", + "GURPS.tastesmell": "Paladar/Olfato", + "GURPS.thrust": "Golpe de Ponta", + "GURPS.touch": "Tato", + "GURPS.vision": "Visão", + "GURPS.attributesQN": "QN", + "GURPS.attributesQNNAME": "Quintessência", + "__ Character AddsDisadsPerksQuirks__": "=========", + "GURPS.advDisadvPerkQuirks": "Vantagens, Desvantagens, Qualidades e Peculiaridades", + "GURPS.highPainThreshold": "Hipoalgia", + "GURPS.lowPainThreshold": "Hiperalgia", + "GURPS.perfectBalance": "Equilíbrio Perfeito", + "__ Character Skills__": "=========", + "GURPS.rsl": "NH Rltv.", + "GURPS.SkillDXA": "DX/M", + "GURPS.SkillDXE": "DX/F", + "GURPS.SkillDXH": "DX/D", + "GURPS.SkillDXVH": "DX/MD", + "GURPS.SkillHTA": "HT/M", + "GURPS.SkillHTE": "HT/F", + "GURPS.SkillHTH": "HT/D", + "GURPS.SkillHTVH": "HT/MD", + "GURPS.SkillQNA": "QN/M", + "GURPS.SkillQNE": "QN/F", + "GURPS.SkillQNH": "QN/D", + "GURPS.SkillQNVH": "QN/MD", + "GURPS.SkillIQA": "IQ/M", + "GURPS.SkillIQE": "IQ/F", + "GURPS.SkillIQH": "IQ/D", + "GURPS.SkillIQVH": "IQ/MD", + "GURPS.SkillPerA": "Per/M", + "GURPS.SkillPerE": "Per/F", + "GURPS.SkillPerH": "Per/D", + "GURPS.SkillPerVH": "Per/MD", + "GURPS.skills": "Perícias", + "GURPS.SkillWillA": "Vont/M", + "GURPS.SkillWillE": "Vont/F", + "GURPS.SkillWillH": "Vont/D", + "GURPS.SkillWillVH": "Vont/MD", + "GURPS.sl": "NH", + "__Character Spells__": "=========", + "GURPS.spellClass": "Classe", + "GURPS.spellCollege": "Escola", + "GURPS.spellCost": "Custo", + "GURPS.spellDuration": "Duração", + "GURPS.spellMaintain": "Manutenção", + "GURPS.spells": "Mágicas", + "GURPS.spellTime": "Tempo", + "GURPS.spellResist": "Resistido Por", + "GURPS.spellDifficulty": "Dificuldade", + "__Character Equipment__": "=========", + "GURPS.equipment": "Equipamento", + "GURPS.otherEquipment": "Outros Equipamentos", + "GURPS.equipmentEquipped": "Eqpd", + "GURPS.equipmentQuantity": "Qtd", + "GURPS.equipmentUses": "Usos", + "GURPS.equipmentCost": "Custo", + "GURPS.equipmentMaxUses": "Máx de Usos", + "GURPS.equipmentTechlevel": "Nível Tecnológico", + "GURPS.equipmentFoundryItem": "Item do Foundry", + "__Character Encumbrance/Lift__": "=========", + "GURPS.basicLift": "Base de Carga", + "GURPS.carryOnBack": "Carregar nas Costas", + "GURPS.dodge": "Esquiva", + "GURPS.encumbranceMoveDodge": "BC, Deslocamento e Esquiva", + "GURPS.liftingAndMovingThings": "Levantar e Mover Objetos", + "GURPS.maxload": "Carga Máx", + "GURPS.move": "Desl.", + "GURPS.oneHandLift": "Levantar com UMA mão", + "GURPS.runningShoveAndKnockOver": "Encontrão e Derrubar", + "GURPS.shiftSlightly": "Mover Ligeiramente", + "GURPS.shoveAndKnockOver": "Empurrar e Derrubar", + "GURPS.twoHandLift": "Levantar com DUAS mãos", + "__Character Weapons__": "=========", + "GURPS.acc": "Prec", + "GURPS.block": "Bloqueio", + "GURPS.blockbonus": "Bônus de Bloqueio", + "GURPS.bulk": "Magnitude", + "GURPS.damage": "Dano", + "GURPS.meleeWeapons": "Armas de Combate Corpo a Corpo", + "GURPS.parry": "Aparar", + "GURPS.parrybonus": "Bônus de Aparar", + "GURPS.range": "Distância", + "GURPS.rangedWeapons": "Armas de Combate à Distância", + "GURPS.rcl": "Rco", + "GURPS.reach": "Alcance", + "GURPS.rof": "CdT", + "GURPS.shots": "Tiros", + "GURPS.usage": "Uso", + "__Apply Damage Dialog__": "=========", + "GURPS.addAbbrev": "Abrev", + "GURPS.addAdditionalStackingModifier": "Modificadores adicionais", + "GURPS.addAdjustedForHitLocation": "* - Ajustado para Ponto de Impacto", + "GURPS.addAdjustedForInjuryTolerance": "† - Ajustado para Tolerância a Ferimentos", + "GURPS.addApply": "Aplicar", + "GURPS.addApplyAndKeep": "Aplicar/Manter Aberto", + "GURPS.addApplyDamageDialog": "Janela de Avaliação de Dano", + "GURPS.addApplyDamageOptions": "OPÇÕES DE APLICAÇÃO DANO", + "GURPS.addApplyInjury": "Aplicar Dano", + "GURPS.addApplyInjuryAndKeep": "Aplicar Dano/Manter Aberto", + "GURPS.addApplyInjuryQuietly": "Aplicar Dano (Discretamente)", + "GURPS.addApplyInjuryQuietlyAndKeep": "Aplicar Dano (Discretamente)/Manter Aberto", + "GURPS.addApplyMultipleTimes": "Aplicar múltiplas vezes", + "GURPS.addApplyOptionsToAll": "Estas opções se aplicam a todo dano", + "GURPS.addApplyQuietly": "Aplicar (Discretamente)", + "GURPS.addApplyQuietlyAndKeep": "Aplicar (Discretamente)/Manter Aberto", + "GURPS.addApplyTo": "Aplicar em", + "GURPS.addArmorDivisor": "Divisor de Armadura", + "GURPS.addBasicDamage": "Dano Básico", + "GURPS.addCalculationAndResults": "Cálculos e Resultados", + "GURPS.addDamageReduction": "Redução de Dano", + "GURPS.addDamageType": "Tipo de Dano", + "GURPS.addDiffuseMax": "Difuso, dano máximo", + "GURPS.addDirectlyApply": "APLICAR DIRETAMENTE", + "GURPS.addEnterModifier": "Informe modificador", + "GURPS.addExplosion": "Explosão", + "GURPS.addExplosionHex": "{hex} hexágono do centro", + "GURPS.addExplosionHexes": "{hex} hexágonos do centro", + "GURPS.addFlexibleArmor": "Armadura Flexível", + "GURPS.addHardenedDRLevel": "RD para Enrijecido", + "GURPS.addHitLocationAndDR": "Ponto de Impacto e RD", + "GURPS.addHitLocationWoundModifiers": "Modificadores de Lesão conforme Ponto de Impacto", + "GURPS.addInjury": "Lesão", + "GURPS.addInjuryTolerance": "Tolerância a Ferimentos", + "GURPS.addInjuryToleranceDiffuse": "Difuso", + "GURPS.addInjuryToleranceHomogenous": "Homogêneo", + "GURPS.addInjuryToleranceUnliving": "Não-vivo", + "GURPS.addLargeAreaInjury": "Lesão em Grande Escala", + "GURPS.addLocationMax": "Dano máximo ao ponto", + "GURPS.addOverrideDR": "Desprezar a RD para o Ponto", + "GURPS.addPenetrating": "Penetrante", + "GURPS.addRangedHalfDamage": "Atq. à Distância, Metade do Dano (1/2D)", + "GURPS.addRangedHalfDamageShort": "Atq. à Distância (1/2D)", + "GURPS.addShotgunCloseRange": "Espingarda, à Queima-Roupa", + "GURPS.addShotgunDamage": "Dano de Espingarda", + "GURPS.addShotgunRofMultiplier": "Multiplicador por CdT", + "GURPS.addSingleRollSelected": "Uma avaliação de dano selecionada", + "GURPS.addSpecialCombatSituations": "Situações Esp. de Combate", + "GURPS.addTacticalRules": "Regras Táticas", + "GURPS.addTacticalRulesDefaults": "Usar definições do sistema como padrão", + "GURPS.addTitle": "Aplicar {basic} ponto(s) de dano [{damage}] a {name}", + "GURPS.addTitleConcat0": "Aplicar", + "GURPS.addTitleConcat01": "ponto de ", + "GURPS.addTitleConcat0s": "pontos de ", + "GURPS.addTitleConcat1": "dano a {name}", + "GURPS.addTypeAndWoundingModifiers": "Mod. de Ferimento e Lesão", + "GURPS.addVulnerability": "Vulnerabilidade", + "GURPS.addWHard": "c/ Rígido", + "__Body Plan__": "=========", + "GURPS.BODYPLANarachnoid": "Aracnídeo", + "GURPS.BODYPLANavian": "Aviário", + "GURPS.BODYPLANcancroid": "Cancroide", + "GURPS.BODYPLANcentaur": "Centauro", + "GURPS.BODYPLANhexapod": "Hexápode", + "GURPS.BODYPLANhexapodWinged": "Hexápode Alado", + "GURPS.BODYPLANhumanoid expanded": "Humanoide, Expandido (GCA)", + "GURPS.BODYPLANhumanoid": "Humanoide", + "GURPS.BODYPLANichthyoid": "Ictioide", + "GURPS.BODYPLANoctopod": "Octópode", + "GURPS.BODYPLANquadruped": "Quadrúpede", + "GURPS.BODYPLANquadrupedWinged": "Quadrúpede Alado", + "GURPS.BODYPLANscorpion": "Escorpião", + "GURPS.BODYPLANsnakeman": "Homem-Cobra", + "GURPS.BODYPLANsquid": "Cefalópode", + "GURPS.BODYPLANvermiform": "Vermiforme", + "GURPS.BODYPLANvermiformWinged": "Vermiforme Alado", + "GURPS.BODYPLANwinged humanoid": "Humanoide Alado", + "__Chat Messages__": "=========", + "GURPS.chatClearing": "Limpando", + "GURPS.chatClearingLastActor": "Limpando Último Ator", + "GURPS.chatDamageResultEnd": "em {location}", + "GURPS.chatDamageResultMiddle": "pontos de dano por {type}", + "GURPS.chatDamageResultShowMath": "Exibir cálculos", + "GURPS.chatDamageResultStart": "inflige {injury} em {defender}", + "GURPS.chatDoesNotHaveEnough": "não há 'USES' suficientes", + "GURPS.chatExceededMax": "MAX excedido", + "GURPS.chatExceededMaxUses": "'MAX USES' excedidos.", + "GURPS.chatFixedDamage": "[{dice} {damageTypeText}] dano.", + "GURPS.chatLightSource": "Selecione a fonte de luz que a miniatura selecionada está segurando.", + "GURPS.chatMoreThanOneActor": "Mais de um Ator encontrado nesses parâmetros", + "GURPS.chatMoreThanOneToken": "Mais de uma Miniatura encontrada nesses parâmetros", + "GURPS.chatMultipleOwnedFound": "Você possui mais de uma miniatura nesta cena. Você pode ou selecionar uma delas e tentar este comando novamente sem a palavra-chave '@self', ou usar a opção ':name'.", + "GURPS.chatMustBeACheck": "A fórmula On-the-Fly deve ser algum tipo de teste", + "GURPS.chatNoActorFound": "Não foram encontrados nenhum Ator/Miniatura que correspondam", + "GURPS.chatNoEquipmentMatched": "Nenhum equipamento corresponde", + "GURPS.chatNoResourceTracker": "Não há Controle de Recursos correspondente", + "GURPS.chatNoStatusMatched": "Nenhuma condição correspondente", + "GURPS.chatNoOwnedTokenFound": "Você não possui miniaturas nesta cena.", + "GURPS.chatNoTokens": "Seu personagem não possui miniatura. É necessária uma miniatura para aplicar uma condição", + "GURPS.chatQty": "QTD", + "GURPS.chatQtySetTo": "QTD definido para", + "GURPS.chatResetTo": "redefinido para", + "GURPS.chatResourceTracker": "Controle de Recursos", + "GURPS.chatResultBelowZero": "Resultado abaixo de zero", + "GURPS.chatRolling": "Rolando [{dice}{desc}]", + "GURPS.chatRollingDamage": "Jogando [{dice} {damageTypeText}] dano.", + "GURPS.chatRollingCR": "Teste de Autocontrole", + "GURPS.chatSetTo": "definido para", + "GURPS.chatSelectSelfOrNameTokens": "Você deve selecionar uma miniatura ou utilizar '{self}', ou ':<token-name>' para aplicar efeitos de condição.", + "GURPS.chatShock": "{name} sofre {modifier} pontos de Choque ", + "GURPS.chatSuffersCripplingInjury": "{name} sofre um ferimento incapacitante {classStart}([PDF:{pdfref}]){classEnd} no ponto de impacto {location}.", + "GURPS.andHalfMove": "e metade do Deslocamento.", + "GURPS.chatToApplyEffects": "para aplicar efeito de condição", + "GURPS.chatTokenLightPicker": "Seletor de Iluminação de Miniatura", + "GURPS.chatToggling": "Alternando", + "GURPS.chatTurnOnReeling": "{name} está Cambaleando. Deslocamento e Esquiva caem pela metade. {classStart}([PDF:{pdfref}]){classEnd}", + "GURPS.chatTurnOnTired": "{name} está Cansado(a). Deslocamento, Esquiva e ST caem pela metade. {classStart}([PDF:{pdfref}]){classEnd}", + "GURPS.chatTurnOffReeling": "{name} não está mais Cambaleando.", + "GURPS.chatTurnOffTired": "{name} não está mais Cansado(a).", + "GURPS.chatUnableToFindMacro": "Incapaz de encontrar macro chamada", + "GURPS.chatUnableToFindManeuver": "Incapaz de encontrar manobra chamada", + "GURPS.chatNotInCombat": "Você só pode configurar a Manobra se a miniatura estiver em combate", + "GURPS.chatUnrecognizedFormat": "Formato não reconhecido", + "GURPS.chatUses": "'USES'", + "GURPS.chatUsesIsNaN": "'USES' não é um número", + "GURPS.chatUsesReset": "'USES' redefinidos para 'MAX USES'", + "GURPS.chatUsesSet": "'USES' definidos para", + "GURPS.chatYouDoNotHaveEnough": "Você não tem o suficiente", + "GURPS.chatYouMustBeGM": "Você precisa ser MJ para executar esse comando", + "GURPS.chatYouMustHaveACharacterSelected": "Você precisa selecionar um personagem", + "GURPS.chatYouMustSelectTokens": "É preciso selecionar uma miniatura (ou usar", + "GURPS.chatHelpHelp": "/help comando de chat: para ver a ajuda para esse cmd\n\n?comando de chat: para ver a ajuda para esse comando", + "GURPS.chatHelpSound": "Tocar um som no fundo
parâmetros:\nw: esperar segundos antes de começar o som\nv: volume\n<caminho completo e nome do arquivo>
exemplos:\n/sound w2.5 /caminho/nome-do-arquivo\n/sound v0.6 /caminho/nome-do-arquivo\n/sound w3 v2 /caminho/nome-do-arquivo", + "GURPS.chatHelpW": "Sussurrar aos jogadores ou aos donos das miniaturas selecionadas
parâmetros:\n<[nomes de jogadores]>\n@: sussurrar aos donos das miniaturas selecionadas\n
exemplos:\n/w [Cris] msg enviada ao jogador Cris\n/w @ msg enviadas aos donos das miniaturas selecionadas", + "GURPS.chatHelpWait": "Aguarde X milissegundos antes de executar o próximo comando de chat
parâmetros:\nX: o número de milissegundos a aguardar\n
exemplos:\n/wait 500", + "GURPS.chatHelpRa": "Fazer Um Teste (ou Fazer Um Teste Particular)
parâmetros:\nX: NH do teste\nNomeDaPerícia-X: Fazer um teste de X, mas exibir 'NomeDaPerícia' ao invés de 'Predefinido'\n
exemplos:\n/ra 12\n.ra 13\n/pra 11\n.pra 10\n/ra Furtividade-12\n.ra Briga-13\n/pra Armadilhas-11\n.pra SacarRápido-10", + "GURPS.chatHelpFpHp": "Aplicar fórmula aos PF ou PV dos personagens selecionados
parâmetros:\n<fórmula>\nreset: Redefinir PF(FP) ou PV(HP) de volta ao valor inicial
exemplos:\n/fp +1\n/hp -1\n/fp +1d\n/hp +1d-3!\n/fp reset\n", + "GURPS.chatHelpSelect": "Selecionar miniatura(s)
parâmetros:\n<nome do personagem>\n@self: selecionar a miniatura do personagem selecionado\n!:selecionar em todas as cenas, não apenas na atual
exemplos:\n/select Bog\n/select @self\n/select Bog !", + "GURPS.chatHelpUses": "Modificar a coluna USOS de um equipamento
parâmetros:\n<formula>\n<equipamento>\no:<equipamento>: buscar apenas na lista 'outros'\nreset: definir os USOS para o MÁX_USOS
exemplos:\n/uses +1 equipamento\n/uses -2 equipamento\n/uses =20 equipamento\n/uses +1 o:equipamento\n/uses reset equipamento", + "GURPS.chatHelpQty": "Modificar a coluna QTD de um equipamento
parâmetros:\n<fórmula>\n<equipamento>\no:<equipamento>: buscar apenas na lista 'outros'
exemplos:\n/qty +1 equipamento\n/qty -2 equipamento\n/qty =20 equipamento\n/qty +1 o:equipamento", + "GURPS.chatHelpLight": "Configurar o nível de luz de uma miniatura
parâmetros:\nnone|off: desligar a luz\nX: raio de baixa luminosidade\nY: raio de luz plena\nZ: transmitir ângulo de luz \n#RRGGBB: cor da luz\nW: intensidade da cor (0.0-1.0)\n<anim>: padrão de animação (torch (tocha), pulse (pulso), chroma (colorido), wave (onda), fog (névoa), sunburst (clarão de sol), dome (domo), emanation (emanação), hexa (hexagonal), ghost (fantasmagórico), energy (energia), roiling (turvo), hole (buraco)\nSPEED: velocidade da animação (1-10)\nINT: intensidade da animação (1-10)
exemplos:\n/li 6 2\n/li 8 3 90\n/li 6 2 #ff0000\n/li 6 2 #ff1111 0.5\n/li 6 2 torch\n/li 8 4 90 #ff7777 0.5 pulse 5 5\nhttps://foundryvtt.com/article/lighting/", + "GURPS.chatHelpTracker": "Modificar o Controle de Recursos
formato do comando:\n/tr0-3\n/tracker0-3\n/resource0-3\n/rt0-3\n/tr(nome)\n/tracker(nome)\n/resource(nome)\n/rt(nome)
parâmetros:\n<fórmula>\nreset: redefine o Controle ao valor inicial
exemplos:\n/tr0 +1\n/tr0 -2\n/tracker1 =20\n/tr(arrows) +1\n/resource(rounds) reset", + "GURPS.chatHelpStatus": "Configurar o efeito de status de uma miniatura
parâmetros:\ntoggle|t: alterna o status\non|+|set: aciona o status\noff|-|unset: desliga o status\nclear: remove todos os status\n@self / :nome da miniatura\nlist: exibe todos os nomes de status\n{JSON data}: dados opcionais de 'duration.combat' (duração de combate)
exemplos:\n/st on prone Bog\n/st - shock1 @self\n/st list", + "GURPS.chatHelpRemote": "Executar uma fórmula On-the-Fly remotamente
parâmetros:\n[OtF]: fórmula On-the-Fly\n<player names>|blank: list of player names (or blank to send to all players)
examples:\n/rem [‏PER] Chris\n/rem [‏ST+2]", + "GURPS.chatHelpEveryone": "Aplicar fórmula aos PF(FP) ou PV(HP) de todos os personagens dos jogadores ou executar uma fórmula On-the-Fly localmente contra todos os personagens dos jogadores
parâmetros:\nfp <fórmula>\nhp <fórmula>\n [OtF]: executar fórmula OtF (localmente) para todos os personagens dos jogadores\nfp reset: Redefinir os PF de volta ao valor inicial\nhp reset: Redefinir os PV de volta ao valor inicial
exemplos:\n/ev fp +1\n/ev hp -1\n/ev fp +1d\n/ev hp +1d-3!\n/ev fp reset\n/ev [‏PER]", + "GURPS.chatHelpAnim": "Tocar uma animação centralizada ou que se move.\n
parâmetros (para ambos)\nlist: exibir uma lista de animações disponíveis\nwX: aguardar X segundos antes de exibir a animação\n<NomeDoArquivo pattern>: 'pattern' pode conter *\nXx:Y: repetir animação X vezes (2x, 3x, etc.) com Y segundos de atraso entre as animações\n
parâmetros para animações centralizadas:\nc: indica uma animação centralizada\n*X: mudar a escala da animação em X\n@self: utilizar a si mesmo como centro, ao invés do alvo\nA opção a seguir pode ser adicionada após o 'c'\n f: vira a animação no eixo x (esquerda para a direita)\n m: desloca a animação centralizada até o alvo\n n: não rotaciona a animação centralizada em deslocamento\n X: número de graus a rotacionar a animação\n :Y,Z: compensar posição da animação (padrão 0.5,0.5)\n
exemples de animações centralizadas:\n/anim <pattern> c *0.5 3x\n'centralizada, escala: 1/2, 3 vezes'\n\n/anim <pattern> cf *2 3x:4\n'centralizada, virada (esquerda-direita), escala: 2x, 3 vezes com atraso de 4 segundos\n\n/anim <pattern> cm\n'centralizada, animação se desloca de si mesmo até o alvo'\n\n/anim <pattern> cmn\n'centralizada, animação se desloca de si mesmo até o alvo, sem rotacionar'\n\n/anim <pattern> cfm\n'centralizada, virada, animação se desloca de si mesmo até o alvo'\n\n/anim <pattern> c90\n'centralizada, rotacionada 90 graus'\n\n/anim <pattern> cf180 *.333\n'centralizada, virada, rotacionada 180 graus, escala: 1/3'\n\n/anim <pattern> cm45\n/anim <pattern> c:0,1\n/anim <pattern> cf:0.5,1\n/anim <pattern> cmn:0.9,1 *2\n
parâmetros para uma animação que se move:\n-X: mover-se à esquerda (0.0-1.0) em direção ao início da animação\n+X: esticar para a direita (0.0-infinito) em direção ao destino\n
exemplos de animações que se movem:\n/anim <pattern> -0.1 +0.1 2x\n'animação que se move, mover-se à esquerda 10%, esticar à direita 10%, 2 vezes'", + "GURPS.chatHelpShow": "Exibe vários valores de miniaturas na cena
parâmetros:\n<Atributos (primários e secundários)>\n<Nome de perícias>\nparry (aparar)\nblock (bloqueio)\nwill (vont)\nfright (verif. de pânico)\nper\nvision (visão)\nhearing (audição)\ntaste (paladar)\nsmell (olfato)\nmove (deslocamento)\nspeed (velocidade)
exemplos:\n/show HP FP IQ\n/show Furtividade PER\n/show per move speed\n/show vision hearing", + "GURPS.chatHelpManeuver": "Configurar as seguintes manobras ao personagem selecionado. Você pode usar * para ligar nomes de Manobras, por exemplo: '/man All Out*Double'
", + "GURPS.chatHelpRepeat": "Repetir o seguinte comando /anim com um atraso de X segundos entre cada execução.
exemplos:\n/repeat /anim 1.2 heal*blue c", + "GURPS.chatWantsToExecute": "Deseja executar {command} em {name},

Você aceita?", + "__Permissions__": "=========", + "GURPS.cannotDragNonFoundryEqt": "Você não pode arrastar equipamento que não é do Foundry para outro personagem.", + "GURPS.youDoNotHavePermssion": "Você não tem permissão para fazer isso.", + "__Damage Types__": "=========", + "GURPS.damageAbbrevburn": "qmd", + "GURPS.damageAbbrevcor": "cor", + "GURPS.damageAbbrevcr": "cont", + "GURPS.damageAbbrevcut": "corte", + "GURPS.damageAbbrevdmg": "dano", + "GURPS.damageAbbrevfat": "fad", + "GURPS.damageAbbrevimp": "perf", + "GURPS.damageAbbrevinjury": "lesão", + "GURPS.damageAbbrevpi-": "pa-", + "GURPS.damageAbbrevpi": "pa", + "GURPS.damageAbbrevpi+": "pa+", + "GURPS.damageAbbrevpi++": "pa++", + "GURPS.damageAbbrevtox": "tox", + "GURPS.damageTypeBurning": "Queimadura", + "GURPS.damageTypeCorrosive": "Corrosão", + "GURPS.damageTypeCrushing": "Contusão", + "GURPS.damageTypeCutting": "Corte", + "GURPS.damageTypeDamage": "Dano", + "GURPS.damageTypeFatigue": "Fadiga", + "GURPS.damageTypeHuge Piercing": "Extremamente Perfurante", + "GURPS.damageTypeImpaling": "Perfuração", + "GURPS.damageTypeInjury": "Lesão", + "GURPS.damageTypeLarge Piercing": "Muito Perfurante", + "GURPS.damageTypePiercing": "Perfurante", + "GURPS.damageTypeSmall Piercing": "Pouco Perfurante", + "GURPS.damageTypeToxic": "Toxina", + "__Drag Ruler__": "=========", + "GURPS.dragrulerFly": "Voo", + "GURPS.dragrulerSprint": "Disparada", + "GURPS.dragrulerWalk": "Caminhada", + "__Fantastic Dungeon Grappling__": "=========", + "GURPS.grapplingControlled": "Sendo controlado(a)", + "GURPS.grapplingControlPoints": "Pontos de Controle", + "GURPS.grapplingCPAbbrev": "ctrle", + "GURPS.grapplingGrabbed": "Sendo segurado(a)", + "GURPS.grapplingGrappled": "Agarrado(a)", + "GURPS.grapplingPinned": "Imobilizado(a)", + "GURPS.grapplingRestrained": "Preso(a)", + "GURPS.grapplingUnrestrained": "Livre", + "__Hit Location__": "=========", + "GURPS.hitLocation": "Ponto de Impacto", + "GURPS.hitLocationArm 1-2": "Braço 1-2", + "GURPS.hitLocationArm 3-4": "Braço 3-4", + "GURPS.hitLocationArm 5-6": "Braço 5-6", + "GURPS.hitLocationArm 7-8": "Braço 7-8", + "GURPS.hitLocationArm, holding shield": "Braço, com escudo", + "GURPS.hitLocationArm": "Braço", + "GURPS.hitLocationArm*": "Braço", + "GURPS.hitLocationBrain": "Cérebro", + "GURPS.hitLocationChest": "Peito", + "GURPS.hitLocationChinks in Torso": "Fendas em armadura (tronco)", + "GURPS.hitLocationChinks in Other": "Fendas em armadura (outros)", + "GURPS.hitLocationDescChest": "*acerto no peito", + "GURPS.hitLocationDescFront": "apenas frente", + "GURPS.hitLocationDescHalfDR": "½ RD", + "GURPS.hitLocationDescImp": "perf or pa(qualquer) apenas", + "GURPS.hitLocationDescLimb": "*acerto em membro", + "GURPS.hitLocationDescNeck": "*acerto no pescoço", + "GURPS.hitLocationDR": "RD", + "GURPS.hitLocationDRWithDivisor": "RD Efetiva", + "GURPS.hitLocationExtremity": "Extremidade", + "GURPS.hitLocationEye": "Olho", + "GURPS.hitLocationEyes": "Olhos", + "GURPS.hitLocationFace, from behind": "Rosto, pelas costas", + "GURPS.hitLocationFace": "Rosto", + "GURPS.hitLocationFin": "Nadadeira", + "GURPS.hitLocationFin*": "Nadadeira", + "GURPS.hitLocationFoot": "Pé", + "GURPS.hitLocationForeleg": "Perna Dianteira ", + "GURPS.hitLocationGroin": "Virilha", + "GURPS.hitLocationHand": "Mão", + "GURPS.hitLocationHind Leg": "Perna Traseira", + "GURPS.hitLocationJaw": "Maxilar", + "GURPS.hitLocationLeft Arm, holding shield": "Braço Esq., com escudo", + "GURPS.hitLocationLeft Arm": "Braço Esq", + "GURPS.hitLocationLeft Leg": "Perna Esq", + "GURPS.hitLocationLeg 1-2": "Perna 1-2", + "GURPS.hitLocationLeg 3-4": "Perna 3-4", + "GURPS.hitLocationLeg 5-6": "Perna 5-6", + "GURPS.hitLocationLeg 7-8": "Perna 7-8", + "GURPS.hitLocationLeg": "Perna", + "GURPS.hitLocationLimb Vein/Artery": "Veia/Artéria de Braço ou Perna", + "GURPS.hitLocationMid Leg": "Perna Central", + "GURPS.hitLocationMid Leg*": "Perna Central", + "GURPS.hitLocationNeck Vein/Artery": "Jugular/Carótida", + "GURPS.hitLocationNeck": "Pescoço", + "GURPS.hitLocationNose": "Nariz", + "GURPS.hitLocationPenalty": "Mod.", + "GURPS.hitLocationRandom": "Aleatório", + "GURPS.hitLocationRight Arm, holding shield": "Braço Dir., com escudo", + "GURPS.hitLocationRight Arm": "Braço Dir", + "GURPS.hitLocationRight Leg": "Perna Dir", + "GURPS.hitLocationSkull, from behind": "Crânio, pelas costas", + "GURPS.hitLocationSkull": "Crânio", + "GURPS.hitLocationTail": "Cauda", + "GURPS.hitLocationTorso": "Tronco", + "GURPS.hitLocationTorso*": "Tronco", + "GURPS.hitLocationVitals, Heart": "Órg. Vitais, Coração", + "GURPS.hitLocationVitals": "Órg. Vitais", + "GURPS.hitLocationWhere": "Onde", + "GURPS.hitLocationWing": "Asa", + "__Modifier Bucket__": "=========", + "GURPS.modifier": "Mod.", + "GURPS.modifierTitle": "Modificadores", + "GURPS.modifierRangeTitle": "Velocidade/Distância", + "GURPS.modifierRange": "para veloc/dist de {range} m", + "GURPS.modifierRangeMHClose": "Próximo (5 m)", + "GURPS.modifierRangeMHCloseDesc": "É possível encostar ou atingir o oponente", + "GURPS.modifierRangeMHShort": "Distância curta (20 m)", + "GURPS.modifierRangeMHShortDesc": "É possível falar com o oponente; alcance de pistolas ou armas/projéteis lançados a mão", + "GURPS.modifierRangeMHMedium": "Distância média (100 m)", + "GURPS.modifierRangeMHMediumDesc": "Só é possível se comunicar gritando; alcance de espingardas ou submetralhadoras", + "GURPS.modifierRangeMHLong": "Distância longa (500 m)", + "GURPS.modifierRangeMHLongDesc": "Oponente longe demais para escutar; alcance de rifles", + "GURPS.modifierRangeMHExtreme": "Distância extrema (500+ m)", + "GURPS.modifierRangeMHExtremeDesc": "Difícil de sequer ver o oponente; alcance de rifles de atirador", + "GURPS.modifierAddRangeRuler": "Balde: Adicionar modificador da Régua", + "GURPS.modifierAddRangeRulerHint": "Se selecionado, o sistema automaticamente vai adicionar o último modificador medido pela Régua ao Balde de Modificadores.", + "GURPS.modifierAffliction": "Atribulações", + "GURPS.modifierAfflictionCough": "-3 para testes de DX (Tossindo)", + "GURPS.modifierAfflictionCoughIQ": "-1 para testes de IQ (Tossindo)", + "GURPS.modifierAfflictionDrowsy": "-2 para testes de IQ/DX/autocontrole (Sonolento)", + "GURPS.modifierAfflictionDrunk": "-2 para testes de IQ/DX (Bêbado)", + "GURPS.modifierAfflictionDrunkCR": "-4 para testes de autocontrole (Bêbado)", + "GURPS.modifierAfflictionEuphoria": "-3 para testes de IQ/DX/autocontrole (Euforia)", + "GURPS.modifierAfflictionModerate": "-2 para testes de IQ/DX/autocontrole (Dor Moderada)", + "GURPS.modifierAfflictionModerateHPT": "-1 para testes de IQ/DX/autocontrole (Dor Moderada c/ Hipoalgia)", + "GURPS.modifierAfflictionNausea": "-2 para todos os atributos (Nauseado)", + "GURPS.modifierAfflictionNauseaDef": "-1 em defesas ativas (Nauseado)", + "GURPS.modifierAfflictionRetch": "-5 para testes de IQ/DX/Per (Ânsia)", + "GURPS.modifierAfflictionSevere": "-4 para testes de IQ/DX/autocontrole (Dor Severa)", + "GURPS.modifierAfflictionSevereHPT": "-2 para testes de IQ/DX/autocontrole (Dor Severa c/ Hipoalgia)", + "GURPS.modifierAfflictionTerrible": "-6 para testes de IQ/DX/autocontrole (Dor Terrível)", + "GURPS.modifierAfflictionTerribleHPT": "-3 para testes de IQ/DX/autocontrole (Dor Terrível c/ Hipoalgia)", + "GURPS.modifierAfflictionTipsy": "-1 para testes de IQ/DX (Embriagado)", + "GURPS.modifierAfflictionTipsyCR": "-2 para testes de autocontrole (Embriagado)", + "GURPS.modifierAppearBelow": "Eles vão aparecer na lista Modificadores Selecionados, abaixo.", + "GURPS.modifierAutomatic": "Automática", + "GURPS.modifierBlindAttack": "-10 na jogada de ataque (Cego)", + "GURPS.modifierBlindDefend": "-4 na esquiva (Cego -- incapaz de ver o atacante)", + "GURPS.modifierBlockRetreat": "para Esquiva/Aparar (Retirada)", + "GURPS.modifierClickToAdd": "Clique nos modificadores acima e à direita para adicioná-los ao seu próximo teste.", + "GURPS.modifierCommon": "Modificadores Comuns", + "GURPS.modifierCover": "Cobertura", + "GURPS.modifierCoverBehindFigure": "-4 no ataque (Atrás de outra pessoa do mesmo tamanho)", + "GURPS.modifierCoverCrouch": "-2 no ataque (Agachado or Ajoelhado, sem cobertura)", + "GURPS.modifierCoverHalfExposed": "-3 no ataque (Metade do corpo exposta)", + "GURPS.modifierCoverHead": "-5 no ataque (Apenas Cabeça)", + "GURPS.modifierCoverHeadShoulder": "-4 no ataque (Cabeça e ombros)", + "GURPS.modifierCoverLight": "-2 no ataque (Atrás de cobertura leve)", + "GURPS.modifierCoverPosture": "Cobertura e Posição", + "GURPS.modifierCoverProne": "-4 no ataque (Deitado, sem cobertura)", + "GURPS.modifierCoverProneHeadDown": "-7 no ataque (Deitado, pouca cobertura, cabeça abaixada)", + "GURPS.modifierCoverProneHeadUp": "-5 no ataque (Deitado, pouca cobertura, cabeça erguida)", + "GURPS.modifierCoverThroughHex": "-4 no ataque (Disparando através de hexágono ocupado)", + "GURPS.modifierCurrentEffects": "Efeitos Selecionados", + "GURPS.modifierCurrentModifiers": "Modificadores Selecionados", + "GURPS.modifierDangerous": "Perigosa", + "GURPS.modifierDeceptiveAttack": "ao ataque (Ataque Enganoso)", + "GURPS.modifierDeterminedAttack": "ao ataque (Ataque Determinado)", + "GURPS.modifierDodgeAcrobatic": "para Esquiva (Acrobática, sucesso)", + "GURPS.modifierDodgeDive": "para Esquiva (Esquiva e Queda)", + "GURPS.modifierDodgeFailedAcro": "para Esquiva (Acrobática, fracasso)", + "GURPS.modifierDodgeRear": "para Esquiva (ataque pelas costas)", + "GURPS.modifierDodgeRetreat": "para Esquiva (Retirada)", + "GURPS.modifierDodgeSide": "para Esquiva (ataque lateral)", + "GURPS.modifierEasy": "Fácil", + "GURPS.modifierExtraEffort": "Esforço Adicional", + "GURPS.modifierFavorable": "Favorável", + "GURPS.modifierFeverishDef": "Defesa Exaltada", + "GURPS.modifierDefDeceptiveAttack": "às defesas devido a um ataque Enganoso", + "GURPS.modifierMaintainConcentration": "para Teste de Vont, para manter concentração", + "GURPS.modifierGrappling": "-4 à DX e perícias baseadas em DX (Agarrado)", + "GURPS.modifierGMBlessed": "Bênção do MJ", + "GURPS.modifierGMDontTry": "MJ: nem pense nisso", + "GURPS.modifierGMSaidSo": "Porque o MJ quer", + "GURPS.modifierHard": "Difícil", + "GURPS.modifierHeroicCharge": "Investida Heroica", + "GURPS.modifierHitLocation": "Pontos de Impacto (se a margem de fracasso for 1, então *)", + "GURPS.modifierImpossible": "Impossível", + "GURPS.modifierJournalManager": "Registro de Balde de Modificadores", + "GURPS.modifierJournals": "Lista de Registro de Balde de Modificadores", + "GURPS.modifierLightDim": "Fogueira grande / tocha / pôr-do-sol / nascer do sol", + "GURPS.modifierLightFullMoon": "Lua cheia", + "GURPS.modifierLightHalfMoon": "Meia lua", + "GURPS.modifierLightMoonless": "Noite de lua nova com céu encoberto", + "GURPS.modifierLightNone": "Escuridão total", + "GURPS.modifierLightQuarterMoon": "Um quarto de lua", + "GURPS.modifierLightStarlight": "Luz das estrelas", + "GURPS.modifierLightStarlightClouds": "Luz das estrelas através das nuvens", + "GURPS.modifierLightTwilight": "Crepúsculo / luz de gás / lanterna", + "GURPS.modifierLightDeepTwilight": "Crepúsculo profundo / luz de velas", + "GURPS.modifierMightyBlow": "dano (Golpe Poderoso)", + "GURPS.modifierMoveAttack": "ao ataque (Avançar e Atacar)", + "GURPS.modifierOthers": "Outros Modificadores", + "GURPS.modifierPosture": "Posição", + "GURPS.modifierPostureCrouchMelee": "-2 no ataque em combate corpo a corpo (Agachado)", + "GURPS.modifierPostureCrouchRanged": "-2 no ataque em combate à distância (Agachado)", + "GURPS.modifierPostureKneelDefend": "-2 em defesas ativas (Ajoelhado/Sentado)", + "GURPS.modifierPostureKneelMelee": "-2 no ataque em combate corpo a corpo (Ajoelhado/Sentado)", + "GURPS.modifierPostureProneDefend": "-3 em defesas ativas (Deitado)", + "GURPS.modifierPostureProneMelee": "-4 no ataque em combate corpo a corpo (Deitado)", + "GURPS.modifierPostureProneRanged": "-2 no ataque em combate à distância (Deitado)", + "GURPS.modifierQuality": "Qualidade de Equipamento", + "GURPS.modifierQualityBest": "Melhor Possível", + "GURPS.modifierQualityFine": "Qualidade Superior (20× o custo)", + "GURPS.modifierQualityGood": "Qualidade Boa (5× o custo)", + "GURPS.modifierQualityImprovised": "Improvisado", + "GURPS.modifierQualityImprovTech": "Improvisado (tecnológica)", + "GURPS.modifierQualityMissing": "Partes Faltando/Danificadas", + "GURPS.modifierQualityNone": "Nenhuma", + "GURPS.modifierQualityNoneTech": "Nenhuma (tecnológica)", + "GURPS.modifierScaleLarge": "Grande (110%)", + "GURPS.modifierScaleNormal": "Normal (100%)", + "GURPS.modifierScaleSmall": "Pequeno (90%)", + "GURPS.modifierScaleVeryLarge": "Muito Grande (120%)", + "GURPS.modifierScaleVerySmall": "Muito Pequeno (80%)", + "GURPS.modifierSelectJournalButton": "Selecionar Registro de Balde", + "GURPS.modifierSelectJournals": "Balde: Registros", + "GURPS.modifierSelectJournalsAside": "Apenas registros 'padrão' (HTML) são válidos para visualização no Balde de Modificadores. Ex: PDFs não podem ser exibidos.", + "GURPS.modifierSelectJournalsHint": "Seleciona os registros de Diário para exibir no Balde de Modificadores.", + "GURPS.modifierSelectJournalsTitle": "Selecionar Registros de Balde de Modificadores", + "GURPS.modifierSendTo": "Enviar Balde de Modificadores para:", + "GURPS.modifierShieldDB": "para Esquiva (BD de Escudo)", + "GURPS.modifierShowOnMouseOver": "Balde: Exibir ao passar o mouse", + "GURPS.modifierShowOnMouseOverHint": "Se selecionado, a janela de Modificadores será exibida como uma dica de contexto: quando o cursor do mouse passar por cima do Balde de Modificadores. Se esta opção for desligada, você pode abrir a janela de modificadores clicando no ícone do Balde de Modificadores. Para esta configuração fazer efeito, é necessário reiniciar o Foundry.", + "GURPS.modifierSize": "Modificador de Tamanho", + "GURPS.modifierSizeDetail": "Diferença no Corpo a Corpo; Absoluta à Distância", + "GURPS.modifierSizeEntry": "{SM} Tamanho {us} ({metric})", + "GURPS.modifierStatus": "Estado", + "GURPS.modifierStatusAffliction": "Estado e Atribulações", + "GURPS.modifierStatusShock1": "-1 para testes de IQ/DX (Choque 1)", + "GURPS.modifierStatusShock2": "-2 para testes de IQ/DX (Choque 2)", + "GURPS.modifierStatusShock3": "-3 para testes de IQ/DX (Choque 3)", + "GURPS.modifierStatusShock4": "-4 para testes de IQ/DX (Choque 4)", + "GURPS.modifierStatusStunned": "-4 em defesas ativas (Atordoado)", + "GURPS.modifierStrongAttack": "dano (Ataque forte)", + "GURPS.modifierTabAside": "Utilizar Configurações de Sistema para definir os Registros de Diário a serem exibidos aqui.", + "GURPS.modifierTaskDifficulty": "Dificuldade da Tarefa", + "GURPS.modifierTelegraphicAttack": "ao ataque (Ataque Telegráfico)", + "GURPS.modifierToHit": "ao ataque", + "GURPS.modifierTrivial": "Trivial", + "GURPS.modifierUnfavorable": "Desfavorável", + "GURPS.modifierUserEntered": "Ou você pode inserir um Modificador", + "GURPS.modifierVeryEasy": "Muito Fácil", + "GURPS.modifierVeryFavorable": "Muito Favorável", + "GURPS.modifierVeryHard": "Muito Difícil", + "GURPS.modifierVeryUnfavorable": "Muito Desfavorável", + "GURPS.modifierViewScale": "Balde: Fator de Escala (EXPERIMENTAL)", + "GURPS.modifierViewScaleHint": "Utilize esta opção para aumentar ou diminuir o tamanho do Balde de Modificadores.", + "GURPS.modifierWillCheck": "Teste de VONT para manter bônus de Apontar", + "__PDF References__": "=========", + "GURPS.pdfAllOutDefense": "B366", + "GURPS.pdfBlockRetreat": "B377", + "GURPS.pdfCrippling": "B420", + "GURPS.pdfDeceptiveAttack": "B369", + "GURPS.pdfDeterminedAttack": "B365", + "GURPS.pdfDamageRoll": "B378", + "GURPS.pdfDodgeAcrobatic": "B374", + "GURPS.pdfDodgeDive": "B377", + "GURPS.pdfDodgeFailedAcro": "B375", + "GURPS.pdfDodgeRear": "B390", + "GURPS.pdfDodgeRetreat": "B375", + "GURPS.pdfDodgeSide": "B390", + "GURPS.pdfExtraEffort": "B356", + "GURPS.pdfGrappling": "B370", + "GURPS.pdfHazardCoughing": "B428", + "GURPS.pdfHazardDrowsy": "B428", + "GURPS.pdfHazardDrunk": "B428", + "GURPS.pdfHazardEuphoria": "B428", + "GURPS.pdfHazardNausea": "B428", + "GURPS.pdfHazardPain": "B428", + "GURPS.pdfHazardRetching": "B428", + "GURPS.pdfHazardTipsy": "B428", + "GURPS.pdfHeroicCharge": "MA131", + "GURPS.pdfHPT": "B63", + "GURPS.pdfKnockback": "B378", + "GURPS.pdfKnockdownStun": "B420", + "GURPS.pdfLPT": "B144", + "GURPS.pdfMajorWound": "B420", + "GURPS.pdfMightyBlow": "MA131", + "GURPS.pdfMoveAttack": "B365", + "GURPS.pdfPostureCrawling": "B551", + "GURPS.pdfPostureCrouching": "B551", + "GURPS.pdfPostureKneeling": "B551", + "GURPS.pdfPostureLyingDown": "B551", + "GURPS.pdfPostureSitting": "B551", + "GURPS.pdfReeling": "B419", + "GURPS.pdfShieldDB": "B374", + "GURPS.pdfShieldRush": "B372", + "GURPS.pdfShock": "B419", + "GURPS.pdfStrongAttack": "B365", + "GURPS.pdfSuffocation": "B437", + "GURPS.pdfTired": "B426", + "GURPS.pdfTelegraphicAttack": "MA113", + "GURPS.pdfTempAttribPenalties": "B421", + "GURPS.pdfVisibility": "B394", + "__Resolve Damage Dialog__": "=========", + "GURPS.RESOLVEDAMAGEMultiple": "Avaliações múltiplas", + "GURPS.RESOLVEDAMAGEPrompt": "O que você quer fazer com esta Avaliação de Dano?", + "GURPS.RESOLVEDAMAGEQuantity": "Número de avaliações:", + "GURPS.RESOLVEDAMAGESendTo": "Enviar Fórmula para...", + "GURPS.RESOLVEDAMAGETitle": "Explicar Avaliação de Dano", + "__Resource Trackers__": "=========", + "GURPS.resourceCopyTemplate": "Copiar Modelo", + "GURPS.resourceCurrentValue": "Valor Atual", + "GURPS.resourceDamageTracker": "Controle de Dano (dano é adicionado ao valor).", + "GURPS.resourceDamageType": "Usar como Tipo de Dano", + "GURPS.resourceDeleteTracker": "Apagar Controle", + "GURPS.resourceEditTracker": "Editar Controle", + "GURPS.resourceInvalidAlias": "Alias inválido: [{alias}].
São permitidos somente caracteres alfanuméricos e '+', '_', and '-'.", + "GURPS.resourceTemplateAlias": "Alias", + "GURPS.resourceTemplateButton": "Exibir e Editar Controles", + "GURPS.resourceTemplateClickToAdd": "Clique no botão '+', acima, para adicionar um modelo.", + "GURPS.resourceTemplateHint": "Use esta opção para criar, reutilizar e aplicar automaticamente Controles de Recursos a planilhas de personagem.", + "GURPS.resourceTemplateInitializer": "Inicializador", + "GURPS.resourceTemplateManager": "Configurar Controle de Recursos", + "GURPS.resourceTemplateSlot": "Posição Atribuída", + "GURPS.resourceTemplateTitle": "Modelos de Controle de Recursos", + "GURPS.resourceTracker": "Controle", + "GURPS.resourceTrackerEditor": "Editar Controle de Recursos", + "GURPS.resourceTrackers": "Controles de Recursos", + "GURPS.resourceUndefined": "Nenhum Definido", + "GURPS.resourceUpdateTrackerSlot": "Atualizar Posição de Controle", + "GURPS.slotNotUnique": "Já existe um controle designado para a posição Controle {value}.", + "GURPS.trackerNotUnique": "Nome do controle ({name}) ou alias ({alias}) não é único.", + "GURPS.resourceEnforceMinimum": "Forçar Mínimo", + "GURPS.resourceEnforceMaximum": "Forçar Máximo", + "GURPS.resourceTemplateName": "Nome do Modelo", + "Skill Names__": "=========", + "GURPS.skillAcrobatics": "Acrobacia", + "GURPS.skillJudo": "Judô", + "__Slam Calculator__": "=========", + "GURPS.slamAOAStrong": "Ataque Total (Forte)", + "GURPS.slamCalculator": "Calculadora de Encontrão", + "GURPS.slamForShieldDB": "BD de Escudo (Arremetida com Escudo)", + "GURPS.slamRelativeVelocity": "Velocidade Relativa", + "GURPS.slams": "dá um encontrão em", + "GURPS.slamShieldDB": "BD de Escudo", + "GURPS.slamVelocity": "Velocidade", + "__Status/Conditions__": "=========", + "GURPS.STATUSAgony": "Agonia", + "GURPS.STATUSAim": "Mirando", + "GURPS.STATUSBleed": "Sangrando", + "GURPS.STATUSBlind": "Cego(a)", + "GURPS.STATUSBurn": "Queimando", + "GURPS.STATUSCoughing": "Tossindo", + "GURPS.STATUSCounter": "Contra-ataque", + "GURPS.STATUSCrouch": "Agachado(a)", + "GURPS.STATUSDeaf": "Ensurdecido(a)", + "GURPS.STATUSDisable": "Desabilitado(a)", + "GURPS.STATUSDrowsy": "Sonolento(a)", + "GURPS.STATUSDrunk": "Bêbado(a)", + "GURPS.STATUSEuphoria": "Eufórico(a)", + "GURPS.STATUSExhausted": "Exausto(a)", + "GURPS.STATUSFall": "Caindo", + "GURPS.STATUSFly": "Voando", + "GURPS.STATUSGrapple": "Agarrado(a)", + "GURPS.STATUSKneel": "Ajoelhado(a)", + "GURPS.STATUSMildPain": "Dor Leve", + "GURPS.STATUSModeratePain": "Dor Moderada", + "GURPS.STATUSNauseated": "Nauseado(a)", + "GURPS.STATUSPin": "Fixado(a)", + "GURPS.STATUSPoison": "Envenenado(a)", + "GURPS.STATUSReeling": "Cambaleando", + "GURPS.STATUSRetching": "Vomitando", + "GURPS.STATUSSeverePain": "Dor Severa", + "GURPS.STATUSSilence": "Silenciado(a)", + "GURPS.STATUSSit": "Sentado(a)", + "GURPS.STATUSSleep": "Dormindo", + "GURPS.STATUSSprint": "Correndo em disparada", + "GURPS.STATUSStealth": "Furtivo(a)", + "GURPS.StatusStunnedMental": "Atordoamento Mental", + "GURPS.STATUSSuffocate": "Sufocando", + "GURPS.STATUSTerriblePain": "Dor Terrível", + "GURPS.STATUSTipsy": "Embriagado(a)", + "GURPS.STATUSWait": "Aguardando", + "__Maneuvers__": "=========", + "GURPS.maneuver": "Manobra", + "GURPS.maneuverDoNothing": "Fazer Nada", + "GURPS.maneuverMove": "Deslocamento", + "GURPS.maneuverAim": "Apontar", + "GURPS.maneuverChangePosture": "Mudança de Posição", + "GURPS.maneuverEvaluate": "Avaliar", + "GURPS.maneuverAttack": "Ataque", + "GURPS.maneuverFeint": "Fintar", + "GURPS.maneuverAllOutAttack": "Ataque Total", + "GURPS.maneuverAllOutAttackDetermined": "Ataque Total (Determinado)", + "GURPS.maneuverAllOutAttackDouble": "Ataque Total (Duplo)", + "GURPS.maneuverAllOutAttackFeint": "Ataque Total (Fintar)", + "GURPS.maneuverAllOutAttackStrong": "Ataque Total (Forte)", + "GURPS.maneuverAllOutAttackSuppressFire": "Ataque Total (Fogo de Retenção)", + "GURPS.maneuverMoveAttack": "Avançar e Atacar", + "GURPS.maneuverAllOutDefense": "Defesa Total", + "GURPS.maneuverAllOutDefenseDodge": "Defesa Total (Esquiva)", + "GURPS.maneuverAllOutDefenseParry": "Defesa Total (Aparar)", + "GURPS.maneuverAllOutDefenseBlock": "Defesa Total (Bloqueio)", + "GURPS.maneuverAllOutDefenseDouble": "Defesa Total (Dupla)", + "GURPS.maneuverReady": "Preparar", + "GURPS.maneuverConcentrate": "Concentrar", + "GURPS.maneuverWait": "Aguardar", + "__Import Messages__": "=========", + "GURPS.importCannotImportGCADirectly": "Não é possível importar um arquivo GCA diretamente. Por favor, exporte o arquivo utilizando a opção 'export to Foundry VTT.gce'.", + "GURPS.importCannotImportGCSDirectly": "Não é possível importar um arquivo GCS diretamente. Por favor, exporte o arquivo utilizando o modelo de saída para o 'Foundry VTT'.", + "GURPS.importGCA5ImprovedInventoryHandling": "Este arquivo foi criado por uma versão mais antiga do GCA5 Export que não lida bem com o texto do inventário.", + "GURPS.importCurrentVersions": "Versões Atualizadas: '{GCAVersion}' & '{GCSVersion}'.", + "GURPS.importErrorParsingXML": "Erro ao analisar o XML: {text}.", + "GURPS.importFantasyGroundUnsupported": "Não é mais possível importar um arquivo de Fantasy Grounds.", + "GURPS.importFileVersion": "Versão do arquivo: '{version}'.", + "GURPS.importGCABadBlockForDB": "Este arquivo foi criado por uma versão mais antiga do GCA Export que calcula incorretamente o valor de Bloqueio para itens com BD (como os Escudos).", + "GURPS.importGCANoBodyPlan": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não contém o atributo 'Tipo de Corpo'. Tentaremos adivinhar o Tipo de Corpo, mas pode ser que algo saia errado.", + "GURPS.importGCANoHideFlag": "Este arquivo foi criado por uma versão mais antiga do GCA Export que ignora a marcação de ocultação para vant/desv/qual/pecul.", + "GURPS.importGCAChildrenWeights": "Este arquivo for criado por uma versão mais antiga do GCA Export, que calculava incorretamente os pesos de equipamentos que continham outros equipamentos.", + "GURPS.importGCANoInnateRangedAndParent": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não exporta Ataques Inatos à distância e contém o Atributo 'Pai' para equipamento. Você pode errar ataques à distância ou certos equipamentos podem não aparecer no contêiner correto.", + "GURPS.importGCANoMeleeIfAlsoRanged": "Este arquivo foi criado por uma versão mais antiga do GCA Export que que pode não exportar um ataque corpo a corpo se ele também existir nos ataques à distância (como a Lança).", + "GURPS.importGCSNoMeleeRangedNotesForSameItem": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não exporta notas individuais nos ataques criadas pelo mesmo item.", + "GURPS.importGCANoParent": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não contém os atributos 'Pais' para Vants/Desvants, Perícias ou Mágicas.", + "GURPS.importGCANoSanitizedEquipmentPageRefs": "Este arquivo foi criado por uma versão mais antiga do GCA Export que pode, de maneira equívoca, colocar ataques à distância na lista de ataques corpo a corpo e não limpa as refs da página de equipamentos.", + "GURPS.importGCANoSanitizeNotes": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não limpa as Notas ou nomes de Vants/Desvants.", + "GURPS.importGCSNoParent": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não contém os atributos 'Pais'. Os itens não aparecerão em seus contêineres.", + "GURPS.importGCSNoSelfControl": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não contém os testes de Autocontrole para Desvantagens (ex: [CR: 9 Irritabilidade]).", + "GURPS.importGCSNoUses": "Este arquivo foi criado por uma versão mais antiga do GCS Export que não contém a coluna 'USOS' na parte de Equipamentos.", + "GURPS.importGCAAdvMods": "Este arquivo foi criado por uma versão mais antiga do GCA Export que concatena os modificadores de Vantagens com os nomes das Vantagens, algo que pode resultar em nomes muito longos de Vantagens (e afetar o leiaute da planilha de personagem)", + "GURPS.importGCAConditionalModifiers": "Este arquivo foi criado por uma versão mais antiga do GCA Export que não exporta Modificadores Condicionais", + "GURPS.importGenericError": "Houve um erro ao importar {name}, {error}:{message}.", + "GURPS.importNoCharacterFormat": "Incapaz de detectar o formato de 'personagem'. É possível que você esteja tentando importar o formato 'npc'.", + "GURPS.importNoXMLDetected": "Nenhum XML detectado. Você está importando o arquivo XML correto?", + "GURPS.importTooManyContainers": "Há níveis de contêineres em demasia. A importação do Foundry só suporta até 3 níveis de sub-contêineres.", + "GURPS.importSuccessful": "{name} importado com sucesso.", + "GURPS.importSeeUsersGuide": "Verifique o Manual do Usuário para detalhes de onde conseguir a última versão.", + "GURPS.importOldGCSFile": "Seu personagem foi salvo com uma versão mais antiga do GCS, que não exporta alguns dos atributos necessários. Atualize o GCS para no mínimo a versão 4.36, abra e salve o arquivo de personagem e então tente novamente.", + "GURPS.importNoJSONDetected": "Incapaz de analisar JSON. Seu arquivo do GCS aparenta estar corrompido.", + "__System Settings__": "=========", + "GURPS.settingShowReadMe": "Exibir 'Leia-Me' quando houver atualização", + "GURPS.settingHintShowReadMe": "Se marcado, o sistema vai exibir o arquivo 'Leia-Me' sempre que uma mudança de versão for detectada.", + "GURPS.settingRangeStrategy": "Combate: Estratégia de modificador de Distância", + "GURPS.settingHintRangeStrategy": "Configura a fórmula a ser utilizada para calcular as penalidades de distância.", + "GURPS.settingRangeStrategyStandard": "Tabela de Tamanho e Velocidade/Distância", + "GURPS.settingRangeStrategyRangeBands": "Bandas de Distância de Monster Hunters 2", + "GURPS.settingRangeStrategyTenPenalties": "-1 para cada 10 hexágonos/jardas/metros", + "GURPS.settingBasicPDFs": "PDF(s) do Módulo Básico", + "GURPS.settingHintBasicPDFs": "Selecione 'Combinado' ou 'Separado' e utilize os códigos de PDF associados quando for configurar o PDFoundry. Nota: Se você selecionar 'Separado', o PDF do Módulo Básico Campanhas deve abrir a partir da página 340 ao executar os testes do PDFoundry.", + "GURPS.settingBasicPDFsCombined": "Módulo Básico Combinado (código 'B')", + "GURPS.settingBasicPDFsSeparate": "Separado (Personagens, 'B'; Campanhas, 'BX')", + "GURPS.settingImportIgnoreName": "Importação: Ignorar atributo 'nome'", + "GURPS.settingHintImportIgnoreName": "Se marcado, o sistema vai ignorar o atributo 'nome' do Ator durante a importação. Isso é útil caso o nome que você utiliza no Foundry for diferente daquele que consta no GCA/GCS e se você não quiser ter que modificá-lo cada vez que fizer uma importação.", + "GURPS.settingBlockImport": "Apenas jogadores CONFIÁVEIS podem Importar", + "GURPS.settingHintBlockImport": "Se marcado, o botão 'Importar' só será exibido na planilha de personagem caso o jogador em questão possuir o nível de permissão 'Confiável', 'Assistente' ou 'GameMaster'", + "GURPS.settingImportHPAndFP": "Importação: PV e FP Atuais", + "GURPS.settingHintImportHPAndFP": "NOTA: Os PV e PF Atuais sempre serão copiados do arquivo durante a primeira importação.", + "GURPS.settingImportHPAndFPUseFile": "Utilizar os valores de PV e FP atuais do arquivo.", + "GURPS.settingImportHPAndFPIgnore": "Ignorar os valores de PV e FP atuais do arquivo.", + "GURPS.settingImportHPAndFPAsk": "Perguntar antes de sobrescrever durante a importação.", + "GURPS.settingImportBodyPlan": "Importar: Tipo de Corpo/Pontos de Impacto", + "GURPS.settingImportHintBodyPlan": "NOTA: O Tipo de Corpo sempre é copiado do arquivo durante a primeira importação.", + "GURPS.settingImportBodyPlanUseFile": "Utilizar o Tipo de Corpo que consta no arquivo de importação.", + "GURPS.settingImportBodyPlanIgnore": "Ignorar o Tipo de Corpo que consta no arquivo de importação.", + "GURPS.settingImportBodyPlanAsk": "Perguntar antes de sobrescrever durante a importação.", + "GURPS.settingShowNavigation": "Ator: Exibir navegação", + "GURPS.settingHintShowNavigation": "Se marcado, o rodapé de navegação será exibido na planilha de personagem completa do GCS.", + "GURPS.settingEnhancedInput": "Ator: Entradas numéricas melhoradas", + "GURPS.settingHintEnhancedInput": "Se marcado, certos campos (como PF) exibirão botões atalho de adição e subtração quando selecionados.", + "GURPS.settingCalculateEnc": "Ator: Calcular Base de Carga", + "GURPS.settingHintCalculateEnc": "Se marcado, o nível de Base de Carga será configurado automaticamente baseado no equipamento portado (e você não poderá modificar o nível de Base de Carga manualmente). Se desmarcado, você pode modificar o nível de Base de Carga clicando no nível desejado.", + "GURPS.settingUseEquipped": "Ator: Peso baseado no que estiver 'Equipado'", + "GURPS.settingHintUseEquipped": "Se marcado, APENAS itens 'Equipados' serão incluídos no cálculo de peso. Se desmarcado, todos os itens na lista de Equipamentos serão incluídos no cálculo de peso. Desmarque e os jogadores poderão utilizar a marcação de 'Equipado' para indicar que largaram o item.", + "GURPS.settingFlagUserCreated": "Ator: Marcar criações do Usuário", + "GURPS.settingHintFlagUserCreated": "Se marcado, um pequeno ícone vai aparecer na frente de equipamento criado pelo usuário (não importado) e antes de notas criadas pelo usuário.", + "GURPS.settingFlagItems": "Ator: Marcar Itens do Foundry", + "GURPS.settingHintFlagItems": "Se marcado, um pequeno ícone vai aparecer na frente de equipamento (e características) criadas a partir dos Itens do Foundry", + "GURPS.settingQtyItems": "Ator: Marcar QTD/Contagem salva", + "GURPS.settingHintQtyItems": "Se marcado, um pequeno ícone vai aparecer na frente de equipamento cuja QTD/Contagem será mantida durante importações", + "GURPS.settingConvertRanged": "Ator: Converter distância 'x2/x5' para jardas", + "GURPS.settingHintConvertRanged": "Se marcado, os campos de distância na forma 'xN' ou 'xN/xM' serão multiplicados pela ST do personagem para determinar a distância real para uma arma de arremesso. NOTA: Isto só acontece numa importação.", + "GURPS.settingShowDiceRoller": "IU: Exibir 3D6 (Próximo ao Balde de Modificadores)", + "GURPS.settingHintShowDiceRoller": "Se marcado, o sistema vai exibir o atalho de rolagem de dados à direita do Balde de Modificadores. Você deve recarregar o Foundry para essa configuração entrar em efeito.", + "GURPS.settingCombatInitiative": "Combate: Fórmula de Iniciativa", + "GURPS.settingHintCombatInitiative": "Trata-se da fórmula utilizada pelo Foundry para determinar a ordem dos turnos no combate. Aviso: Só mude isto se você souber o que está fazendo! Nós não avaliamos o que está aqui para determinar se está correto ou não. Deixe este campo em branco para redefinir a fórmula para a Sequência de Combate do GURPS, B362.", + "GURPS.settingDamageRestrictADD": "Dano: Restringir JAD para o MJ", + "GURPS.settingHintDamageRestrictADD": "Se marcado, só o MJ pode visualizar/utilizar a Janela de Avaliação de Dano. Jogadores de arrastarem e soltarem dano receberão uma mensagem.", + "GURPS.settingDamageSimpleADD": "Dano: JAD Simples", + "GURPS.settingHintDamageSimpleADD": "Se marcado, só exibirá a opção de 'Aplicar Diretamente' na Janela de Avaliação de Dano.", + "GURPS.settingDamageLocation": "Dano: Ponto de impacto padrão", + "GURPS.settingHintDamageLocation": "Configura o ponto de impacto padrão a ser utilizada nas avaliações de dano.", + "GURPS.settingDamageLocationTorso": "Tronco", + "GURPS.settingDamageLocationRandom": "Aleatório", + "GURPS.settingDamageAD": "Dano: Divisores de Armadura", + "GURPS.settingHintDamageAD": "Se marcado, ajusta a RD do alvo de acordo com o divisor de armadura do ataque.", + "GURPS.settingDamageBluntTrauma": "Dano: Trauma por Impacto", + "GURPS.settingHintDamageBluntTrauma": "Se marcado, serão utilizadas as regras de de Trauma por Impacto para cálculo de dano em armadura flexível.", + "GURPS.settingDamageLocationMods": "Dano: Mod. de Ferimento de acordo com Ponto de Impacto", + "GURPS.settingHintDamageLocationMods": "Se marcado, os Modificadores de Ferimento serão alterados baseados no Ponto de Impacto.", + "GURPS.settingDamageMath": "Dano: Exibir cálculos", + "GURPS.settingHintDamageMath": "Se marcado, a seção de 'EXIBIR CÁLCULOS' da mensagem de chat será, por padrão, expandida. Se desmarcado, você pode clicar no título 'EXIBIR CÁLCULOS' para expandi-lo. NOTA: Se ela for a última mensagem do chat, pode ser que ela se expanda para baixo do limite inferior da janela de chat, e pode ser que você precise rolar para baixo para visualizá-la.", + "GURPS.settingDamageCondInjury": "Dano: Lesão Condicional", + "GURPS.settingHintDamagCondInjury": "Da Pyramid #3/120: Lesão Condicional retira os Pontos de Vida do jogo como base para acompanhar as lesões, e os substitui por método baseado em efeitos, para fins de lesão.", + "GURPS.settingStatusWhisper": "Efeitos de Estado: Sussurro", + "GURPS.settingHintStatusWhisper": "Se marcado, mensagens de Efeitos de Estado (Choque, Ferimento Grave, etc.) serão enviadas ao dono do alvo como um Sussurro. De outra forma, elas serão enviadas como mensagens em off para todos.", + "GURPS.settingStatusReeling": "Efeitos de Estado: Cambaleando e Cansado Automáticos", + "GURPS.settingHintStatusReeling": "Se marcado, Cambaleando (1/2 deslocamento/esquiva) e Cansado (1/2 deslocamento/esquiva) serão automaticamente ativados quando o personagem ficar com PV e/ou FP abaixo de 1/3.", + "GURPS.settingPlayerBlindRoll": "Permitir rolagens às cegas para os Jogadores", + "GURPS.settingHintPlayerBlindRoll": "Se não estiver marcado, segurar a tecla SHIFT quando for fazer uma rolagem de dados resultará numa rolagem Oculta (só você pode ver, não importa quem você seja). Se marcado, quando os jogadores segurarem a tecla SHIFT eles farão uma Rolagem às Cegas (O MJ vê como uma Rolagem Oculta).", + "GURPS.settingPlayerChatPrivate": "Comandos privados no Chat de Jogadores", + "GURPS.settingHintPlayerChatPrivate": "Se marcado, a maioria dos comandos de chat (ex.: /hp, /fp, /qty, etc.) serão exibidas como sussurros para o jogador (ao invés de uma mensagem pública). Se você confia nos seus jogadores e não gosta de ver o chat repleto de comandos de chat, desative isto.", + "GURPS.settingMookGenerator": "Padrões do Gerador de Mook", + "GURPS.settingLabelMookGenerator": "Editor Padrão do Gerador de Mook", + "GURPS.settingHintMookGenerator": "Editar os valores iniciais do Gerador de Mook", + "GURPS.settingManeuverVisibility": "Visibilidade de Ícones de Manobra", + "GURPS.settingHintManeuverVisibility": "Determina quem pode ver o ícone de manobra de uma miniatura.", + "GURPS.settingManeuverNoOne": "Ninguém", + "GURPS.settingManeuverGMOnly": "Apenas MJ e Dono", + "GURPS.settingManeuverEveryone": "Todos", + "GURPS.settingManeuverDetail": "Detalhes de Visibilidade de Manobra", + "GURPS.settingHintManeuverDetail": "Determina qual manobra é visível para os jogadores que não sejam o MJ ou o Dono, se houver algum. 'Todos os Detalhes': Ex.:, mostrar \"Ataque Total (Determinado)\" e \"Fintar\" exatamente como exibidos. 'Sem Fintar': Como 'Todos os Detalhes', exceto que Fintar aparece como \"Ataque\". 'Geral': Como 'Completo, Sem Fintar' exceto que a opção não é exibida -- ex.:, Ataque Total (Forte) aparece como \"Ataque Total\". (O MJ e o Dono sempre veem Todos os Detalhes)", + "GURPS.settingManeuverDetailFull": "Todos os Detalhes", + "GURPS.settingManeuverDetailNoFeint": "Sem Fintar", + "GURPS.settingManeuverDetailGeneral": "Geral", + "GURPS.settingAutoIgnoreQty": "Importar: Salvar automaticamente a Qtd/Contagem do Foundry", + "GURPS.settingHintAutoIgnoreQty": "Se marcada, esta opção vai configurar automaticamente a opção 'Salvar QTD/Contagem atual na importação' em um determinado equipamento quando o usuário mudar a QTD/Contagem (e vai exibir um pequeno ícone azul de arquivo). NOTA: Isto não detecta mudanças nos 'Usos'. Se você precisar se lembrar dos 'Usos' entre as importações, você precisa configurar manualmente isso no equipamento.", + "GURPS.settingSheetDetail": "Planilha Rápida", + "GURPS.settingHintSheetDetail": "Seleciona a planilha de personagem que você deseja que seja a 'Planilha Rápida'. Ela será exibida na barra de título e o usuário pode escolher entre ela e a 'Planilha completa'", + "GURPS.settingImportEncoding": "Importar codificação de arquivo", + "GURPS.settingImportHintEncoding": "Se você estiver importando um personagem e caracteres unicode não estiverem sendo exibidos, modifique esta configuração para codificação UTF-8.", + "GURPS.settingImportEncodingISO8859": "ISO-8859-1 (default)", + "GURPS.settingImportEncodingUTF8": "UTF-8", + "GURPS.settingRemoveUnequipped": "Ator: Remover armas Não-Equipadas das listas de armas Corpo a Corpo e à Distância", + "GURPS.settingHintRemoveUnequipped": "Se marcado, os nomes dos ataques Corpo a Corpo e à Distância serão comparados à lista de equipamentos portados, e se for encontrada alguma equivalência, o ataque será listado somente se estiver Equipado", + "GURPS.settingImportBrowserImporter": "Utilizar janela de importação para não hospedado localmente", + "GURPS.settingImportHintBrowserImporter": "Marque isso se você NÃO estiver hospedando localmente sua instância do Foundry (você está hospedando externamente, como por exemplo na Oracle Cloud). Dessa forma, a janela de importação se lembrará da localização dos arquivos importados durante a sessão (o que significa que se você importar o personagem novamente, na mesma sessão, a janela de Arquivo não precisará ser aberta).", + "GURPS.settingShowChatReeling": "Exibir estado de Cambaleando/Cansado no Chat", + "GURPS.settingHintShowChatReeling": "Quando marcado, quaisquer mudanças no status de algum ator em relação ao estado de Cambaleando ou Cansado será exibida como mensagem de chat.", + "GURPS.settingDefaultADDAction": "Definir ação padrão para a Janela de Dano", + "GURPS.settingHintefaultADDAction": "Quando configurado para 'Alvo' o sistema vai escolher 'Aplicar' para PdJs e 'Aplicar Discretamente' para PdMs.", + "GURPS.settingApplyBasedOnTarget": "'Alvo'", + "GURPS.settingTokenOverrideRefresh": "Desconsiderar dimensionamento de miniatura", + "GURPS.settingHintTokenOverrideRefresh": "Se estiver \"ativado\", tentará desenhar as miniaturas para que se encaixem adequadamente na grade hexagonal. Ignora as funções de desenho do Foundry -- desative esta opção se houver qualquer comportamento inadequado nos desenhos do Foundry. Será necessário recarregar o mundo.", + "__Color Settings__": "=========", + "GURPS.settingColorSheetMenuTitle": "Cor da Planilha de Personagem", + "GURPS.settingColorSheetMenuHint": "Configuração de Cor da Planilha de Personagem", + "GURPS.colorSheetMenuOverride": "Desconsiderar Cores", + "GURPS.colorSheetMenuCustomColors": "Cores Personalizadas", + "GURPS.colorSheetMenuColorAreas": "Áreas de Cor", + "GURPS.colorSheetMenuAreasAttributesColor": "Cor dos Atributos", + "GURPS.colorSheetMenuAreasAttributesTextColor": "Cor do Texto dos Atributos", + "GURPS.colorSheetMenuAreasAttributesHoverColor": "Cor ao Passar o Mouse sobre os Atributos", + "GURPS.colorSheetMenuAreasAttributesHoverTextColor": "Cor do Texto ao Passar o Mouse sobre os Atributos", + "GURPS.colorSheetMenuAreasDodgeColor": "Cor da Esquiva", + "GURPS.colorSheetMenuAreasDodgeTextColor": "Cor do Texto da Esquiva", + "GURPS.colorSheetMenuAreasDodgeHoverColor": "Cor ao Passar o Mouse sobre a Esquiva", + "GURPS.colorSheetMenuAreasDodgeHoverTextColor": "Cor do Texto ao Passar o Mouse sobre a Esquiva", + "GURPS.colorSheetMenuAreasDamageColor": "Cor do Dano", + "GURPS.colorSheetMenuAreasDamageTextColor": "Cor do Texto do Dano", + "GURPS.colorSheetMenuAreasDamageHoverColor": "Cor ao Passar o Mouse sobre o Dano", + "GURPS.colorSheetMenuAreasDamageHoverTextColor": "Cor do Texto ao Passar o Mouse sobre o Dano", + "GURPS.colorSheetMenuAreasBlockColor": "Cor do Bloqueio", + "GURPS.colorSheetMenuAreasBlockTextColor": "Cor do Texto do Bloqueio", + "GURPS.colorSheetMenuAreasBlockHoverColor": "Cor ao Passar o Mouse sobre o Bloqueio", + "GURPS.colorSheetMenuAreasBlockHoverTextColor": "Cor do Texto ao Passar o Mouse sobre o Bloqueio", + "GURPS.colorSheetMenuAreasParryColor": "Cor de Aparar", + "GURPS.colorSheetMenuAreasParryTextColor": "Cor to Texto de Aparar", + "GURPS.colorSheetMenuAreasParryHoverColor": "Cor ao Passar o Mouse sobre Aparar", + "GURPS.colorSheetMenuAreasParryHoverTextColor": "Cor do Texto ao Passar o Mouse sobre Aparar", + "GURPS.colorSheetMenuAreasWeaponsColor": "Cor das Armas", + "GURPS.colorSheetMenuAreasWeaponsTextColor": "Cor do Texto das Armas", + "GURPS.colorSheetMenuAreasWeaponsHoverColor": "Cor ao Passar o Mouse sobre as Armas", + "GURPS.colorSheetMenuAreasWeaponsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Armas", + "GURPS.colorSheetMenuAreasSkillsColor": "Cor das Perícias", + "GURPS.colorSheetMenuAreasSkillsTextColor": "Cor do Texto das Perícias", + "GURPS.colorSheetMenuAreasSkillsHoverColor": "Cor ao Passar o Mouse sobre as Perícias", + "GURPS.colorSheetMenuAreasSkillsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Perícias", + "GURPS.colorSheetMenuAreasSpellsColor": "Cor das Mágicas", + "GURPS.colorSheetMenuAreasSpellsTextColor": "Cor do Texto das Mágicas", + "GURPS.colorSheetMenuAreasSpellsHoverColor": "Cor ao Passar o Mouse sobre as Mágicas", + "GURPS.colorSheetMenuAreasSpellsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Mágicas", + "GURPS.colorSheetMenuAreasOtfNotesColor": "Cor das Notas OtF", + "GURPS.colorSheetMenuAreasOtfNotesTextColor": "Cor do Texto das Notas OtF", + "GURPS.colorSheetMenuAreasOtfNotesHoverColor": "Cor ao Passar o Mouse sobre as Notas OtF", + "GURPS.colorSheetMenuAreasOtfNotesHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Notas OtF", + "GURPS.colorSheetMenuAreasAdsDisadsColor": "Cor das Vants/Desvants", + "GURPS.colorSheetMenuAreasAdsDisadsTextColor": "Cor do Texto das Vants/Desvants", + "GURPS.colorSheetMenuAreasAdsDisadsHoverColor": "Cor ao Passar o Mouse sobre as Vants/Desvants", + "GURPS.colorSheetMenuAreasAdsDisadsHoverTextColor": "Cor do Texto ao Passar o Mouse sobre as Vants/Desvants", + "GURPS.adDisad": "Vantagem/Desvantagem", + "GURPS.adDisadQuirkPerk": "Vantagem/Desvantagem/Peculiaridade/Qualidade", + "GURPS.conditionalModifier": "Modificador Condicional", + "GURPS.delete": "Apagar", + "GURPS.fromEllipses": "de ...", + "GURPS.moveToOtherEquipment": "Mover para Outros Equipamentos", + "GURPS.sortAscending": "Organizar Crescente", + "GURPS.sortContentsAscending": "Organizar Conteúdo (Crescente)", + "GURPS.sortContentsDescending": "Organizar Conteúdo (Decrescente)", + "GURPS.sortDescending": "Organizar Decrescente", + "GURPS.actions": "Ações", + "GURPS.addAdvantage": "Adicionar Vantagem", + "GURPS.addMeleeAttack": "Adicionar Ataque Corpo a Corpo", + "GURPS.addRangedAttack": "Adicionar Ataque à Distância", + "GURPS.addRT": "Adicionar Controle de Recurso", + "GURPS.addSkill": "Adicionar Perícia", + "GURPS.addSpell": "Adicionar Mágica", + "GURPS.advantage": "Vantagem", + "GURPS.advantages": "Vantagens", + "GURPS.advantagesTab": "Vantagens e Desvantagens", + "GURPS.aim": "Apontar", + "GURPS.allDamage": "TODO DANO", + "GURPS.allOutDefense": "Defesa Total", + "GURPS.allTheDamage": "TODO O DANO!!", + "GURPS.applyAllToTarget": "Aplicar Tudo em {name}", + "GURPS.basic": "Básico", + "GURPS.bluntTrauma": "Trauma por Impacto", + "GURPS.bonuses": "Bônus", + "GURPS.check": "Teste", + "GURPS.check1": "Teste #1", + "GURPS.check2": "Teste #2", + "GURPS.check3": "Teste #3", + "GURPS.check4": "Teste #4", + "GURPS.clickToEdit": "Clique para Editar", + "GURPS.clickToRemove": "clique para remover", + "GURPS.collapse": "Desmaio", + "GURPS.color": "Cor", + "GURPS.combatTab": "Combate", + "GURPS.concentrationCheck": "Teste de Concentração", + "GURPS.condition": "Condição", + "GURPS.conditions": "Condições", + "GURPS.crippling": "Lesão incapacitante, ", + "GURPS.current": "Atual", + "GURPS.currentdodge": "Esquiva", + "GURPS.damageAbove": "Dano acima de ", + "GURPS.dead": "Morto(a)", + "GURPS.defense": "Defesa", + "GURPS.destroyed": "Destruído(a)", + "GURPS.Dice": "Dados", + "GURPS.during": "Durante", + "GURPS.dxCheckOrFallApplyProne": "{name}: faça um teste de DX ou sofra uma queda!", + "GURPS.dxJudoAcrobaticsCheckToRemainStanding": "Faça um teste de [DX, Judô, ou Acrobacia] {modifierText} para permanecer de pé.", + "GURPS.effectsNotApplicableDefenses": "Não se aplica a Defesas Ativas ou outras reações defensivas.", + "GURPS.effectsTemporaryAttributePenalties": "Ver Penalidades de Atributo Temporárias", + "GURPS.equipmentTab": "Equipamento", + "GURPS.equippedblock": "Bloqueio", + "GURPS.equippedparry": "Aparar", + "GURPS.fail": "Fracasso", + "GURPS.fallsDownApplyProne": "{name}: se deita!", + "GURPS.for": "para", + "GURPS.forHighPainThreshold": "{mod} para Hipoalgia", + "GURPS.forLowPainThreshold": "{mod} para Hiperalgia", + "GURPS.forPerfectBalance": "{mod} para Equilíbrio Perfeito", + "GURPS.chatGameAidUsersGuide": "GUIA DE USUÁRIO do Auxílio para GURPS 4e", + "GURPS.groundCreatures": "Criaturas Terrestres", + "GURPS.groundCreaturesSuffer": "Criaturas terrestres recebem", + "GURPS.headVitalsHit": "Acerto na cabeça ou orgãos vitais ", + "GURPS.highPainThresholdNoPenalty": "Hipoalgia ignora, sem penalidades", + "GURPS.hpIgnored": " PV são ignorados.", + "GURPS.htCheck": "Teste de HT", + "GURPS.ID": "ID", + "GURPS.itemBonusText": "Insira Fórmulas 'Bônus' On-the-Fly (uma por linha) para modificar valores de atributos, perícias, etc.", + "GURPS.itemEditor": "Editor de Itens", + "GURPS.itemFeatures": "Características", + "GURPS.itemImport": "Importar Biblioteca de Equipamentos", + "GURPS.knockback": "Projeção, {amount} {unit}", + "GURPS.knockbackCheck": "{name}: teste de {dx}, {acrobacia}, ou {judô} ou sofra uma queda!", + "GURPS.level": "Nív.", + "GURPS.lighting": "Iluminação", + "GURPS.location": "Ponto", + "GURPS.lowPainThresholdDoubles": "Hiperalgia duplica a penalidade", + "GURPS.majorWound": "Ferimento Grave", + "GURPS.majorWoundEffect": " para evitar Atordoamento ou Nocaute.", + "GURPS.majorWoundEffectLabel": "{name}: teste de {htCheck} para evitar Atordoamento/Nocaute.", + "GURPS.max": "Máx", + "GURPS.maximum": "Máximo", + "GURPS.melee": "Corpo a Corpo", + "GURPS.meleeAttack": "Ataque Corpo a Corpo", + "GURPS.meters": " metros", + "GURPS.minimum": "Mínimo", + "GURPS.minimumDamageRule": "* — Regra de dano mínimo aplicada.", + "GURPS.name": "Nome", + "GURPS.noModifier": "Sem Modificador", + "GURPS.normal": "Normal", + "GURPS.notAffected": "não é afetado(a).", + "GURPS.notes": "Notas", + "GURPS.ok": "OK", + "GURPS.overridden": "substituído", + "GURPS.pass": "Sucesso", + "GURPS.pdfPageReference": "Ref de Pág", + "GURPS.pdfRef": "Ref", + "GURPS.pointDamage": "{damage} ponto de dano", + "GURPS.pointsDamage": "{damage} pontos de dano.", + "GURPS.quantity": "Quantidade", + "GURPS.ranged": "À Distância", + "GURPS.rangedAttack": "Ataque à Distância", + "GURPS.rateOfFire": "Cadência de Tiro", + "GURPS.reaction": "Reação", + "GURPS.reference": "Referência", + "GURPS.removeItem": "Remover Item", + "GURPS.resolve": "Determinação", + "GURPS.resource": "Recurso", + "GURPS.roll": "Teste", + "GURPS.rolled": "Resultado", + "GURPS.rollForMe": "Rolar para mim", + "GURPS.selectToken": "Selecionar Miniatura", + "GURPS.shock": "Choque", + "GURPS.shockPenalty": "Penalidade (–{amount}) para DX e IQ.", + "GURPS.shockPenaltyNextTurnOnly": "{name}: –{modifier} para DX e IQ apenas no próximo turno.", + "GURPS.showQuestion": "Exibir?", + "GURPS.skill": "Perícia", + "GURPS.skillLevel": "Nível de Habilidade", + "GURPS.skillsTab": "Perícias", + "GURPS.spell": "Mágica", + "GURPS.spellsTab": "Mágicas", + "GURPS.statsTab": "Características", + "GURPS.suffersAMajorWound": "{name} sofre um Ferimento Grave", + "GURPS.suffersHeadVitalsWound": "{name} foi atingido(a) no(a) {location} com uma Penalidade de Choque.", + "GURPS.suffersKnockback": "{name} sofre uma Projeção {classStart}([PDF:{pdfref}]){classEnd} de {yards} {unit}.", + "GURPS.swimmerFlyer": "Nadador/Voador", + "GURPS.swimmersOrFlyersSuffer": "Nadadores ou voadores sofrem", + "GURPS.target": "Alvo", + "GURPS.targeting": "{name} é o alvo", + "GURPS.noTargetSelected": "Nenhum Alvo selecionado", + "GURPS.tired": "Cansado(a)", + "GURPS.toAllDXBasedRolls": " para todos os testes baseados em DX", + "GURPS.TransferTo": "Transferir para", + "GURPS.unconscious": "Inconsciente", + "GURPS.update": "Atualização", + "GURPS.warning": "AVISO", + "GURPS.yard": "jarda", + "GURPS.yards": "jardas", + "GURPS.addTracker": "Adicionar Controle de Recurso no final", + "GURPS.edit": "Editar", + "GURPS.moveToCarriedEquipment": "Mover para Equipamento Portado", + "GURPS.dragSameContainer": "Não é possível adicionar o objeto e este contêiner, pois ele já está dentro dele.", + "GURPS.dropResolve": "Onde você quer soltar este objeto?", + "GURPS.dropBefore": "Antes do alvo", + "GURPS.dropInside": "Dentro do alvo", + "GURPS.moveNone": "Nenhum ({reason})", + "GURPS.moveConstant": "{value} {unit}/seg ({reason})", + "GURPS.moveStep": "Passo ({reason})", + "GURPS.moveOneThird": "×1/3 ({reason})", + "GURPS.moveTwoThirds": "×2/3 ({reason})", + "GURPS.moveHalf": "Metade ({reason})", + "GURPS.moveFull": "Cheio", + "GURPS.setManeuver": "Configurar Manobra", + "GURPS.abbrevPoints": "Ptos", + "GURPS.abbrevReference": "Ref", + "GURPS.attributesSecondary": "Atributos Secundários", + "GURPS.attributesPrimary": "Atributos Básicos", + "GURPS.injury": "Lesão", + "GURPS.serverity": "Severidade", + "GURPS.days": "Dias", + "GURPS.none": "Nenhum", + "GURPS.equipmentCarried": "Equipamento Portado", + "GURPS.equipmentOther": "Outros Equipamentos", + "GURPS.equipmentUserCreated": "Criado pelo Usuário", + "GURPS.equipmentIgnoreQtyImport": "Importar não atualiza a quantidade.", + "GURPS.showFlightMove": "Exibir Desloc./Desloc. Aéreo", + "GURPS.rt": "CR", + "GURPS.thresholds": "Limites", + "GURPS.conditionalMods": "Modificadores Condicionais", + "GURPS.ignoreBodyPlan": "Ignorar Tipo de Corpo Importado", + "GURPS.abbrevRef": "Ref", + "GURPS.noteBlank": "Esta nota foi intencionalmente deixada em branco.", + "GURPS.pointsTotal": "Total de Pontos", + "GURPS.severities": "Severidades", + "GURPS.addAdjustedForDamageType": "‡ - Ajustado devido ao Modificador de Dano", + "GURPS.addDamageModifier": "Modificador de Dano", + "GURPS.reset": "Limpar Configuração", + "GURPS.resolveDiceRoll": "Qual Foi a Jogada?", + "GURPS.settingUsePhysicalDice": "Usar Dados Físicos", + "GURPS.settingHintUsePhysicalDice": "Se ativado, personagens de CONFIANÇA receberão uma notificação para todas as jogadas de dados. Dessa forma eles podem jogar dados físicos e inserir os resultados no Foundry.", + "GURPS.STATUSStanding": "Em Pé", + "GURPS.STATUSCrawling": "Rastejando", + "GURPS.STATUSProne": "Deitado", + "GURPS.effectHintBlind": "-6 na jogada de ataque se acostumado à cegueira; Audição -2 um sucesso reduz a penalidade na jogada de ataque para -4.", + "GURPS.effectChatModifiedToHit": "{displayName} :
[{modifier}]", + "GURPS.effectChatRangedModifier": "{displayName} :
[-2 nas jogadas de ataque feitas contra você com armas de combate à distância ({posture})].", + "GURPS.tokenToolsTitle": "Abrir Janela de Modificadores de Efeitos", + "GURPS.effectModifierPopout": "Modificadores de Efeitos", + "GURPS.effectModNoTokenSelected": "Nenhuma miniatura selecionada", + "GURPS.targetedModifiers": "Modificadores Escolhidos", + "GURPS.settingActiveEffects": "Acionar Efeitos Ativos", + "GURPS.targetModifiers": "Alvo:", + "GURPS.settingHintActiveEffects": "Permitir ao Mestre criar e aplicar Efeitos Ativos", + "GURPS.CR0": "CR: N/D (Incapaz de Resistir)", + "GURPS.CR6": "CR: 6 (Resiste Raramente)", + "GURPS.CR9": "CR: 9 (Resiste Com Alguma Frequência)", + "GURPS.CR12": "CR: 12 (Resiste Com Muita Frequência)", + "GURPS.CR15": "CR: 15 (Resiste Quase Sempre)", + "GURPS.modifiersBlindAttack": "-10 na jogada de ataque (Cego)", + "GURPS.modifiersBlindDefend": "-4 nas Defesas Ativas (Cego)", + "GURPS.moveModeGround": "Solo", + "GURPS.moveModeAir": "Ar", + "GURPS.moveModeWater": "Água", + "GURPS.moveModeSpace": "Espaço", + "GURPS.moveModeOther": "Outro...", + "GURPS.moveModeType": "Tipo de Deslocamento", + "GURPS.moveModeValue": "Metros/Turno", + "GURPS.effectsTermination": "Condição para Finalizar (OtF)", + "GURPS.effectsEffect": "Efeito", + "GURPS.default": "Predefinido", + "GURPS.conditionsCombatMove": "Deslocamento em Combate", + "GURPS.activeEffects": "Efeitos Ativos", + "GURPS.quicknotes": "Notas Rápidas", + "GURPS.language": "Idioma", + "GURPS.spoken": "Falado", + "GURPS.written": "Escrito", + "GURPS.pdfOffset": "Ajuste de página", + "GURPS.pdfCode": "Código do PDF", + "__Rolling__": "=========", + "GURPS.rollVs": "Rolagem contra", + "GURPS.rollNewTarget": "Novo alvo: ({target})", + "GURPS.rollCriticalSuccess": "Sucesso decisivo!", + "GURPS.rollSuccess": "Sucesso!", + "GURPS.rollFailure": "Falha!", + "GURPS.rollCriticalFailure": "Falha crítica!", + "GURPS.rollFail17": "17 e 18 sempre falham.", + "GURPS.rollJustMadeIt": "Por um triz", + "GURPS.rollMadeBy": "Margem de acerto {margin}.", + "GURPS.rollMissedBy": "Margem de fracasso {margin}.", + "GURPS.rollTotalHits": "{rofrcl} acertos possíveis ({link})
devido à CdT ({rof}) e o RCO ({rcl}).", + "GURPS.rollTotal": "Resultado da rolagem ({rolls}) = {rtotal}." } diff --git a/lib/hitpoints.js b/lib/hitpoints.js index 3f313c4ab..c7915de86 100755 --- a/lib/hitpoints.js +++ b/lib/hitpoints.js @@ -11,76 +11,76 @@ import { i18n } from './utilities.js' /** @type Record */ const hpConditions = { - NORMAL: { - breakpoint: _ => Number.MAX_SAFE_INTEGER, - label: 'GURPS.normal', - style: 'normal', - }, - REELING: { - breakpoint: HP => Math.ceil(HP.max / 3) - 1, - label: 'GURPS.STATUSReeling', - style: 'reeling', - }, - COLLAPSE: { - breakpoint: _ => 0, - label: 'GURPS.collapse', - style: 'collapse', - }, - CHECK1: { - breakpoint: HP => -1 * HP.max, - label: 'GURPS.check1', - style: 'check', - }, - CHECK2: { - breakpoint: HP => -2 * HP.max, - label: 'GURPS.check2', - style: 'check', - }, - CHECK3: { - breakpoint: HP => -3 * HP.max, - label: 'GURPS.check3', - style: 'check', - }, - CHECK4: { - breakpoint: HP => -4 * HP.max, - label: 'GURPS.check4', - style: 'check', - }, - DEAD: { - breakpoint: HP => -5 * HP.max, - label: 'GURPS.dead', - style: 'dead', - }, - DESTROYED: { - breakpoint: HP => -10 * HP.max, - label: 'GURPS.destroyed', - style: 'destroyed', - }, + NORMAL: { + breakpoint: _ => Number.MAX_SAFE_INTEGER, + label: 'GURPS.normal', + style: 'normal', + }, + REELING: { + breakpoint: HP => Math.ceil(HP.max / 3) - 1, + label: 'GURPS.STATUSReeling', + style: 'reeling', + }, + COLLAPSE: { + breakpoint: _ => 0, + label: 'GURPS.collapse', + style: 'collapse', + }, + CHECK1: { + breakpoint: HP => -1 * HP.max, + label: 'GURPS.check1', + style: 'check', + }, + CHECK2: { + breakpoint: HP => -2 * HP.max, + label: 'GURPS.check2', + style: 'check', + }, + CHECK3: { + breakpoint: HP => -3 * HP.max, + label: 'GURPS.check3', + style: 'check', + }, + CHECK4: { + breakpoint: HP => -4 * HP.max, + label: 'GURPS.check4', + style: 'check', + }, + DEAD: { + breakpoint: HP => -5 * HP.max, + label: 'GURPS.dead', + style: 'dead', + }, + DESTROYED: { + breakpoint: HP => -10 * HP.max, + label: 'GURPS.destroyed', + style: 'destroyed', + }, } /** @type Record */ const fpConditions = { - NORMAL: { - breakpoint: _ => Number.MAX_SAFE_INTEGER, - label: 'GURPS.normal', - style: 'normal', - }, - REELING: { - breakpoint: FP => Math.ceil(FP.max / 3) - 1, - label: 'GURPS.tired', - style: 'tired', - }, - COLLAPSE: { - breakpoint: _ => 0, - label: 'GURPS.collapse', - - style: 'collapse', - }, - UNCONSCIOUS: { - breakpoint: FP => -1 * FP.max, - label: 'GURPS.unconscious', - style: 'unconscious', - }, + NORMAL: { + breakpoint: _ => Number.MAX_SAFE_INTEGER, + label: 'GURPS.normal', + style: 'normal', + }, + REELING: { + breakpoint: FP => Math.ceil(FP.max / 3) - 1, + label: 'GURPS.tired', + style: 'tired', + }, + COLLAPSE: { + breakpoint: _ => 0, + label: 'GURPS.collapse', + + style: 'collapse', + }, + UNCONSCIOUS: { + breakpoint: FP => -1 * FP.max, + label: 'GURPS.unconscious', + style: 'unconscious', + }, } /* @@ -94,132 +94,132 @@ const fpConditions = { * "Reeling" is 4 (or, 12 / 3). */ export default class HitFatPoints { - constructor() { - this.setup() - } - - setup() { - // "this" must be bound to the methods BEFORE they are registered as handlebar helpers - Handlebars.registerHelper('hpFpCondition', this._resolveCondition.bind(this)) - - Handlebars.registerHelper('hpFpBreakpoints', this._resolveBreakpoints.bind(this)) - - Handlebars.registerHelper('hpCondition', this.hpCondition.bind(this)) - Handlebars.registerHelper('hpBreakpoints', this.getHpBreakpoints.bind(this)) - - Handlebars.registerHelper('fpCondition', this.fpCondition.bind(this)) - Handlebars.registerHelper('fpBreakpoints', this.getFpBreakpoints.bind(this)) - } - - /** - * @param {string} type - * @param {Attribute} value - * @param {string} attr - */ - _resolveCondition(type, value, attr) { - if (type === 'HP') return this.hpCondition(value, attr) - if (type === 'FP') return this.fpCondition(value, attr) - throw `hpFpCondition called with invalid type: [${type}]` - } - - /** - * @param {Attribute} HP - * @param {string} member - */ - hpCondition(HP, member) { - let key = this._getConditionKey(HP, hpConditions) - // @ts-ignore - return hpConditions[key][member] - } - - /** - * @param {Attribute} FP - * @param {string} member - */ - fpCondition(FP, member) { - let key = this._getConditionKey(FP, fpConditions) - // @ts-ignore - return fpConditions[key][member] - } - - /** - * @param {Attribute} pts - * @param {Record} conditions - */ - _getConditionKey(pts, conditions) { - let found = 'NORMAL' - for (const [key, value] of Object.entries(conditions)) { - if (!!pts && pts.value > value.breakpoint(pts)) { - return found - } - found = key - } - return found - } - - /** - * @param {string} type - * @param {Attribute} value - * @param {any} options - */ - _resolveBreakpoints(type, value, options) { - if (type === 'HP') return this.getHpBreakpoints(value, options) - if (type === 'FP') return this.getFpBreakpoints(value, options) - throw `hpFpBreakpoints called with invalid type: [${type}]` - } - - /** - * @param {Record} conditions - * @param {Attribute} pts - * @param {any} options - */ - _getBreakpoints(conditions, pts, options) { - /** @type {{breakpoint: number, label: string, style: string}[]} */ - let list = [] - for (const [key, value] of Object.entries(conditions)) { - let currentKey = this._getConditionKey(pts, conditions) - list.push({ - breakpoint: Math.floor(value.breakpoint(pts || 0)), - label: i18n(value.label), - style: key === currentKey ? 'selected' : '', - }) - } - list.shift() // throw out the first element ('Normal') - return this._buildOutput(list, options) - } - - /** - * @param {Attribute} HP - * @param {any} options - */ - getHpBreakpoints(HP, options) { - return this._getBreakpoints(hpConditions, HP, options) - } - - /** - * @param {Attribute} FP - * @param {any} options - */ - getFpBreakpoints(FP, options) { - return this._getBreakpoints(fpConditions, FP, options) - } - - /** - * @param {{breakpoint: number, label: string, style: string}[]} list - * @param {{ fn: (arg0: any) => string; }} opt - */ - _buildOutput(list, opt) { - let results = '' - list.forEach(item => { - results += opt.fn(item) - }) - return results - } - - get hpConditions() { - return hpConditions - } - get fpConditions() { - return fpConditions - } + constructor() { + this.setup() + } + + setup() { + // "this" must be bound to the methods BEFORE they are registered as handlebar helpers + Handlebars.registerHelper('hpFpCondition', this._resolveCondition.bind(this)) + + Handlebars.registerHelper('hpFpBreakpoints', this._resolveBreakpoints.bind(this)) + + Handlebars.registerHelper('hpCondition', this.hpCondition.bind(this)) + Handlebars.registerHelper('hpBreakpoints', this.getHpBreakpoints.bind(this)) + + Handlebars.registerHelper('fpCondition', this.fpCondition.bind(this)) + Handlebars.registerHelper('fpBreakpoints', this.getFpBreakpoints.bind(this)) + } + + /** + * @param {string} type + * @param {Attribute} value + * @param {string} attr + */ + _resolveCondition(type, value, attr) { + if (type === 'HP') return this.hpCondition(value, attr) + if (type === 'FP') return this.fpCondition(value, attr) + throw `hpFpCondition called with invalid type: [${type}]` + } + + /** + * @param {Attribute} HP + * @param {string} member + */ + hpCondition(HP, member) { + let key = this._getConditionKey(HP, hpConditions) + // @ts-ignore + return hpConditions[key][member] + } + + /** + * @param {Attribute} FP + * @param {string} member + */ + fpCondition(FP, member) { + let key = this._getConditionKey(FP, fpConditions) + // @ts-ignore + return fpConditions[key][member] + } + + /** + * @param {Attribute} pts + * @param {Record} conditions + */ + _getConditionKey(pts, conditions) { + let found = 'NORMAL' + for (const [key, value] of Object.entries(conditions)) { + if (!!pts && pts.value > value.breakpoint(pts)) { + return found + } + found = key + } + return found + } + + /** + * @param {string} type + * @param {Attribute} value + * @param {any} options + */ + _resolveBreakpoints(type, value, options) { + if (type === 'HP') return this.getHpBreakpoints(value, options) + if (type === 'FP') return this.getFpBreakpoints(value, options) + throw `hpFpBreakpoints called with invalid type: [${type}]` + } + + /** + * @param {Record} conditions + * @param {Attribute} pts + * @param {any} options + */ + _getBreakpoints(conditions, pts, options) { + /** @type {{breakpoint: number, label: string, style: string}[]} */ + let list = [] + for (const [key, value] of Object.entries(conditions)) { + let currentKey = this._getConditionKey(pts, conditions) + list.push({ + breakpoint: Math.floor(value.breakpoint(pts || 0)), + label: i18n(value.label), + style: key === currentKey ? 'selected' : '', + }) + } + list.shift() // throw out the first element ('Normal') + return this._buildOutput(list, options) + } + + /** + * @param {Attribute} HP + * @param {any} options + */ + getHpBreakpoints(HP, options) { + return this._getBreakpoints(hpConditions, HP, options) + } + + /** + * @param {Attribute} FP + * @param {any} options + */ + getFpBreakpoints(FP, options) { + return this._getBreakpoints(fpConditions, FP, options) + } + + /** + * @param {{breakpoint: number, label: string, style: string}[]} list + * @param {{ fn: (arg0: any) => string; }} opt + */ + _buildOutput(list, opt) { + let results = '' + list.forEach(item => { + results += opt.fn(item) + }) + return results + } + + get hpConditions() { + return hpConditions + } + get fpConditions() { + return fpConditions + } } diff --git a/lib/markdown-it.js b/lib/markdown-it.js index dac66ae8d..6b0c385e8 100755 --- a/lib/markdown-it.js +++ b/lib/markdown-it.js @@ -10899,16 +10899,16 @@ module.exports = function text(state, silent) { root.punycode = punycode } })(this) - }.call( + }).call( this, typeof global !== 'undefined' ? global : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' - ? window - : {} - )) + ? self + : typeof window !== 'undefined' + ? window + : {} + ) }, {}, ], diff --git a/lib/moustachewax.js b/lib/moustachewax.js index 2447ecfa6..46bc206f7 100755 --- a/lib/moustachewax.js +++ b/lib/moustachewax.js @@ -594,15 +594,17 @@ export default function () { Handlebars.registerHelper('threshold-of', function (thresholds, max, value) { // return the index of the threshold that the value falls into let result = null - thresholds.some(function ( - /** @type {{ operator: string; comparison: string; value: number; }} */ threshold, - /** @type {number} */ index - ) { - let op = getOperation(threshold.operator) - let comparison = getComparison(threshold.comparison) - let testValue = op(max, threshold.value) - return comparison(value, testValue) ? ((result = index), true) : false - }) + thresholds.some( + function ( + /** @type {{ operator: string; comparison: string; value: number; }} */ threshold, + /** @type {number} */ index + ) { + let op = getOperation(threshold.operator) + let comparison = getComparison(threshold.comparison) + let testValue = op(max, threshold.value) + return comparison(value, testValue) ? ((result = index), true) : false + } + ) return result }) diff --git a/lib/parselink.js b/lib/parselink.js index 02ff17299..033506cb9 100755 --- a/lib/parselink.js +++ b/lib/parselink.js @@ -424,7 +424,7 @@ export function parselink(str, htmldesc, clrdmods = false) { falsetext: opt[5], target: target, melee: melee, - sourceId: sourceId + sourceId: sourceId, } return { text: gspan(overridetxt, spantext, action, brtxt), diff --git a/lib/ranges.js b/lib/ranges.js index 50637ea86..16386b74a 100644 --- a/lib/ranges.js +++ b/lib/ranges.js @@ -38,238 +38,233 @@ import { i18n, i18n_f } from './utilities.js' */ export class RulerGURPS extends Ruler { - - _getSegmentLabel(segment, totalDistance) { - const units = canvas.scene.grid.units - let dist = (d, u) => { - return `${Math.round(d * 100) / 100} ${u}` - } - let yards = this.convert_to_yards(totalDistance, units) - let label = dist(segment.distance, units) - let mod = this.yardsToSpeedRangePenalty(yards) - GURPS.ModifierBucket.setTempRangeMod(mod) - if (segment.last) { + _getSegmentLabel(segment, totalDistance) { + const units = canvas.scene.grid.units + let dist = (d, u) => { + return `${Math.round(d * 100) / 100} ${u}` + } + let yards = this.convert_to_yards(totalDistance, units) + let label = dist(segment.distance, units) + let mod = this.yardsToSpeedRangePenalty(yards) + GURPS.ModifierBucket.setTempRangeMod(mod) + if (segment.last) { let total = `${dist(totalDistance, units)}` - if (total != label) - label += ` [${total}]` - } - return label + ` (${mod})` - } - - _endMeasurement() { - let addRangeMod = !this.draggedEntity // Will be false is using DragRuler and it was movement - super._endMeasurement() - if (addRangeMod) GURPS.ModifierBucket.addTempRangeMod() - } - - convert_to_yards(numeric, Unit) { - //console.log("entering convert to yards") - let meter = 0 - let unit = Unit.toLowerCase() - //console.log("Assigning Unit") - //console.log("Unit in convert_to_yards is " + unit); - if (unit == 'meters' || unit == 'meter' || unit == 'm') meter = numeric - else if (unit == 'millimeters' || unit == 'millimeter' || unit == 'mm') meter = numeric / 1000 - else if (unit == 'kilometers' || unit == 'kilometer' || unit == 'km') meter = numeric * 1000 - else if (unit == 'miles' || unit == 'mile' || unit == 'mi') meter = numeric / 0.00062137 - else if (unit == 'inches' || unit == 'inch' || unit == 'in') meter = numeric / 39.37 - else if (unit == 'centimeters' || unit == 'centimeter' || unit == 'cm') meter = numeric / 100 - else if (unit == 'feet' || unit == 'foot' || unit == 'ft') meter = numeric / 3.2808 - else if (unit == 'yards' || unit == 'yard' || unit == 'yd' || unit == 'y') meter = numeric / (3.2808 / 3) - else if (unit == 'lightyears' || unit == 'lightyear' || unit == 'ly') meter = numeric * 9460730472580800 - else if (unit == 'astronomical units' || unit == 'astronomical unit' || unit == 'au') meter = numeric * 149597870700 - else if (unit == 'parsecs' || unit == 'parsec' || unit == 'pc') meter = numeric * 30856776376340068 - return meter * 1.0936 - } - - yardsToSpeedRangePenalty(yards) { - let currentValue = game.settings.get(Settings.SYSTEM_NAME, Settings.SETTING_RANGE_STRATEGY) - if (currentValue == 'Standard') { - return GURPS.SSRT.getModifier(yards) - } else { - for (let range of GURPS.rangeObject.ranges) { - if (typeof range.max === 'string') - // Handles last distance being "500+" - return range.penalty - if (yards <= range.max) return range.penalty - } - } - } + if (total != label) label += ` [${total}]` + } + return label + ` (${mod})` + } + + _endMeasurement() { + let addRangeMod = !this.draggedEntity // Will be false is using DragRuler and it was movement + super._endMeasurement() + if (addRangeMod) GURPS.ModifierBucket.addTempRangeMod() + } + + convert_to_yards(numeric, Unit) { + //console.log("entering convert to yards") + let meter = 0 + let unit = Unit.toLowerCase() + //console.log("Assigning Unit") + //console.log("Unit in convert_to_yards is " + unit); + if (unit == 'meters' || unit == 'meter' || unit == 'm') meter = numeric + else if (unit == 'millimeters' || unit == 'millimeter' || unit == 'mm') meter = numeric / 1000 + else if (unit == 'kilometers' || unit == 'kilometer' || unit == 'km') meter = numeric * 1000 + else if (unit == 'miles' || unit == 'mile' || unit == 'mi') meter = numeric / 0.00062137 + else if (unit == 'inches' || unit == 'inch' || unit == 'in') meter = numeric / 39.37 + else if (unit == 'centimeters' || unit == 'centimeter' || unit == 'cm') meter = numeric / 100 + else if (unit == 'feet' || unit == 'foot' || unit == 'ft') meter = numeric / 3.2808 + else if (unit == 'yards' || unit == 'yard' || unit == 'yd' || unit == 'y') meter = numeric / (3.2808 / 3) + else if (unit == 'lightyears' || unit == 'lightyear' || unit == 'ly') meter = numeric * 9460730472580800 + else if (unit == 'astronomical units' || unit == 'astronomical unit' || unit == 'au') meter = numeric * 149597870700 + else if (unit == 'parsecs' || unit == 'parsec' || unit == 'pc') meter = numeric * 30856776376340068 + return meter * 1.0936 + } + + yardsToSpeedRangePenalty(yards) { + let currentValue = game.settings.get(Settings.SYSTEM_NAME, Settings.SETTING_RANGE_STRATEGY) + if (currentValue == 'Standard') { + return GURPS.SSRT.getModifier(yards) + } else { + for (let range of GURPS.rangeObject.ranges) { + if (typeof range.max === 'string') + // Handles last distance being "500+" + return range.penalty + if (yards <= range.max) return range.penalty + } + } + } } export class GURPSRange { - constructor() { - // this.setup() - this.update() - this._buildModifiers() - } - - static get basicSetRanges() { - const basicSetRanges = [] - - // Yes, I should be able to do this programatically... but my brain hurts right now, so there. - const r = [ - 2, - 0, - 3, - -1, - 5, - -2, - 7, - -3, - 10, - -4, - 15, - -5, - 20, - -6, - 30, - -7, - 50, - -8, - 70, - -9, - 100, - -10, - 150, - -11, - 200, - -12, - 300, - -13, - 500, - -14, - '500+', - -15, - ] - - for (let i = 0; i < r.length; i = i + 2) { - let d = { - moddesc: i18n_f("GURPS.modifierRange", { range: r[i] }), - max: r[i], - penalty: r[i + 1], - desc: `${r[i]} yds`, - } - basicSetRanges.push(d) - } - return basicSetRanges - } - - static get monsterHunter2Ranges() { - const monsterHunter2Ranges = [ - { - moddesc: i18n("GURPS.modifierRangeMHClose"), - max: 5, - penalty: 0, - description: i18n("GURPS.modifierRangeMHCloseDesc"), - }, - { - moddesc: i18n("GURPS.modifierRangeMHShort"), - max: 20, - penalty: -3, - description: i18n("GURPS.modifierRangeMHShortDesc"), - }, - { - moddesc: i18n("GURPS.modifierRangeMHMedium"), - max: 100, - penalty: -7, - description: i18n("GURPS.modifierRangeMHMediumDesc"), - }, - { - moddesc: i18n("GURPS.modifierRangeMHLong"), - max: 500, - penalty: -11, - description: i18n("GURPS.modifierRangeMHLongDesc"), - }, - { - moddesc: i18n("GURPS.modifierRangeMHExtreme"), - max: '500+', // Finaly entry. We will check for "is string" to assume infinite - penalty: -15, - description: i18n("GURPS.modifierRangeMHExtremeDesc"), - }, - ] - return monsterHunter2Ranges - } - - static get penaltiesPerTenRanges() { - const penaltiesPerTenRanges = [] - for (let i = 0; i < 50; i++) { - penaltiesPerTenRanges.push({ - moddesc: i18n_f("GURPS.modifierRange", { range: (i + 1) * 10 }), - max: (i + 1) * 10, - penalty: -i, - desc: `${(i + 1) * 10} yds`, - }) - return penaltiesPerTenRanges - } + constructor() { + // this.setup() + this.update() + this._buildModifiers() + } + static get basicSetRanges() { + const basicSetRanges = [] + + // Yes, I should be able to do this programatically... but my brain hurts right now, so there. + const r = [ + 2, + 0, + 3, + -1, + 5, + -2, + 7, + -3, + 10, + -4, + 15, + -5, + 20, + -6, + 30, + -7, + 50, + -8, + 70, + -9, + 100, + -10, + 150, + -11, + 200, + -12, + 300, + -13, + 500, + -14, + '500+', + -15, + ] + + for (let i = 0; i < r.length; i = i + 2) { + let d = { + moddesc: i18n_f('GURPS.modifierRange', { range: r[i] }), + max: r[i], + penalty: r[i + 1], + desc: `${r[i]} yds`, + } + basicSetRanges.push(d) + } + return basicSetRanges + } - // Must be kept in order... checking range vs Max. If >Max, go to next entry. - - } - - - _buildModifiers() { - /** @type {import('../module/modifier-bucket/bucket-app.js').Modifier[]} */ - let m = [] - this.ranges.forEach(band => { - if (band.penalty != 0) GURPS.ModifierBucket.addModifier(band.penalty, band.moddesc, m) - }) - this.modifiers = m.map(e => e.mod + ' ' + e.desc) - } - - async update() { - let currentValue = game.settings.get(Settings.SYSTEM_NAME, Settings.SETTING_RANGE_STRATEGY) - console.debug(currentValue) - - switch (currentValue) { - case 'Standard': { - this.ranges = GURPSRange.basicSetRanges - break - } - case 'TenPenalties': { - this.ranges = GURPSRange.penaltiesPerTenRanges - break - } - default: { - this.ranges = GURPSRange.monsterHunter2Ranges - break - } - } + static get monsterHunter2Ranges() { + const monsterHunter2Ranges = [ + { + moddesc: i18n('GURPS.modifierRangeMHClose'), + max: 5, + penalty: 0, + description: i18n('GURPS.modifierRangeMHCloseDesc'), + }, + { + moddesc: i18n('GURPS.modifierRangeMHShort'), + max: 20, + penalty: -3, + description: i18n('GURPS.modifierRangeMHShortDesc'), + }, + { + moddesc: i18n('GURPS.modifierRangeMHMedium'), + max: 100, + penalty: -7, + description: i18n('GURPS.modifierRangeMHMediumDesc'), + }, + { + moddesc: i18n('GURPS.modifierRangeMHLong'), + max: 500, + penalty: -11, + description: i18n('GURPS.modifierRangeMHLongDesc'), + }, + { + moddesc: i18n('GURPS.modifierRangeMHExtreme'), + max: '500+', // Finaly entry. We will check for "is string" to assume infinite + penalty: -15, + description: i18n('GURPS.modifierRangeMHExtremeDesc'), + }, + ] + return monsterHunter2Ranges + } - this._buildModifiers() + static get penaltiesPerTenRanges() { + const penaltiesPerTenRanges = [] + for (let i = 0; i < 50; i++) { + penaltiesPerTenRanges.push({ + moddesc: i18n_f('GURPS.modifierRange', { range: (i + 1) * 10 }), + max: (i + 1) * 10, + penalty: -i, + desc: `${(i + 1) * 10} yds`, + }) + return penaltiesPerTenRanges + } + + // Must be kept in order... checking range vs Max. If >Max, go to next entry. + } - // update modifier bucket - if (!!GURPS.ModifierBucket) GURPS.ModifierBucket.refresh() + _buildModifiers() { + /** @type {import('../module/modifier-bucket/bucket-app.js').Modifier[]} */ + let m = [] + this.ranges.forEach(band => { + if (band.penalty != 0) GURPS.ModifierBucket.addModifier(band.penalty, band.moddesc, m) + }) + this.modifiers = m.map(e => e.mod + ' ' + e.desc) + } - // FYI update all actors - for (const actor of game.actors.contents) { - if (actor.permission >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER) - // Return true if the current game user has observer or owner rights to an actor - await actor.update({ ranges: this.ranges }) - } - } + async update() { + let currentValue = game.settings.get(Settings.SYSTEM_NAME, Settings.SETTING_RANGE_STRATEGY) + console.debug(currentValue) + + switch (currentValue) { + case 'Standard': { + this.ranges = GURPSRange.basicSetRanges + break + } + case 'TenPenalties': { + this.ranges = GURPSRange.penaltiesPerTenRanges + break + } + default: { + this.ranges = GURPSRange.monsterHunter2Ranges + break + } + } + + this._buildModifiers() + + // update modifier bucket + if (!!GURPS.ModifierBucket) GURPS.ModifierBucket.refresh() + + // FYI update all actors + for (const actor of game.actors.contents) { + if (actor.permission >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER) + // Return true if the current game user has observer or owner rights to an actor + await actor.update({ ranges: this.ranges }) + } + } } class SizeAndSpeedRangeTable { - constructor() { - this._table = new RepeatingSequenceConverter([2, 3, 5, 7, 10, 15]) - } - - // pass in distance in yards, get back modifier - getModifier(yards) { - return -this._table.valueToIndex(yards) - } - - // pass in modifier, get distance in yards - getDistance(modifier) { - return this._table.indexToValue(modifier) - } - - // pass in distance in yards, get back the furthest distance that has the same modifier - ceil(yards) { - return this._table.ceil(measure) - } + constructor() { + this._table = new RepeatingSequenceConverter([2, 3, 5, 7, 10, 15]) + } + + // pass in distance in yards, get back modifier + getModifier(yards) { + return -this._table.valueToIndex(yards) + } + + // pass in modifier, get distance in yards + getDistance(modifier) { + return this._table.indexToValue(modifier) + } + + // pass in distance in yards, get back the furthest distance that has the same modifier + ceil(yards) { + return this._table.ceil(measure) + } } // Must be kept in order... checking range vs Max. If >Max, go to next entry. @@ -281,10 +276,9 @@ class SizeAndSpeedRangeTable { */ export function setupRanges() { - // GURPS.SSRT = new SizeAndSpeedRangeTable() - return new SizeAndSpeedRangeTable() - // GURPS.SSRT = SSRT + // GURPS.SSRT = new SizeAndSpeedRangeTable() + return new SizeAndSpeedRangeTable() + // GURPS.SSRT = SSRT } - // Hooks.on('ready', () => GURPS.SSRT = SSRT) diff --git a/lib/xregexp-all.js b/lib/xregexp-all.js index 8a4d3de29..445843d79 100644 --- a/lib/xregexp-all.js +++ b/lib/xregexp-all.js @@ -4264,7 +4264,8 @@ value = self[index] result = boundFunction(value, index, O) if (TYPE) { - if (IS_MAP) target[index] = result // map + if (IS_MAP) + target[index] = result // map else if (result) switch (TYPE) { case 3: @@ -4628,17 +4629,17 @@ return it === undefined ? 'Undefined' : it === null - ? 'Null' - : // @@toStringTag case - typeof (tag = tryGet((O = Object(it)), TO_STRING_TAG)) == 'string' - ? tag - : // builtinTag case - CORRECT_ARGUMENTS - ? classofRaw(O) - : // ES3 arguments fallback - (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' - ? 'Arguments' - : result + ? 'Null' + : // @@toStringTag case + typeof (tag = tryGet((O = Object(it)), TO_STRING_TAG)) == 'string' + ? tag + : // builtinTag case + CORRECT_ARGUMENTS + ? classofRaw(O) + : // ES3 arguments fallback + (result = classofRaw(O)) == 'Object' && typeof O.callee == 'function' + ? 'Arguments' + : result } }, { @@ -5274,17 +5275,17 @@ return this })() || Function('return this')() - }.call(this)) - }.call( + }).call(this) + }).call( this, typeof global !== 'undefined' ? global : typeof self !== 'undefined' - ? self - : typeof window !== 'undefined' - ? window - : {} - )) + ? self + : typeof window !== 'undefined' + ? window + : {} + ) }, {}, ], @@ -5498,10 +5499,10 @@ return value == POLYFILL ? true : value == NATIVE - ? false - : typeof detection == 'function' - ? fails(detection) - : !!detection + ? false + : typeof detection == 'function' + ? fails(detection) + : !!detection } var normalize = (isForced.normalize = function (string) { @@ -6276,8 +6277,8 @@ ? S.charAt(position) : first : CONVERT_TO_STRING - ? S.slice(position, position + 2) - : ((first - 0xd800) << 10) + (second - 0xdc00) + 0x10000 + ? S.slice(position, position + 2) + : ((first - 0xd800) << 10) + (second - 0xdc00) + 0x10000 } } diff --git a/module/actor/actor-importer.js b/module/actor/actor-importer.js new file mode 100644 index 000000000..7f41d6ece --- /dev/null +++ b/module/actor/actor-importer.js @@ -0,0 +1,2314 @@ +import { xmlTextToJson, recurselist, i18n, i18n_f, arrayBuffertoBase64 } from '../../lib/utilities.js' +import * as HitLocations from '../hitlocation/hitlocation.js' +import * as settings from '../../lib/miscellaneous-settings.js' +import { SmartImporter } from '../smart-importer.js' +import { parseDecimalNumber } from '../../lib/parse-decimal-number/parse-decimal-number.js' +import { + _Base, + Skill, + Spell, + Advantage, + Ranged, + Note, + Encumbrance, + Equipment, + Reaction, + Modifier, + Melee, + Language, +} from './actor-components.js' + +// const GCA5Version = 'GCA5-14' +const GCAVersion = 'GCA-11' + +export class ActorImporter { + GCSVersion = 0 + + constructor(actor) { + this.actor = actor + } + + async importActor() { + let p = this.actor.system.additionalresources.importpath + if (!!p) { + let m = p.match(/.*[/\\]Data[/\\](.*)/) + if (!!m) { + let f = m[1].replace(/\\/g, '/') + let xhr = new XMLHttpRequest() + xhr.responseType = 'arraybuffer' + xhr.open('GET', f) + new Promise(resolve => { + xhr.onload = () => { + if (xhr.status === 200) { + let s = arrayBuffertoBase64(xhr.response) + this.importActorFromExternalProgram(s, m[1], p) + } else this._openImportDialog() + resolve(this) + } + }) + xhr.send(null) + } else this._openImportDialog() + } else this._openImportDialog() + } + + async _openImportDialog() { + if (game.settings.get(settings.SYSTEM_NAME, settings.SETTING_USE_BROWSER_IMPORTER)) + this._openNonLocallyHostedImportDialog() + else this._openLocallyHostedImportDialog() + } + + async _openNonLocallyHostedImportDialog() { + try { + const file = await SmartImporter.getFileForActor(this) + const res = await this.importActorFromExternalProgram(await file.text(), file.name) + if (res) SmartImporter.setFileForActor(this, file) + } catch (e) { + ui.notifications?.error(e) + throw e + } + } + + async _openLocallyHostedImportDialog() { + setTimeout(async () => { + new Dialog( + { + title: `Import character data for: ${this.actor.name}`, + content: await renderTemplate('systems/gurps/templates/import-gcs-v1-data.html', { + name: '"' + this.actor.name + '"', + }), + buttons: { + import: { + icon: '', + label: 'Import', + callback: html => { + const form = html.find('form')[0] + let files = form.data.files + let file = null + if (!files.length) { + return ui.notifications.error('You did not upload a data file!') + } else { + file = files[0] + GURPS.readTextFromFile(file).then(text => + this.importActorFromExternalProgram(text, file.name, file.path) + ) + } + }, + }, + no: { + icon: '', + label: 'Cancel', + }, + }, + default: 'import', + }, + { + width: 400, + } + ).render(true) + }, 200) + } + + async importActorFromExternalProgram(source, importName, importPath, suppressMessage = false) { + if (importName.endsWith('.gcs')) return this.importActorFromGCS(source, importName, importPath, suppressMessage) + return this.importActorFromGCA(source, importName, importPath, suppressMessage) + } + + /** + * @param {string} json + * @param {string} importname + * @param {string | undefined} [importpath] + */ + async importActorFromGCS(json, importname, importpath, suppressMessage = false) { + let r + let msg = [] + let exit = false + try { + r = JSON.parse(json) + } catch (err) { + msg.push(i18n('GURPS.importNoJSONDetected')) + exit = true + } + if (!!r) { + if (!r.calc) { + msg.push(i18n('GURPS.importOldGCSFile')) + exit = true + } + } + this.GCSVersion = r.version + + if (msg.length > 0) { + ui.notifications?.error(msg.join('
')) + let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { + lines: msg, + version: version, + GCAVersion: GCAVersion, + GCSVersion: this.GCSVersion, + url: GURPS.USER_GUIDE_URL, + }) + ChatMessage.create({ + content: content, + user: game.user.id, + whisper: [game.user.id], + }) + if (exit) return false + } + + let nm = r['profile']['name'] + console.log("Importing '" + nm + "'") + let starttime = performance.now() + let commit = {} + + commit = { ...commit, ...{ 'system.lastImport': new Date().toString().split(' ').splice(1, 4).join(' ') } } + let ar = this.actor.system.additionalresources || {} + ar.importname = importname || ar.importname + ar.importpath = importpath || ar.importpath + try { + commit = { ...commit, ...{ 'system.additionalresources': ar } } + commit = { ...commit, ...(await this.importAttributesFromGCS(r.attributes, r.equipment, r.calc)) } + commit = { ...commit, ...(await this.importTraitsFromGCS(r.profile, r.created_date, r.modified_date)) } + commit = { + ...commit, + ...this.importSizeFromGCS(commit, r.profile, r.traits || r.advantages, r.skills, r.equipment), + } + if (r.version === 4) { + commit = { ...commit, ...this.importAdsFromGCS(r.traits || r.advantages) } + commit = { ...commit, ...this.importSkillsFromGCS(r.skills) } + commit = { ...commit, ...this.importSpellsFromGCS(r.spells) } + commit = { ...commit, ...this.importEquipmentFromGCS(r.equipment, r.other_equipment) } + commit = { ...commit, ...this.importNotesFromGCS(r.notes) } + } else if (r.version === 5) { + commit = { ...commit, ...this.importAdsFromGCS(r.traits || r.advantages) } + commit = { ...commit, ...this.importSkillsFromGCS(r.skills) } + commit = { ...commit, ...this.importSpellsFromGCS(r.spells) } + commit = { ...commit, ...this.importEquipmentFromGCS(r.equipment, r.other_equipment) } + commit = { ...commit, ...this.importNotesFromGCS(r.notes) } + } + + commit = { + ...commit, + ...(await this.importProtectionFromGCS(r.settings.body_type || r.settings.hit_locations)), + } + commit = { + ...commit, + ...this.importPointTotalsFromGCS(r.total_points, r.attributes, r.traits || r.advantages, r.skills, r.spells), + } + commit = { ...commit, ...this.importReactionsFromGCS(r.traits || r.advantages, r.skills, r.equipment) } + commit = { ...commit, ...this.importCombatFromGCS(r.traits || r.advantages, r.skills, r.spells, r.equipment) } + } catch (err) { + console.log(err.stack) + msg.push( + i18n_f('GURPS.importGenericError', { + name: nm, + error: err.name, + message: err.message, + }) + ) + let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { + lines: [msg], + version: version, + GCAVersion: GCAVersion, + GCSVersion: this.GCSVersion, + url: GURPS.USER_GUIDE_URL, + }) + ui.notifications?.warn(msg) + let chatData = { + user: game.user.id, + content: content, + whisper: [game.user.id], + } + ChatMessage.create(chatData, {}) + // Don't return + } + + console.log('Starting commit') + + let deletes = Object.fromEntries(Object.entries(commit).filter(([key, _value]) => key.includes('.-='))) + let adds = Object.fromEntries(Object.entries(commit).filter(([key, _value]) => !key.includes('.-='))) + + try { + this.ignoreRender = true + await this.actor.internalUpdate(deletes, { diff: true }) + await this.actor.internalUpdate(adds, { diff: false }) + // This has to be done after everything is loaded + await this.actor.postImport() + this.actor._forceRender() + + // Must update name outside of protection so that Actors list (and other external views) update correctly + if (!game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IGNORE_IMPORT_NAME)) { + await this.actor.update({ name: nm, 'token.name': nm }) + } + + if (!suppressMessage) ui.notifications?.info(i18n_f('GURPS.importSuccessful', { name: nm })) + console.log( + 'Done importing (' + + Math.round(performance.now() - starttime) + + 'ms.) You can inspect the character data below:' + ) + console.log(this) + return true + } catch (err) { + console.log(err.stack) + let msg = [i18n_f('GURPS.importGenericError', { name: nm, error: err.name, message: err.message })] + if (err.message == 'Maximum depth exceeded') msg.push(i18n('GURPS.importTooManyContainers')) + ui.notifications?.warn(msg.join('
')) + let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { + lines: msg, + version: 'GCS Direct', + GCAVersion: GCAVersion, + GCSVersion: this.GCSVersion, + url: GURPS.USER_GUIDE_URL, + }) + + let chatData = { + user: game.user.id, + content: content, + whisper: [game.user.id], + } + ChatMessage.create(chatData, {}) + return false + } + } + + async importActorFromGCA(source, importName, importPath, suppressMessage) { + let c, ra // The character json, release attributes + let isFoundryGCA = false + let isFoundryGCA5 = false + // need to remove

and replace

with newlines from "formatted text" + let origx = GURPS.cleanUpP(source) + let x = xmlTextToJson(origx) + let r = x.root + let msg = [] + let version = 'unknown' + let vernum = 1 + let exit = false + if (!r) { + if (importName.endsWith('.gca5')) msg.push(i18n('GURPS.importCannotImportGCADirectly')) + if (importName.endsWith('.gca4')) msg.push(i18n('GURPS.importCannotImportGCADirectly')) + else if (!xml.startsWith(' 0) { + ui.notifications?.error(msg.join('
')) + let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { + lines: msg, + version: version, + GCAVersion: GCAVersion, + GCSVersion: this.GCSVersion, + url: GURPS.USER_GUIDE_URL, + }) + + ChatMessage.create({ + content: content, + user: game.user.id, + whisper: [game.user.id], + }) + if (exit) return false // Some errors cannot be forgiven ;-) + } + let nm = this.textFrom(c.name) + console.log("Importing '" + nm + "'") + let starttime = performance.now() + + let commit = {} + commit = { ...commit, ...{ 'system.lastImport': new Date().toString().split(' ').splice(1, 4).join(' ') } } + let ar = this.actor.system.additionalresources || {} + ar.importName = importName || ar.importName + ar.importPath = importPath || ar.importPath + ar.importversion = ra.version + commit = { ...commit, ...{ 'system.additionalresources': ar } } + + try { + // This is going to get ugly, so break out various data into different methods + commit = { ...commit, ...(await this.importAttributesFromGCA(c.attributes)) } + commit = { ...commit, ...this.importSkillsFromGCA(c.abilities?.skilllist) } + commit = { ...commit, ...this.importTraitsfromGCA(c.traits) } + commit = { ...commit, ...this.importCombatMeleeFromGCA(c.combat?.meleecombatlist) } + commit = { ...commit, ...this.importCombatRangedFromGCA(c.combat?.rangedcombatlist) } + commit = { ...commit, ...this.importSpellsFromGCA(c.abilities?.spelllist) } + commit = { ...commit, ...this.importLangFromGCA(c.traits?.languagelist) } + commit = { ...commit, ...this.importAdsFromGCA(c.traits?.adslist, c.traits?.disadslist) } + commit = { ...commit, ...this.importReactionsFromGCA(c.traits?.reactionmodifiers, vernum) } + commit = { ...commit, ...this.importEncumbranceFromGCA(c.encumbrance) } + commit = { ...commit, ...this.importPointTotalsFromGCA(c.pointtotals) } + commit = { ...commit, ...this.importNotesFromGCA(c.description, c.notelist) } + commit = { ...commit, ...this.importEquipmentFromGCA(c.inventorylist) } + commit = { ...commit, ...(await this.importProtectionFromGCA(c.combat?.protectionlist)) } + } catch (err) { + console.log(err.stack) + let msg = i18n_f('GURPS.importGenericError', { name: nm, error: err.name, message: err.message }) + let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { + lines: [msg], + version: version, + GCAVersion: GCAVersion, + GCSVersion: this.GCSVersion, + url: GURPS.USER_GUIDE_URL, + }) + + ui.notifications?.warn(msg) + let chatData = { + user: game.user.id, + content: content, + whisper: [game.user.id], + } + ChatMessage.create(chatData, {}) + // Don't return, because we want to see how much actually gets committed. + } + console.log('Starting commit') + + let deletes = Object.fromEntries(Object.entries(commit).filter(([key, _value]) => key.includes('.-='))) + let adds = Object.fromEntries(Object.entries(commit).filter(([key, _value]) => !key.includes('.-='))) + + try { + this.ignoreRender = true + await this.actor.internalUpdate(deletes, { diff: false }) + await this.actor.internalUpdate(adds, { diff: false }) + // This has to be done after everything is loaded + await this.actor.postImport() + this.actor._forceRender() + + // Must update name outside of protection so that Actors list (and other external views) update correctly + if (!game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IGNORE_IMPORT_NAME)) { + await this.actor.update({ name: nm, 'token.name': nm }) + } + + if (!suppressMessage) ui.notifications?.info(i18n_f('GURPS.importSuccessful', { name: nm })) + console.log( + 'Done importing (' + + Math.round(performance.now() - starttime) + + 'ms.) You can inspect the character data below:' + ) + console.log(this) + return true + } catch (err) { + console.log(err.stack) + let msg = [i18n_f('GURPS.importGenericError', { name: nm, error: err.name, message: err.message })] + if (err.message == 'Maximum depth exceeded') msg.push(i18n('GURPS.importTooManyContainers')) + if (!supressMessage) ui.notifications?.warn(msg.join('
')) + let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { + lines: msg, + version: version, + GCAVersion: GCAVersion, + GCSVersion: this.GCSVersion, + url: GURPS.USER_GUIDE_URL, + }) + + let chatData = { + user: game.user.id, + content: content, + whisper: [game.user.id], + } + ChatMessage.create(chatData, {}) + return false + } + } + + // Import the section of the GCS FG XML file. + /** + * @param {{ [key: string]: any }} json + */ + async importAttributesFromGCA(json) { + if (!json) return + let i = this.intFrom // shortcut to make code smaller -- I reject your attempt to make the code smaller. Why does it need to be smaller? + let t = this.textFrom // shortcut to make code smaller -- I reject your attempt to make the code smaller. Why does it need to be smaller? + let data = this.actor.system + let att = data.attributes + + // attribute.values will be calculated in calculateDerivedValues() + att.ST.import = i(json.strength) + att.ST.points = i(json.strength_points) + att.DX.import = i(json.dexterity) + att.DX.points = i(json.dexterity_points) + att.IQ.import = i(json.intelligence) + att.IQ.points = i(json.intelligence_points) + att.HT.import = i(json.health) + att.HT.points = i(json.health_points) + att.WILL.import = i(json.will) + att.WILL.points = i(json.will_points) + att.PER.import = i(json.perception) + att.PER.points = i(json.perception_points) + + data.HP.max = i(json.hitpoints) + data.HP.points = i(json.hitpoints_points) + data.FP.max = i(json.fatiguepoints) + data.FP.points = i(json.fatiguepoints_points) + let hp = i(json.hps) + let fp = i(json.fps) + + let saveCurrent = false + if (!!data.lastImport && (data.HP.value != hp || data.FP.value != fp)) { + let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_HP_FP) + if (option == 0) { + saveCurrent = true + } + if (option == 2) { + saveCurrent = await new Promise(resolve => { + let d = new Dialog({ + title: 'Current HP & FP', + content: `Do you want to

Save the current HP (${data.HP.value}) & FP (${data.FP.value}) values or

Overwrite it with the import data, HP (${hp}) & FP (${fp})?

 `, + buttons: { + save: { + icon: '', + label: 'Save', + callback: () => resolve(true), + }, + overwrite: { + icon: '', + label: 'Overwrite', + callback: () => resolve(false), + }, + }, + default: 'save', + close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. + }) + d.render(true) + }) + } + } + if (!saveCurrent) { + data.HP.value = hp + data.FP.value = fp + } + + let lm = {} + lm.basiclift = t(json.basiclift) + lm.carryonback = t(json.carryonback) + lm.onehandedlift = t(json.onehandedlift) + lm.runningshove = t(json.runningshove) + lm.shiftslightly = t(json.shiftslightly) + lm.shove = t(json.shove) + lm.twohandedlift = t(json.twohandedlift) + + data.basicmove.value = t(json.basicmove) + data.basicmove.points = i(json.basicmove_points) + data.basicspeed.value = this.floatFrom(json.basicspeed) + + data.basicspeed.points = i(json.basicspeed_points) + data.thrust = t(json.thrust) + data.swing = t(json.swing) + data.currentmove = t(json.move) + data.frightcheck = i(json.frightcheck) + + data.hearing = i(json.hearing) + data.tastesmell = i(json.tastesmell) + data.touch = i(json.touch) + data.vision = i(json.vision) + + return { + 'system.attributes': att, + 'system.HP': data.HP, + 'system.FP': data.FP, + 'system.basiclift': data.basiclift, + 'system.basicmove': data.basicmove, + 'system.basicspeed': data.basicspeed, + 'system.thrust': data.thrust, + 'system.swing': data.swing, + 'system.currentmove': data.currentmove, + 'system.frightcheck': data.frightcheck, + 'system.hearing': data.hearing, + 'system.tastesmell': data.tastesmell, + 'system.touch': data.touch, + 'system.vision': data.vision, + 'system.liftingmoving': lm, + } + } + + /** + * @param {{ race: Record; height: Record; weight: Record; age: Record; title: Record; player: Record; createdon: Record; modifiedon: Record; religion: Record; birthday: Record; hand: Record; sizemodifier: Record; tl: Record; appearance: Record; }} json + */ + importTraitsfromGCA(json) { + if (!json) return + let t = this.textFrom + let ts = {} + ts.race = t(json.race) + ts.height = t(json.height) + ts.weight = t(json.weight) + ts.age = t(json.age) + ts.title = t(json.title) + ts.player = t(json.player) + ts.createdon = t(json.createdon) + ts.modifiedon = t(json.modifiedon) + ts.religion = t(json.religion) + ts.birthday = t(json.birthday) + ts.hand = t(json.hand) + ts.sizemod = t(json.sizemodifier) + ts.techlevel = t(json.tl) + // @GENDER, Eyes: @EYES, Hair: @HAIR, Skin: @SKIN + let a = t(json.appearance) + ts.appearance = a + try { + let x = a.indexOf(', Eyes: ') + if (x >= 0) { + ts.gender = a.substring(0, x) + let y = a.indexOf(', Hair: ') + ts.eyes = a.substring(x + 8, y) + x = a.indexOf(', Skin: ') + ts.hair = a.substring(y + 8, x) + ts.skin = a.substr(x + 8) + } + } catch { + console.log('Unable to parse appearance traits for ') + console.log(this) + } + return { + 'system.-=traits': null, + 'system.traits': ts, + } + } + + /** + * @param {{ [key: string]: any }} adsjson + * @param {{ [key: string]: any }} disadsjson + */ + importAdsFromGCA(adsjson, disadsjson) { + /** @type {Advantage[]} */ + let list = [] + this.importBaseAdvantagesFromGCA(list, adsjson) + this.importBaseAdvantagesFromGCA(list, disadsjson) + return { + 'system.-=ads': null, + 'system.ads': this.foldList(list), + } + } + + /** + * @param {Advantage[]} datalist + * @param {{ [key: string]: any }} json + */ + importBaseAdvantagesFromGCA(datalist, json) { + if (!json) return + let t = this.textFrom /// shortcut to make code smaller + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + let a = new Advantage() + a.name = t(j.name) + a.points = this.intFrom(j.points) + a.setNotes(t(j.text)) + a.pageRef(t(j.pageref) || a.pageref) + a.uuid = t(j.uuid) + a.parentuuid = t(j.parentuuid) + let old = this._findElementIn('ads', a.uuid) + this._migrateOtfsAndNotes(old, a, t(j.vtt_notes)) + datalist.push(a) + } + } + } + + /** + * @param {{ [key: string]: any }} json + */ + importSkillsFromGCA(json) { + if (!json) return + let temp = [] + let t = this.textFrom /// shortcut to make code smaller + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + let sk = new Skill() + sk.name = t(j.name) + sk.type = t(j.type) + sk.import = t(j.level) + if (sk.level == 0) sk.level = '' + sk.points = this.intFrom(j.points) + sk.relativelevel = t(j.relativelevel) + sk.setNotes(t(j.text)) + if (!!j.pageref) sk.pageRef(t(j.pageref)) + sk.uuid = t(j.uuid) + sk.parentuuid = t(j.parentuuid) + let old = this._findElementIn('skills', sk.uuid) + this._migrateOtfsAndNotes(old, sk, t(j.vtt_notes)) + + temp.push(sk) + } + } + return { + 'system.-=skills': null, + 'system.skills': this.foldList(temp), + } + } + + // create/update the spells. + // NOTE: For the update to work correctly, no two spells can have the same name. + // When reading data, use "this.actor.system.spells", however, when updating, use "system.spells". + /** + * @param {{ [key: string]: any }} json + */ + importSpellsFromGCA(json) { + if (!json) return + let temp = [] + let t = this.textFrom /// shortcut to make code smaller + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + let sp = new Spell() + sp.name = t(j.name) + sp.class = t(j.class) + sp.college = t(j.college) + let cm = t(j.costmaintain) + let i = cm.indexOf('/') + if (i >= 0) { + sp.cost = cm.substring(0, i) + sp.maintain = cm.substr(i + 1) + } else { + sp.cost = cm + } + sp.setNotes(t(j.text)) + sp.pageRef(t(j.pageref)) + sp.duration = t(j.duration) + sp.points = t(j.points) + sp.casttime = t(j.time) + sp.import = t(j.level) + sp.uuid = t(j.uuid) + sp.parentuuid = t(j.parentuuid) + let old = this._findElementIn('spells', sp.uuid) + this._migrateOtfsAndNotes(old, sp, t(j.vtt_notes)) + temp.push(sp) + } + } + return { + 'system.-=spells': null, + 'system.spells': this.foldList(temp), + } + } + + /** + * @param {{ [key: string]: any }} json + */ + importCombatMeleeFromGCA(json) { + if (!json) return + let t = this.textFrom + let melee = {} + let index = 0 + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + for (let k2 in j.meleemodelist) { + if (k2.startsWith('id-')) { + let j2 = j.meleemodelist[k2] + let m = new Melee() + m.name = t(j.name) + m.st = t(j.st) + m.weight = t(j.weight) + m.techlevel = t(j.tl) + m.cost = t(j.cost) + try { + m.setNotes(t(j.text)) + } catch { + console.log(m) + console.log(t(j.text)) + } + m.mode = t(j2.name) + m.import = t(j2.level) + m.damage = t(j2.damage) + m.reach = t(j2.reach) + m.parry = t(j2.parry) + m.block = t(j2.block) + let old = this._findElementIn('melee', false, m.name, m.mode) + this._migrateOtfsAndNotes(old, m, t(j2.vtt_notes)) + + GURPS.put(melee, m, index++) + } + } + } + } + return { + 'system.-=melee': null, + 'system.melee': melee, + } + } + + /** + * @param {{ [key: string]: any }} json + */ + importCombatRangedFromGCA(json) { + if (!json) return + let t = this.textFrom + let ranged = {} + let index = 0 + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + for (let k2 in j.rangedmodelist) { + if (k2.startsWith('id-')) { + let j2 = j.rangedmodelist[k2] + let r = new Ranged() + r.name = t(j.name) + r.st = t(j.st) + r.bulk = t(j.bulk) + r.legalityclass = t(j.lc) + r.ammo = t(j.ammo) + try { + r.setNotes(t(j.text)) + } catch { + console.log(r) + console.log(t(j.text)) + } + r.mode = t(j2.name) + r.import = t(j2.level) + r.damage = t(j2.damage) + r.acc = t(j2.acc) + let m = r.acc.trim().match(/(\d+)([+-]\d+)/) + if (m) { + r.acc = m[1] + r.notes += ' [' + m[2] + ' ' + i18n('GURPS.acc') + ']' + } + r.rof = t(j2.rof) + r.shots = t(j2.shots) + r.rcl = t(j2.rcl) + let rng = t(j2.range) + r.range = rng + let old = this._findElementIn('ranged', false, r.name, r.mode) + this._migrateOtfsAndNotes(old, r, t(j2.vtt_notes)) + + GURPS.put(ranged, r, index++) + } + } + } + } + return { + 'system.-=ranged': null, + 'system.ranged': ranged, + } + } + + /** + * @param {{ [key: string]: any }} descjson + * @param {{ [key: string]: any }} json + */ + importNotesFromGCA(descjson, json) { + if (!json) return + let t = this.textFrom + let temp = [] + if (!!descjson) { + // support for GCA description + + let n = new Note() + n.notes = t(descjson).replace(/\\r/g, '\n') + n.imported = true + temp.push(n) + } + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + let n = /** @type {Note & { imported: boolean, uuid: string, parentuuid: string }} */ (new Note()) + //n.setNotes(t(j.text)); + n.notes = t(j.name) + let txt = t(j.text) + if (!!txt) n.notes = n.notes + '\n' + txt.replace(/\\r/g, '\n') + n.uuid = t(j.uuid) + n.parentuuid = t(j.parentuuid) + n.pageref = t(j.pageref) + let old = this._findElementIn('notes', n.uuid) + this._migrateOtfsAndNotes(old, n) + temp.push(n) + } + } + // Save the old User Entered Notes. + recurselist(this.actor.system.notes, t => { + if (!!t.save) temp.push(t) + }) + return { + 'system.-=notes': null, + 'system.notes': this.foldList(temp), + } + } + + /** + * @param {{ [key: string]: any }} json + */ + importEquipmentFromGCA(json) { + if (!json) return + let t = this.textFrom + let i = this.intFrom + + /** + * @type {Equipment[]} + */ + let temp = [] + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + let eqt = new Equipment() + eqt.name = t(j.name) + eqt.count = t(j.count) + eqt.cost = t(j.cost) + eqt.location = t(j.location) + let cstatus = i(j.carried) + eqt.carried = cstatus >= 1 + eqt.equipped = cstatus == 2 + eqt.techlevel = t(j.tl) + eqt.legalityclass = t(j.lc) + eqt.categories = t(j.type) + eqt.uses = t(j.uses) + eqt.maxuses = t(j.maxuses) + eqt.uuid = t(j.uuid) + eqt.parentuuid = t(j.parentuuid) + eqt.setNotes(t(j.notes)) + eqt.weight = t(j.weightsum) // GCA sends calculated weight in 'weightsum' + eqt.pageRef(t(j.pageref)) + let old = this._findElementIn('equipment.carried', eqt.uuid) + if (!old) old = this._findElementIn('equipment.other', eqt.uuid) + this._migrateOtfsAndNotes(old, eqt) + if (!!old) { + eqt.carried = old.carried + eqt.equipped = old.equipped + eqt.parentuuid = old.parentuuid + if (old.ignoreImportQty) { + eqt.count = old.count + eqt.uses = old.uses + eqt.maxuses = old.maxuses + eqt.ignoreImportQty = true + } + } + temp.push(eqt) + } + } + + // Save the old User Entered Notes. + recurselist(this.actor.system.equipment?.carried, t => { + t.carried = true + if (!!t.save) temp.push(t) + }) // Ensure carried eqt stays in carried + recurselist(this.actor.system.equipment?.other, t => { + t.carried = false + if (!!t.save) temp.push(t) + }) + + temp.forEach(eqt => { + // Remove all entries from inside items because if they still exist, they will be added back in + eqt.contains = {} + eqt.collapsed = {} + }) + + // Put everything in it container (if found), otherwise at the top level + temp.forEach(eqt => { + if (!!eqt.parentuuid) { + let parent = null + parent = temp.find(e => e.uuid === eqt.parentuuid) + if (!!parent) GURPS.put(parent.contains, eqt) + else eqt.parentuuid = '' // Can't find a parent, so put it in the top list + } + }) + + let equipment = { + carried: {}, + other: {}, + } + let cindex = 0 + let oindex = 0 + + temp.forEach(eqt => { + Equipment.calc(eqt) + if (!eqt.parentuuid) { + if (eqt.carried) GURPS.put(equipment.carried, eqt, cindex++) + else GURPS.put(equipment.other, eqt, oindex++) + } + }) + return { + 'system.-=equipment': null, + 'system.equipment': equipment, + } + } + + /** + * @param {{ [x: string]: any; bodyplan: Record; }} json + */ + async importProtectionFromGCA(json) { + if (!json) return + let t = this.textFrom + let data = this.actor.system + if (!!data.additionalresources.ignoreinputbodyplan) return + + /** @type {HitLocations.HitLocation[]} */ + let locations = [] + for (let key in json) { + if (key.startsWith('id-')) { + // Allows us to skip over junk elements created by xml->json code, and only select the skills. + let j = json[key] + let hl = new HitLocations.HitLocation(t(j.location)) + let i = t(j.dr) + if (i.match(/^\d+ *(\+ *\d+ *)?$/)) i = eval(t(j.dr)) // supports "0 + 8" + hl.import = !i ? 0 : i + hl.penalty = t(j.db) + hl.setEquipment(t(j.text)) + + // Some hit location tables have two entries for the same location. The code requires + // each location to be unique. Append an asterisk to the location name in that case. Hexapods and ichthyoid + while (locations.filter(it => it.where == hl.where).length > 0) { + hl.where = hl.where + '*' + } + locations.push(hl) + } + } + + // Do the results contain vitals? If not, add it. + let vitals = locations.filter(value => value.where === HitLocations.HitLocation.VITALS) + if (vitals.length === 0) { + let hl = new HitLocations.HitLocation(HitLocations.HitLocation.VITALS) + hl.penalty = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].penalty + hl.roll = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].roll + hl.import = '0' + locations.push(hl) + } + + // Hit Locations MUST come from an existing bodyplan hit location table, or else ADD (and + // potentially other features) will not work. Sometime in the future, we will look at + // user-entered hit locations. + let bodyplan = t(json.bodyplan)?.toLowerCase() // Was a body plan actually in the import? + if (bodyplan === 'snakemen') bodyplan = 'snakeman' + let table = HitLocations.hitlocationDictionary[bodyplan] // If so, try to use it. + + /** @type {HitLocations.HitLocation[]} */ + let locs = [] + locations.forEach(e => { + if (!!table && !!table[e.where]) { + // if e.where already exists in table, don't map + locs.push(e) + } else { + // map to new name(s) ... sometimes we map 'Legs' to ['Right Leg', 'Left Leg'], for example. + e.locations(false).forEach(l => locs.push(l)) // Map to new names + } + }) + locations = locs + + if (!table) { + locs = [] + locations.forEach(e => { + e.locations(true).forEach(l => locs.push(l)) // Map to new names, but include original to help match against tables + }) + bodyplan = this._getBodyPlan(locs) + table = HitLocations.hitlocationDictionary[bodyplan] + } + // update location's roll and penalty based on the bodyplan + + if (!!table) { + Object.values(locations).forEach(it => { + let [lbl, entry] = HitLocations.HitLocation.findTableEntry(table, it.where) + if (!!entry) { + it.where = lbl // It might be renamed (ex: Skull -> Brain) + if (!it.penalty) it.penalty = entry.penalty + if (!it.roll || it.roll.length === 0 || it.roll === HitLocations.HitLocation.DEFAULT) it.roll = entry.roll + } + }) + } + + // write the hit locations out in bodyplan hit location table order. If there are + // other entries, append them at the end. + /** @type {HitLocations.HitLocation[]} */ + let temp = [] + Object.keys(table).forEach(key => { + let results = Object.values(locations).filter(loc => loc.where === key) + if (results.length > 0) { + if (results.length > 1) { + // If multiple locs have same where, concat the DRs. Leg 7 & Leg 8 both map to "Leg 7-8" + let d = '' + + /** @type {string | null} */ + let last = null + results.forEach(r => { + if (r.import != last) { + d += '|' + r.import + last = r.import + } + }) + + if (!!d) d = d.substring(1) + results[0].import = d + } + temp.push(results[0]) + locations = locations.filter(it => it.where !== key) + } else { + // Didn't find loc that should be in the table. Make a default entry + temp.push(new HitLocations.HitLocation(key, '0', table[key].penalty, table[key].roll)) + } + }) + locations.forEach(it => temp.push(it)) + + let prot = {} + let index = 0 + temp.forEach(it => GURPS.put(prot, it, index++)) + + let saveprot = true + if (!!data.lastImport && !!data.additionalresources.bodyplan && bodyplan != data.additionalresources.bodyplan) { + let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_BODYPLAN) + if (option == 1) { + saveprot = false + } + if (option == 2) { + saveprot = await new Promise((resolve, _reject) => { + let d = new Dialog({ + title: 'Hit Location Body Plan', + content: + `Do you want to

Save the current Body Plan (${game.i18n.localize( + 'GURPS.BODYPLAN' + data.additionalresources.bodyplan + )}) or ` + + `

Overwrite it with the Body Plan from the import: (${game.i18n.localize( + 'GURPS.BODYPLAN' + bodyplan + )})?

 `, + buttons: { + save: { + icon: '', + label: 'Save', + callback: () => resolve(false), + }, + overwrite: { + icon: '', + label: 'Overwrite', + callback: () => resolve(true), + }, + }, + default: 'save', + close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. + }) + d.render(true) + }) + } + } + if (saveprot) + return { + 'system.-=hitlocations': null, + 'system.hitlocations': prot, + 'system.additionalresources.bodyplan': bodyplan, + } + else return {} + } + + importLangFromGCA(json) { + if (!json) return + let langs = {} + let index = 0 + let t = this.textFrom + for (let key in json) { + if (key.startsWith('id-')) { + let j = json[key] + let n = t(j.name) + let s = t(j.spoken) + let w = t(j.written) + let p = t(j.points) + let l = new Language(n, s, w, p) + GURPS.put(langs, l, index++) + } + } + return { + 'system.-=languages': null, + 'system.languages': langs, + } + } + + /** + * @param {{ [key: string]: any }} json + */ + importReactionsFromGCA(json, vernum) { + if (!json) return + let text = this.textFrom(json) + let a = vernum <= 9 ? text.split(',') : text.split('|') + let rs = {} + let index = 0 + a.forEach((/** @type {string} */ m) => { + if (!!m) { + let t = m.trim() + let i = t.indexOf(' ') + let mod = t.substring(0, i) + let sit = t.substring(i + 1) + let r = new Reaction(mod, sit) + GURPS.put(rs, r, index++) + } + }) + return { + 'system.-=reactions': null, + 'system.reactions': rs, + } + } + + /** + * @param {{ [x: string]: Record; }} json + */ + importEncumbranceFromGCA(json) { + if (!json) return + let t = this.textFrom + let es = {} + let index = 0 + let cm = 0 + let cd = 0 + for (let i = 0; i < 5; i++) { + let e = new Encumbrance() + e.level = i + let k = 'enc_' + i + let c = t(json[k]) + e.current = c === '1' + k = 'enc' + i + e.key = k + let k2 = k + '_weight' + e.weight = t(json[k2]) + k2 = k + '_move' + e.move = this.intFrom(json[k2]) + k2 = k + '_dodge' + e.dodge = this.intFrom(json[k2]) + if (e.current) { + cm = e.move + cd = e.dodge + } + GURPS.put(es, e, index++) + } + return { + 'system.currentmove': cm, + 'system.currentdodge': cd, + 'system.-=encumbrance': null, + 'system.encumbrance': es, + } + } + + /** + * @param {{ attributes: Record; ads: Record; disads: Record; quirks: Record; skills: Record; spells: Record; unspentpoints: Record; totalpoints: Record; race: Record; }} json + */ + importPointTotalsFromGCA(json) { + if (!json) return + + let i = this.intFrom + return { + 'system.totalpoints.attributes': i(json.attributes), + 'system.totalpoints.ads': i(json.ads), + 'system.totalpoints.disads': i(json.disads), + 'system.totalpoints.quirks': i(json.quirks), + 'system.totalpoints.skills': i(json.skills), + 'system.totalpoints.spells': i(json.spells), + 'system.totalpoints.unspent': i(json.unspentpoints), + 'system.totalpoints.total': i(json.totalpoints), + 'system.totalpoints.race': i(json.race), + } + } + + /** + * + * @param {{ [key: string]: any}} json + */ + async importAttributesFromGCS(atts, eqp, calc) { + if (!atts) return + let data = this.actor.system + let att = data.attributes + if (!att.QN) { + // upgrade older actors to include Q + att.QN = {} + data.QP = {} + } + + att.ST.import = atts.find(e => e.attr_id === 'st')?.calc?.value || 0 + att.ST.points = atts.find(e => e.attr_id === 'st')?.calc?.points || 0 + att.DX.import = atts.find(e => e.attr_id === 'dx')?.calc?.value || 0 + att.DX.points = atts.find(e => e.attr_id === 'dx')?.calc?.points || 0 + att.IQ.import = atts.find(e => e.attr_id === 'iq')?.calc?.value || 0 + att.IQ.points = atts.find(e => e.attr_id === 'iq')?.calc?.points || 0 + att.HT.import = atts.find(e => e.attr_id === 'ht')?.calc?.value || 0 + att.HT.points = atts.find(e => e.attr_id === 'ht')?.calc?.points || 0 + att.WILL.import = atts.find(e => e.attr_id === 'will')?.calc?.value || 0 + att.WILL.points = atts.find(e => e.attr_id === 'will')?.calc?.points || 0 + att.PER.import = atts.find(e => e.attr_id === 'per')?.calc?.value || 0 + att.PER.points = atts.find(e => e.attr_id === 'per')?.calc?.points || 0 + att.QN.import = atts.find(e => e.attr_id === 'qn')?.calc?.value || 0 + att.QN.points = atts.find(e => e.attr_id === 'qn')?.calc?.points || 0 + + data.HP.max = atts.find(e => e.attr_id === 'hp')?.calc?.value || 0 + data.HP.points = atts.find(e => e.attr_id === 'hp')?.calc?.points || 0 + data.FP.max = atts.find(e => e.attr_id === 'fp')?.calc?.value || 0 + data.FP.points = atts.find(e => e.attr_id === 'fp')?.calc?.points || 0 + data.QP.max = atts.find(e => e.attr_id === 'qp')?.calc?.value || 0 + data.QP.points = atts.find(e => e.attr_id === 'qp')?.calc?.points || 0 + let hp = atts.find(e => e.attr_id === 'hp')?.calc?.current || 0 + let fp = atts.find(e => e.attr_id === 'fp')?.calc?.current || 0 + let qp = atts.find(e => e.attr_id === 'qp')?.calc?.current || 0 + + let saveCurrent = false + + if (!!data.lastImport && (data.HP.value != hp || data.FP.value != fp)) { + let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_HP_FP) + if (option == 0) { + saveCurrent = true + } + if (option == 2) { + saveCurrent = await new Promise((resolve, _reject) => { + let d = new Dialog({ + title: 'Current HP & FP', + content: `Do you want to

Save the current HP (${data.HP.value}) & FP (${data.FP.value}) values or

Overwrite it with the import data, HP (${hp}) & FP (${fp})?

 `, + buttons: { + save: { + icon: '', + label: 'Save', + callback: () => resolve(true), + }, + overwrite: { + icon: '', + label: 'Overwrite', + callback: () => resolve(false), + }, + }, + default: 'save', + close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. + }) + d.render(true) + }) + } + } + if (!saveCurrent) { + data.HP.value = hp + data.FP.value = fp + } + data.QP.value = qp + + let bl_value = parseFloat(calc?.basic_lift.match(/[\d\.]+/g)) + let bl_unit = calc?.basic_lift.replace(bl_value + ' ', '') + + let lm = {} + lm.basiclift = (bl_value * 1).toString() + ' ' + bl_unit + lm.carryonback = (bl_value * 15).toString() + ' ' + bl_unit + lm.onehandedlift = (bl_value * 2).toString() + ' ' + bl_unit + lm.runningshove = (bl_value * 24).toString() + ' ' + bl_unit + lm.shiftslightly = (bl_value * 50).toString() + ' ' + bl_unit + lm.shove = (bl_value * 12).toString() + ' ' + bl_unit + lm.twohandedlift = (bl_value * 8).toString() + ' ' + bl_unit + + let bm = atts.find(e => e.attr_id === 'basic_move')?.calc?.value || 0 + data.basicmove.value = bm.toString() + data.basicmove.points = atts.find(e => e.attr_id === 'basic_move')?.calc?.points || 0 + let bs = atts.find(e => e.attr_id === 'basic_speed')?.calc?.value || 0 + data.basicspeed.value = bs.toString() + data.basicspeed.points = atts.find(e => e.attr_id === 'basic_speed')?.calc?.points || 0 + + data.thrust = calc?.thrust + data.swing = calc?.swing + data.currentmove = data.basicmove.value + data.frightcheck = atts.find(e => e.attr_id === 'fright_check')?.calc?.value || 0 + + data.hearing = atts.find(e => e.attr_id === 'hearing')?.calc?.value || 0 + data.tastesmell = atts.find(e => e.attr_id === 'taste_smell')?.calc?.value || 0 + data.touch = atts.find(e => e.attr_id === 'touch')?.calc?.value || 0 + data.vision = atts.find(e => e.attr_id === 'vision')?.calc?.value || 0 + + let cm = 0 + let cd = 0 + let es = {} + let ew = [1, 2, 3, 6, 10] + let index = 0 + let total_carried = this.calcTotalCarried(eqp) + for (let i = 0; i <= 4; i++) { + let e = new Encumbrance() + e.level = i + e.current = false + e.key = 'enc' + i + let weight_value = bl_value * ew[i] + // e.current = total_carried <= weight_value && (i == 4 || total_carried < bl_value*ew[i+1]); + e.current = + (total_carried < weight_value || i == 4 || bl_value == 0) && (i == 0 || total_carried > bl_value * ew[i - 1]) + e.weight = weight_value.toString() + ' ' + bl_unit + e.move = calc?.move[i].toString() + e.dodge = calc?.dodge[i] + if (e.current) { + cm = e.move + cd = e.dodge + } + GURPS.put(es, e, index++) + } + + return { + 'system.attributes': att, + 'system.HP': data.HP, + 'system.FP': data.FP, + 'system.basiclift': data.basiclift, + 'system.basicmove': data.basicmove, + 'system.basicspeed': data.basicspeed, + 'system.thrust': data.thrust, + 'system.swing': data.swing, + 'system.currentmove': data.currentmove, + 'system.frightcheck': data.frightcheck, + 'system.hearing': data.hearing, + 'system.tastesmell': data.tastesmell, + 'system.touch': data.touch, + 'system.vision': data.vision, + 'system.liftingmoving': lm, + 'system.currentmove': cm, + 'system.currentdodge': cd, + 'system.encumbrance': es, + 'system.QP': data.QP, + } + } + + async importTraitsFromGCS(p, cd, md) { + if (!p) return + let ts = {} + ts.race = '' + ts.height = p.height || '' + ts.weight = p.weight || '' + ts.age = p.age || '' + ts.title = p.title || '' + ts.player = p.player_name || '' + ts.createdon = + new Date(cd).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' }).replace(' at', ',') || '' + ts.modifiedon = + new Date(md).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' }).replace(' at', ',') || '' + // ts.modifiedon = md || '' + ts.religion = p.religion || '' + ts.birthday = p.birthday || '' + ts.hand = p.handedness || '' + ts.techlevel = p.tech_level || '' + ts.gender = p.gender || '' + ts.eyes = p.eyes || '' + ts.hair = p.hair || '' + ts.skin = p.skin || '' + ts.sizeod = p.SM || '+0' + + const r = { + 'system.-=traits': null, + 'system.traits': ts, + } + + if (p.portrait) { + if (game.user.hasPermission('FILES_UPLOAD')) { + r.img = `data:image/png;base64,${p.portrait}.png` + } else { + await ui.notifications.error( + 'You do not have "FILES_UPLOAD" permission, portrait upload has failed. Please ask your GM to import your character, or acquire the correct permissions.' + ) + } + } + + return r + } + + importAdsFromGCS(ads) { + let temp = [] + if (!!ads) + for (let i of ads) { + temp = temp.concat(this.importAd(i, '')) + } + return { + 'system.-=ads': null, + 'system.ads': this.foldList(temp), + } + } + + importAd(i, p) { + let a = new Advantage() + if (this.GCSVersion === 5) { + i.type = i.id.startsWith('t') ? 'trait' : 'trait_container' + } + a.name = i.name + (i.levels ? ' ' + i.levels.toString() : '') || 'Trait' + a.points = i.calc?.points + a.notes = i.calc?.resolved_notes ?? i.notes ?? '' + a.userdesc = i.userdesc + + if (i.cr != null) { + a.notes = '[' + game.i18n.localize('GURPS.CR' + i.cr.toString()) + ': ' + a.name + ']' + } + if (i.modifiers?.length) { + for (let j of i.modifiers) + if (!j.disabled) a.notes += `${!!a.notes ? '; ' : ''}${j.name}${!!j.notes ? ' (' + j.notes + ')' : ''}` + } + // Not certain if this is needed, or is it a type-o (note vs. notes) + if (!!a.note) a.notes += (!!a.notes ? '\n' : '') + a.note + + if (!!a.userdesc) a.notes += (!!a.notes ? '\n' : '') + a.userdesc + a.pageRef(i.reference) + a.uuid = i.id + a.parentuuid = p + + let old = this._findElementIn('ads', a.uuid) + this._migrateOtfsAndNotes(old, a, i.vtt_notes) + + let ch = [] + if (i.children?.length) { + for (let j of i.children) ch = ch.concat(this.importAd(j, i.id)) + } + return [a].concat(ch) + } + + importSkillsFromGCS(sks) { + if (!sks) return + let temp = [] + for (let i of sks) { + temp = temp.concat(this.importSk(i, '')) + } + return { + 'system.-=skills': null, + 'system.skills': this.foldList(temp), + } + } + + importSk(i, p) { + if (this.GCSVersion === 5) { + i.type = i.id.startsWith('q') ? 'technique' : i.id.startsWith('s') ? 'skill' : 'skill_container' + } + let name = + i.name + (!!i.tech_level ? `/TL${i.tech_level}` : '') + (!!i.specialization ? ` (${i.specialization})` : '') || + 'Skill' + if (i.type == 'technique' && !!i.default) { + let addition = '' + addition = ' (' + i.default.name + if (!!i.default.specialization) { + addition += ' (' + i.default.specialization + ')' + } + name += addition + ')' + } + let s = new Skill(name, '') + s.pageRef(i.reference || '') + s.uuid = i.id + s.parentuuid = p + if (['skill', 'technique'].includes(i.type)) { + s.type = i.type.toUpperCase() + s.import = !!i.calc ? i.calc.level : '' + if (s.level == 0) s.level = '' + s.points = i.points + s.relativelevel = i.calc?.rsl + s.notes = i.calc?.resolved_notes ?? i.notes ?? '' + } else { + // Usually containers + s.level = '' + } + let old = this._findElementIn('skills', s.uuid) + this._migrateOtfsAndNotes(old, s, i.vtt_notes) + + let ch = [] + if (i.children?.length) { + for (let j of i.children) ch = ch.concat(this.importSk(j, i.id)) + } + return [s].concat(ch) + } + + importSpellsFromGCS(sps) { + if (!sps) return + let temp = [] + for (let i of sps) { + temp = temp.concat(this.importSp(i, '')) + } + return { + 'system.-=spells': null, + 'system.spells': this.foldList(temp), + } + } + + importSp(i, p) { + let s = new Spell() + if (this.GCSVersion === 5) { + i.type = i.id.startsWith('r') ? 'ritual_magic_spell' : i.id.startsWith('p') ? 'spell' : 'spell_container' + } + s.name = i.name || 'Spell' + s.uuid = i.id + s.parentuuid = p + s.pageRef(i.reference || '') + if (['spell', 'ritual_magic_spell'].includes(i.type)) { + s.class = i.spell_class || '' + s.college = i.college || '' + s.cost = i.casting_cost || '' + s.maintain = i.maintenance_cost || '' + s.difficulty = i.difficulty.toUpperCase() + s.relativelevel = i.calc?.rsl + s.notes = i.calc?.resolved_notes ?? i.notes ?? '' + s.duration = i.duration || '' + s.points = i.points || '' + s.casttime = i.casting_time || '' + s.import = i.calc?.level || 0 + } + + let old = this._findElementIn('spells', s.uuid) + this._migrateOtfsAndNotes(old, s, i.vtt_notes) + + let ch = [] + if (i.children?.length) { + for (let j of i.children) ch = ch.concat(this.importSp(j, i.id)) + } + return [s].concat(ch) + } + + importEquipmentFromGCS(eq, oeq) { + if (!eq && !oeq) return + let temp = [] + if (!!eq) + for (let i of eq) { + temp = temp.concat(this.importEq(i, '', true)) + } + if (!!oeq) + for (let i of oeq) { + temp = temp.concat(this.importEq(i, '', false)) + } + + recurselist(this.actor.system.equipment?.carried, t => { + t.carried = true + if (!!t.save) temp.push(t) + }) + recurselist(this.actor.system.equipment?.other, t => { + t.carried = false + if (!!t.save) temp.push(t) + }) + + temp.forEach(e => { + e.contains = {} + e.collapsed = {} + }) + + temp.forEach(e => { + if (!!e.parentuuid) { + let parent = null + parent = temp.find(f => f.uuid === e.parentuuid) + if (!!parent) GURPS.put(parent.contains, e) + else e.parentuuid = '' + } + }) + + let equipment = { + carried: {}, + other: {}, + } + let cindex = 0 + let oindex = 0 + + temp.forEach(eqt => { + Equipment.calc(eqt) + if (!eqt.parentuuid) { + if (eqt.carried) GURPS.put(equipment.carried, eqt, cindex++) + else GURPS.put(equipment.other, eqt, oindex++) + } + }) + return { + 'system.-=equipment': null, + 'system.equipment': equipment, + } + } + + importEq(i, p, carried) { + let e = new Equipment() + if (this.GCSVersion === 5) { + i.type = i.id.startsWith('e') ? 'equipment' : 'equipment_container' + } + e.name = i.description || 'Equipment' + e.count = i.type == 'equipment_container' ? '1' : i.quantity || '0' + e.cost = + (parseFloat(i.calc?.extended_value) / (i.type == 'equipment_container' ? 1 : i.quantity || 1)).toString() || '' + e.carried = carried + e.equipped = i.equipped + e.techlevel = i.tech_level || '' + e.legalityclass = i.legality_class || '4' + e.categories = i.categories?.join(', ') || '' + e.uses = i.uses || 0 + e.maxuses = i.max_uses || 0 + e.uuid = i.id + e.parentuuid = p + e.notes = '' + e.notes = i.calc?.resolved_notes ?? i.notes ?? '' + if (i.modifiers?.length) { + for (let j of i.modifiers) + if (!j.disabled) e.notes += `${!!e.notes ? '; ' : ''}${j.name}${!!j.notes ? ' (' + j.notes + ')' : ''}` + } + if (!!e.note) e.notes += (!!e.notes ? '\n' : '') + e.note + e.weight = + (parseFloat(i.calc?.extended_weight) / (i.type == 'equipment_container' ? 1 : i.quantity || 1)).toString() || '0' + e.pageRef(i.reference || '') + let old = this._findElementIn('equipment.carried', e.uuid) + if (!old) old = this._findElementIn('equipment.other', e.uuid) + this._migrateOtfsAndNotes(old, e, i.vtt_notes) + if (!!old) { + e.carried = old.carried + e.equipped = old.equipped + e.parentuuid = old.parentuuid + if (old.ignoreImportQty) { + e.count = old.count + e.uses = old.uses + e.maxuses = old.maxuses + e.ignoreImportQty = true + } + } + let ch = [] + if (i.children?.length) { + for (let j of i.children) ch = ch.concat(this.importEq(j, i.id, carried)) + for (let j of ch) { + e.cost -= j.cost * j.count + e.weight -= j.weight * j.count + } + } + return [e].concat(ch) + } + + importNotesFromGCS(notes) { + if (!notes) return + let temp = [] + for (let i of notes) { + temp = temp.concat(this.importNote(i, '')) + } + recurselist(this.actor.system.notes, t => { + if (!!t.save) temp.push(t) + }) + return { + 'system.-=notes': null, + 'system.notes': this.foldList(temp), + } + } + + importNote(i, p) { + let n = new Note() + if (this.GCSVersion === 5) { + i.type = i.id.startsWith('n') ? 'note' : 'note_container' + } + n.notes = i.calc?.resolved_text ?? i.text ?? '' + n.uuid = i.id + n.parentuuid = p + n.pageRef(i.reference || '') + let old = this._findElementIn('notes', n.uuid) + this._migrateOtfsAndNotes(old, n) + let ch = [] + if (i.children?.length) { + for (let j of i.children) ch = ch.concat(this.importNote(j, i.id)) + } + return [n].concat(ch) + } + + importSizeFromGCS(commit, profile, ads, skills, equipment) { + let ts = commit['system.traits'] + let final = profile.SM || 0 + let temp = [].concat(ads, skills, equipment) + let all = [] + for (let i of temp) { + all = all.concat(this.recursiveGet(i)) + } + for (let i of all) { + if (i.features?.length) + for (let f of i.features) { + if (f.type == 'attribute_bonus' && f.attribute == 'sm') + final += f.amount * (!!i.levels ? parseFloat(i.levels) : 1) + } + } + ts.sizemod = this.signedNum(final) + return { + 'system.-=traits': null, + 'system.traits': ts, + } + } + + async importProtectionFromGCS(hls) { + if (!hls) return + let data = this.actor.system + if (!!data.additionalresources.ignoreinputbodyplan) return + + /** @type {HitLocations.HitLocation[]} */ + let locations = [] + for (let i of hls.locations) { + let l = new HitLocations.HitLocation(i.table_name) + l.import = i.calc?.dr.all?.toString() || '0' + for (let [key, value] of Object.entries(i.calc?.dr)) + if (key != 'all') { + let damtype = GURPS.DamageTables.damageTypeMap[key] + if (!l.split) l.split = {} + l.split[damtype] = +l.import + value + } + l.penalty = i.hit_penalty?.toString() || '0' + while (locations.filter(it => it.where == l.where).length > 0) { + l.where = l.where + '*' + } + locations.push(l) + } + let vitals = locations.filter(value => value.where === HitLocations.HitLocation.VITALS) + if (vitals.length === 0) { + let hl = new HitLocations.HitLocation(HitLocations.HitLocation.VITALS) + hl.penalty = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].penalty + hl.roll = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].roll + hl.import = '0' + locations.push(hl) + } + // Hit Locations MUST come from an existing bodyplan hit location table, or else ADD (and + // potentially other features) will not work. Sometime in the future, we will look at + // user-entered hit locations. + let bodyplan = hls.id // Was a body plan actually in the import? + if (bodyplan === 'snakemen') bodyplan = 'snakeman' + let table = HitLocations.hitlocationDictionary[bodyplan] // If so, try to use it. + + /** @type {HitLocations.HitLocation[]} */ + let locs = [] + locations.forEach(e => { + if (!!table && !!table[e.where]) { + // if e.where already exists in table, don't map + locs.push(e) + } else { + // map to new name(s) ... sometimes we map 'Legs' to ['Right Leg', 'Left Leg'], for example. + e.locations(false).forEach(l => locs.push(l)) // Map to new names + } + }) + locations = locs + + if (!table) { + locs = [] + locations.forEach(e => { + e.locations(true).forEach(l => locs.push(l)) // Map to new names, but include original to help match against tables + }) + bodyplan = this._getBodyPlan(locs) + table = HitLocations.hitlocationDictionary[bodyplan] + } + // update location's roll and penalty based on the bodyplan + + if (!!table) { + Object.values(locations).forEach(it => { + let [lbl, entry] = HitLocations.HitLocation.findTableEntry(table, it.where) + if (!!entry) { + it.where = lbl // It might be renamed (ex: Skull -> Brain) + if (!it.penalty) it.penalty = entry.penalty + if (!it.roll || it.roll.length === 0 || it.roll === HitLocations.HitLocation.DEFAULT) it.roll = entry.roll + } + }) + } + + // write the hit locations out in bodyplan hit location table order. If there are + // other entries, append them at the end. + /** @type {HitLocations.HitLocation[]} */ + let temp = [] + Object.keys(table).forEach(key => { + let results = Object.values(locations).filter(loc => loc.where === key) + if (results.length > 0) { + if (results.length > 1) { + // If multiple locs have same where, concat the DRs. Leg 7 & Leg 8 both map to "Leg 7-8" + let d = '' + + /** @type {string | null} */ + let last = null + results.forEach(r => { + if (r.import != last) { + d += '|' + r.import + last = r.import + } + }) + + if (!!d) d = d.substring(1) + results[0].import = d + } + temp.push(results[0]) + locations = locations.filter(it => it.where !== key) + } else { + // Didn't find loc that should be in the table. Make a default entry + temp.push(new HitLocations.HitLocation(key, '0', table[key].penalty, table[key].roll)) + } + }) + locations.forEach(it => temp.push(it)) + + let prot = {} + let index = 0 + temp.forEach(it => GURPS.put(prot, it, index++)) + + let saveprot = true + if (!!data.lastImport && !!data.additionalresources.bodyplan && bodyplan != data.additionalresources.bodyplan) { + let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_BODYPLAN) + if (option == 1) { + saveprot = false + } + if (option == 2) { + saveprot = await new Promise((resolve, _reject) => { + let d = new Dialog({ + title: 'Hit Location Body Plan', + content: + `Do you want to

Save the current Body Plan (${game.i18n.localize( + 'GURPS.BODYPLAN' + data.additionalresources.bodyplan + )}) or ` + + `

Overwrite it with the Body Plan from the import: (${game.i18n.localize( + 'GURPS.BODYPLAN' + bodyplan + )})?

 `, + buttons: { + save: { + icon: '', + label: 'Save', + callback: () => resolve(false), + }, + overwrite: { + icon: '', + label: 'Overwrite', + callback: () => resolve(true), + }, + }, + default: 'save', + close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. + }) + d.render(true) + }) + } + } + if (saveprot) { + return { + 'system.-=hitlocations': null, + 'system.hitlocations': prot, + 'system.additionalresources.bodyplan': bodyplan, + } + } else return {} + } + + importPointTotalsFromGCS(total, atts, ads, skills, spells) { + if (!ads) ads = [] + if (!skills) skills = [] + if (!spells) spells = [] + let p_atts = 0 + let p_ads = 0 + let p_disads = 0 + let p_quirks = 0 + let p_skills = 0 + let p_spells = 0 + let p_unspent = total + let p_total = total + let p_race = 0 + for (let i of atts) p_atts += i.calc?.points + for (let i of ads) + [p_ads, p_disads, p_quirks, p_race] = this.adPointCount(i, p_ads, p_disads, p_quirks, p_race, true) + for (let i of skills) p_skills = this.skPointCount(i, p_skills) + for (let i of spells) p_spells = this.skPointCount(i, p_spells) + p_unspent -= p_atts + p_ads + p_disads + p_quirks + p_skills + p_spells + p_race + return { + 'system.totalpoints.attributes': p_atts, + 'system.totalpoints.ads': p_ads, + 'system.totalpoints.disads': p_disads, + 'system.totalpoints.quirks': p_quirks, + 'system.totalpoints.skills': p_skills, + 'system.totalpoints.spells': p_spells, + 'system.totalpoints.unspent': p_unspent, + 'system.totalpoints.total': p_total, + 'system.totalpoints.race': p_race, + } + } + + importReactionsFromGCS(ads, skills, equipment) { + let rs = {} + let cs = {} + let index_r = 0 + let index_c = 0 + let temp = [].concat(ads, skills, equipment) + let all = [] + for (let i of temp) { + all = all.concat(this.recursiveGet(i)) + } + let temp_r = [] + let temp_c = [] + for (let i of all) { + if (i.features?.length) + for (let f of i.features) { + if (f.type == 'reaction_bonus') { + temp_r.push({ + modifier: f.amount * (f.per_level && !!i.levels ? parseInt(i.levels) : 1), + situation: f.situation, + }) + } else if (f.type == 'conditional_modifier') { + temp_c.push({ + modifier: f.amount * (f.per_level && !!i.levels ? parseInt(i.levels) : 1), + situation: f.situation, + }) + } + } + } + let temp_r2 = [] + let temp_c2 = [] + for (let i of temp_r) { + let existing_condition = temp_r2.find(e => e.situation == i.situation) + if (!!existing_condition) existing_condition.modifier += i.modifier + else temp_r2.push(i) + } + for (let i of temp_c) { + let existing_condition = temp_c2.find(e => e.situation == i.situation) + if (!!existing_condition) existing_condition.modifier += i.modifier + else temp_c2.push(i) + } + for (let i of temp_r2) { + let r = new Reaction() + r.modifier = i.modifier.toString() + r.situation = i.situation + GURPS.put(rs, r, index_r++) + } + for (let i of temp_c2) { + let c = new Modifier() + c.modifier = i.modifier.toString() + c.situation = i.situation + GURPS.put(cs, c, index_c++) + } + return { + 'system.-=reactions': null, + 'system.reactions': rs, + 'system.-=conditionalmods': null, + 'system.conditionalmods': cs, + } + } + + importCombatFromGCS(ads, skills, spells, equipment) { + let melee = {} + let ranged = {} + let m_index = 0 + let r_index = 0 + let temp = [].concat(ads, skills, spells, equipment) + let all = [] + for (let i of temp) { + all = all.concat(this.recursiveGet(i)) + } + for (let i of all) { + if (i.weapons?.length) + for (let w of i.weapons) { + if (w.type == 'melee_weapon') { + let m = new Melee() + m.name = i.name || i.description || '' + m.st = w.strength || '' + m.weight = i.weight || '' + m.techlevel = i.tech_level || '' + m.cost = i.value || '' + m.notes = i.notes || '' + m.pageRef(i.reference || '') + m.mode = w.usage || '' + m.import = w.calc?.level?.toString() || '0' + m.damage = w.calc?.damage || '' + m.reach = w.reach || '' + m.parry = w.calc?.parry || '' + m.block = w.calc?.block || '' + let old = this._findElementIn('melee', false, m.name, m.mode) + this._migrateOtfsAndNotes(old, m, i.vtt_notes, w.usage_notes) + + GURPS.put(melee, m, m_index++) + } else if (w.type == 'ranged_weapon') { + let r = new Ranged() + r.name = i.name || i.description || '' + r.st = w.strength || '' + r.bulk = w.bulk || '' + r.legalityclass = i.legality_class || '4' + r.ammo = 0 + r.notes = i.notes || '' + r.pageRef(i.reference || '') + r.mode = w.usage || '' + r.import = w.calc?.level || '0' + r.damage = w.calc?.damage || '' + r.acc = w.accuracy || '' + let m = r.acc.trim().match(/(\d+)([+-]\d+)/) + if (m) { + r.acc = m[1] + r.notes += ' [' + m[2] + ' ' + i18n('GURPS.acc') + ']' + } + r.rof = w.rate_of_fire || '' + r.shots = w.shots || '' + r.rcl = w.recoil || '' + r.range = w.calc?.range || w.range || '' + let old = this._findElementIn('ranged', false, r.name, r.mode) + this._migrateOtfsAndNotes(old, r, i.vtt_notes, w.usage_notes) + + GURPS.put(ranged, r, r_index++) + } + } + } + return { + 'system.-=melee': null, + 'system.melee': melee, + 'system.-=ranged': null, + 'system.ranged': ranged, + } + } + + // hack to get to private text element created by xml->json method. + /** + * @param {{ [key: string]: any }} o + */ + textFrom(o) { + if (!o) return '' + let t = o['#text'] + if (!t) return '' + return t.trim() + } + + // similar hack to get text as integer. + /** + * @param {{ [key: string]: any }} o + */ + intFrom(o) { + if (!o) return 0 + let i = o['#text'] + if (!i) return 0 + return parseInt(i) + } + + /** + * @param {{[key: string] : any}} o + */ + floatFrom(o) { + if (!o) return 0 + let f = o['#text'].trim() + if (!f) return 0 + return f.includes(',') ? parseDecimalNumber(f, { thousands: '.', decimal: ',' }) : parseDecimalNumber(f) + } + + calcTotalCarried(eqp) { + let t = 0 + if (!eqp) return t + for (let i of eqp) { + let w = 0 + w += parseFloat(i.weight || '0') * (i.type == 'equipment_container' ? 1 : i.quantity || 0) + if (i.children?.length) w += this.calcTotalCarried(i.children) + t += w + } + return t + } + + recursiveGet(i) { + if (!i) return [] + let ch = [] + if (i.children?.length) for (let j of i.children) ch = ch.concat(this.recursiveGet(j)) + if (i.modifiers?.length) for (let j of i.modifiers) ch = ch.concat(this.recursiveGet(j)) + if (!!i.disabled || (i.equipped != null && i.equipped == false)) return [] + return [i].concat(ch) + } + + signedNum(x) { + if (x >= 0) return `+${x}` + else return x.toString() + } + + /** + * @param {string} list + * @param {string|boolean} uuid + */ + _findElementIn(list, uuid, name = '', mode = '') { + var foundkey + let l = foundry.utils.getProperty(this.actor, 'system.' + list) + recurselist(l, (e, k, _d) => { + if ((uuid && e.uuid == uuid) || (!!e.name && e.name.startsWith(name) && e.mode == mode)) foundkey = k + }) + return foundkey == null ? foundkey : foundry.utils.getProperty(this.actor, 'system.' + list + '.' + foundkey) + } + + adPointCount(i, ads, disads, quirks, race, toplevel = false) { + if (this.GCSVersion === 5) { + i.type = i.id.startsWith('t') ? 'trait' : 'trait_container' + } + if (i.type == 'trait_container' && i.container_type == 'race') race += i.calc?.points + else if (i.type == 'trait_container' && i.container_type == 'alternative_abilities') ads += i.calc?.points + else if (i.type == 'trait_container' && !!i.children?.length) { + var [a, d] = [0, 0] + for (let j of i.children) [a, d, quirks, race] = this.adPointCount(j, a, d, quirks, race) + if (toplevel) { + if (a > 0) ads += a + else disads += a + disads += d + } else ads += a + d + } else if (i.calc?.points == -1) quirks += i.calc?.points + else if (i.calc?.points > 0) ads += i.calc?.points + else disads += i.calc?.points + return [ads, disads, quirks, race] + } + + skPointCount(i, skills) { + if (this.GCSVersion === 5) { + if (i.id.startsWith('q')) i.type = 'technique' + if (i.id.startsWith('s')) i.type = 'skill' + if (i.id.startsWith('S')) i.type = 'skill_container' + if (i.id.startsWith('r')) i.type = 'ritual_magic_spell' + if (i.id.startsWith('p')) i.type = 'spell' + if (i.id.startsWith('P')) i.type = 'spell_container' + } + if (i.type == ('skill_container' || 'spell_container') && i.children?.length) + for (let j of i.children) skills = this.skPointCount(j, skills) + else skills += i.points + return skills + } + + /** + * Copy old OTFs to the new object, and update the displayable notes + * @param {Skill|Spell|Ranged|Melee} oldobj + * @param {Skill|Spell|Ranged|Melee} newobj + */ + _migrateOtfsAndNotes(oldobj = {}, newobj, importvttnotes = '', usagenotes = '') { + if (!!importvttnotes) newobj.notes += (!!newobj.notes ? ' ' : '') + importvttnotes + if (!!usagenotes) newobj.notes += (!!newobj.notes ? ' ' : '') + usagenotes + this._updateOtf('check', oldobj, newobj) + this._updateOtf('during', oldobj, newobj) + this._updateOtf('pass', oldobj, newobj) + this._updateOtf('fail', oldobj, newobj) + if (oldobj.notes?.startsWith(newobj.notes)) + // Must be done AFTER OTFs have been stripped out + newobj.notes = oldobj.notes + if (oldobj.name?.startsWith(newobj.name)) newobj.name = oldobj.name + } + + /** + * Search for specific format OTF in the notes (and vttnotes). + * If we find it in the notes, remove it and replace the notes with the shorter version + */ + _updateOtf(otfkey, oldobj, newobj) { + let objkey = otfkey + 'otf' + let oldotf = oldobj[objkey] + newobj[objkey] = oldotf + var notes, newotf + ;[notes, newotf] = this._removeOtf(otfkey, newobj.notes || '') + if (!!newotf) newobj[objkey] = newotf + newobj.notes = notes.trim() + } + + // Looking for OTFs in text. ex: c:[/qty -1] during:[/anim healing c] + _removeOtf(key, text) { + if (!text) return [text, null] + let otf = null + let found = true + while (found) { + found = false + var start + let patstart = text.toLowerCase().indexOf(key[0] + ':[') + if (patstart < 0) { + patstart = text.toLowerCase().indexOf(key + ':[') + if (patstart < 0) return [text, otf] + else start = patstart + key.length + 2 + } else start = patstart + 3 + let cnt = 1 + let i = start + if (i >= text.length) return [text, otf] + do { + let ch = text[i++] + if (ch == '[') cnt++ + if (ch == ']') cnt-- + } while (i < text.length && cnt > 0) + if (cnt == 0) { + found = true + otf = text.substring(start, i - 1) + let front = text.substring(0, patstart) + let end = text.substr(i) + if ((front == '' || front.endsWith(' ')) && end.startsWith(' ')) end = end.substring(1) + text = front + end + } else return [text, otf] + } + return [text, otf] + } + + // Fold a flat array into a hierarchical target object + /** + * @param {any[]} flat + */ + foldList(flat, target = {}) { + flat.forEach(obj => { + if (!!obj.parentuuid) { + const parent = flat.find(o => o.uuid == obj.parentuuid) + if (!!parent) { + if (!parent.contains) parent.contains = {} // lazy init for older characters + GURPS.put(parent.contains, obj) + } else obj.parentuuid = '' // Can't find a parent, so put it in the top list. should never happen with GCS + } + }) + let index = 0 + flat.forEach(obj => { + if (!obj.parentuuid) GURPS.put(target, obj, index++) + }) + return target + } + + /** + * + * @param {Array} locations + */ + _getBodyPlan(locations) { + // each key is a "body plan" name like "humanoid" or "quadruped" + let tableNames = Object.keys(HitLocations.hitlocationDictionary) + + // create a map of tableName:count + /** @type {Record} */ + let tableScores = {} + tableNames.forEach(it => (tableScores[it] = 0)) + + // increment the count for a tableScore if it contains the same hit location as "prot" + locations.forEach(function (hitLocation) { + tableNames.forEach(function (tableName) { + if (HitLocations.hitlocationDictionary[tableName].hasOwnProperty(hitLocation.where)) { + tableScores[tableName] = tableScores[tableName] + 1 + } + }) + }) + + // Select the tableScore with the highest score. + let match = -1 + let name = HitLocations.HitLocation.HUMANOID + Object.keys(tableScores).forEach(function (score) { + if (tableScores[score] > match) { + match = tableScores[score] + name = score + } + }) + + // In the case of a tie, select the one whose score is closest to the number of entries + // in the table. + let results = Object.keys(tableScores).filter(it => tableScores[it] === match) + if (results.length > 1) { + let diff = Number.MAX_SAFE_INTEGER + results.forEach(key => { + // find the smallest difference + let table = HitLocations.hitlocationDictionary[key] + if (Object.keys(table).length - match < diff) { + diff = Object.keys(table).length - match + name = key + } + }) + } + + return name + } +} diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index f2ec503b9..34ebe2f34 100755 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -11,6 +11,7 @@ import GurpsActiveEffectListSheet from '../effects/active-effect-list.js' import MoveModeEditor from './move-mode-editor.js' import { Advantage, Equipment, Melee, Modifier, Note, Ranged, Reaction, Skill, Spell } from './actor-components.js' import SplitDREditor from './splitdr-editor.js' +import { ActorImporter } from './actor-importer.js' /** * Extend the basic ActorSheet with some very simple modifications @@ -1452,7 +1453,8 @@ export class GurpsActorSheet extends ActorSheet { async _onFileImport(event) { event.preventDefault() - this.actor.importCharacter() + new ActorImporter(this.actor).importActor() + // this.actor.importCharacter() } async _onToggleSheet(event, altsheet) { diff --git a/module/actor/actor.js b/module/actor/actor.js index f84f33b5a..4ab12a571 100644 --- a/module/actor/actor.js +++ b/module/actor/actor.js @@ -1,8 +1,6 @@ 'use strict' import { - xmlTextToJson, - // convertRollStringToArrayOfInt, recurselist, makeRegexPatternFrom, i18n, @@ -12,14 +10,12 @@ import { objectToArray, arrayToObject, zeroFill, - arrayBuffertoBase64, } from '../../lib/utilities.js' import { parselink, COSTS_REGEX } from '../../lib/parselink.js' import { ResourceTrackerManager } from './resource-tracker-manager.js' import ApplyDamageDialog from '../damage/applydamage.js' import * as HitLocations from '../hitlocation/hitlocation.js' import * as settings from '../../lib/miscellaneous-settings.js' -// import { SemanticVersion } from '../../lib/semver.js' import { MOVE_NONE, MOVE_ONE, @@ -31,25 +27,9 @@ import { PROPERTY_MOVEOVERRIDE_MANEUVER, PROPERTY_MOVEOVERRIDE_POSTURE, } from './maneuver.js' -import { SmartImporter } from '../smart-importer.js' import { GurpsItem } from '../item.js' import GurpsToken from '../token.js' -import { parseDecimalNumber } from '../../lib/parse-decimal-number/parse-decimal-number.js' -import { - _Base, - Skill, - Spell, - Advantage, - Ranged, - Note, - Encumbrance, - Equipment, - Reaction, - Modifier, - Melee, - HitLocationEntry, - Language, -} from './actor-components.js' +import { _Base, Advantage, Equipment, HitLocationEntry } from './actor-components.js' import { multiplyDice } from '../utilities/damage-utils.js' // Ensure that ALL actors has the current version loaded into them (for migration purposes) @@ -209,7 +189,7 @@ export class GurpsActor extends Actor { let newads = { ...this.system.ads } let langn = new RegExp('Language:?', 'i') let langt = new RegExp(i18n('GURPS.language') + ':?', 'i') - recurselist(this.system.languages, (e, k, d) => { + recurselist(this.system.languages, (e, _k, _d) => { let a = GURPS.findAdDisad(this, '*' + e.name) // is there an Adv including the same name if (a) { if (!a.name.match(langn) && !a.name.match(langt)) { @@ -281,17 +261,17 @@ export class GurpsActor extends Actor { // After all of the attributes are copied over, apply tired to ST // if (!!data.conditions.exhausted) // data.attributes.ST.value = Math.ceil(parseInt(data.attributes.ST.value.toString()) / 2) - recurselist(data.skills, (e, k, d) => { + recurselist(data.skills, (e, _k, _d) => { // @ts-ignore if (!!e.import) e.level = parseInt(+e.import) }) - recurselist(data.spells, (e, k, d) => { + recurselist(data.spells, (e, _k, _d) => { // @ts-ignore if (!!e.import) e.level = parseInt(+e.import) }) // we don't really need to use recurselist for melee/ranged... but who knows, they may become hierarchical in the future - recurselist(data.melee, (e, k, d) => { + recurselist(data.melee, (e, _k, _d) => { if (!!e.import) { e.level = parseInt(e.import) if (!isNaN(parseInt(e.parry))) { @@ -315,11 +295,11 @@ export class GurpsActor extends Actor { } }) - recurselist(data.ranged, (e, k, d) => { + recurselist(data.ranged, (e, _k, _d) => { e.level = parseInt(e.import) }) - recurselist(data.hitlocations, (e, k, d) => { + recurselist(data.hitlocations, (e, _k, _d) => { e.dr = e.import }) } @@ -340,7 +320,7 @@ export class GurpsActor extends Actor { let link = parselink(bonus) // ATM, we only support attribute and skill if (!!link.action) { // start OTF - recurselist(data.melee, (e, k, d) => { + recurselist(data.melee, (e, _k, _d) => { e.level = pi(e.level) if (link.action.type == 'attribute' && link.action.attrkey == 'DX') { // All melee attack skills affected by DX @@ -376,14 +356,14 @@ export class GurpsActor extends Actor { } } }) // end melee - recurselist(data.ranged, (e, k, d) => { + recurselist(data.ranged, (e, _k, _d) => { e.level = pi(e.level) if (link.action.type == 'attribute' && link.action.attrkey == 'DX') e.level += pi(link.action.mod) if (link.action.type == 'attack' && !!link.action.isRanged) { if (e.name.match(makeRegexPatternFrom(link.action.name, false))) e.level += pi(link.action.mod) } }) // end ranged - recurselist(data.skills, (e, k, d) => { + recurselist(data.skills, (e, _k, _d) => { e.level = pi(e.level) if (link.action.type == 'attribute') { // skills affected by attribute changes @@ -393,7 +373,7 @@ export class GurpsActor extends Actor { if (e.name.match(makeRegexPatternFrom(link.action.name, false))) e.level += pi(link.action.mod) } }) // end skills - recurselist(data.spells, (e, k, d) => { + recurselist(data.spells, (e, _k, _d) => { e.level = pi(e.level) if (link.action.type == 'attribute') { // spells affected by attribute changes @@ -454,11 +434,11 @@ export class GurpsActor extends Actor { _findEqtkeyForId(key, id) { var eqtkey let data = this.system - recurselist(data.equipment.carried, (e, k, d) => { + recurselist(data.equipment.carried, (e, k, _d) => { if (e[key] == id) eqtkey = 'system.equipment.carried.' + k }) if (!eqtkey) - recurselist(data.equipment.other, (e, k, d) => { + recurselist(data.equipment.other, (e, k, _d) => { if (e[key] == id) eqtkey = 'system.equipment.other.' + k }) return eqtkey @@ -966,294 +946,6 @@ export class GurpsActor extends Actor { await GURPS.performAction(accumulator, GURPS.LastActor) } - async importCharacter() { - let p = this.system.additionalresources.importpath - if (!!p) { - let m = p.match(/.*[/\\]Data[/\\](.*)/) - if (!!m) { - let f = m[1].replace(/\\/g, '/') - let xhr = new XMLHttpRequest() - xhr.responseType = 'arraybuffer' - xhr.open('GET', f) - - let promise = new Promise(resolve => { - xhr.onload = () => { - if (xhr.status === 200) { - // @ts-ignore - let s = arrayBuffertoBase64(xhr.response) - // @ts-ignore - this.importFromGCSv1(s, m[1], p) - } else this._openImportDialog() - resolve(this) - } - }) - xhr.send(null) - } else this._openImportDialog() - } else this._openImportDialog() - } - - async _openImportDialog() { - if (game.settings.get(settings.SYSTEM_NAME, settings.SETTING_USE_BROWSER_IMPORTER)) - this._openNonLocallyHostedImportDialog() - else this._openLocallyHostedImportDialog() - } - - async _openNonLocallyHostedImportDialog() { - try { - const file = await SmartImporter.getFileForActor(this) - const res = await this.importFromGCSv1(await file.text(), file.name) - if (res) SmartImporter.setFileForActor(this, file) - } catch (e) { - ui.notifications?.error(e) - throw e - } - } - - async _openLocallyHostedImportDialog() { - setTimeout(async () => { - new Dialog( - { - title: `Import character data for: ${this.name}`, - content: await renderTemplate('systems/gurps/templates/import-gcs-v1-data.html', { - name: '"' + this.name + '"', - }), - buttons: { - import: { - icon: '', - label: 'Import', - callback: html => { - const form = html.find('form')[0] - let files = form.data.files - let file = null - if (!files.length) { - return ui.notifications.error('You did not upload a data file!') - } else { - file = files[0] - GURPS.readTextFromFile(file).then(text => this.importFromGCSv1(text, file.name, file.path)) - } - }, - }, - no: { - icon: '', - label: 'Cancel', - }, - }, - default: 'import', - }, - { - width: 400, - } - ).render(true) - }, 200) - } - - /** - * - * @param {{ [key: string]: any}} json - */ - async importAttributesFromGCSv2(atts, eqp, calc) { - if (!atts) return - let data = this.system - let att = data.attributes - if (!att.QN) { - // upgrade older actors to include Q - att.QN = {} - data.QP = {} - } - - att.ST.import = atts.find(e => e.attr_id === 'st')?.calc?.value || 0 - att.ST.points = atts.find(e => e.attr_id === 'st')?.calc?.points || 0 - att.DX.import = atts.find(e => e.attr_id === 'dx')?.calc?.value || 0 - att.DX.points = atts.find(e => e.attr_id === 'dx')?.calc?.points || 0 - att.IQ.import = atts.find(e => e.attr_id === 'iq')?.calc?.value || 0 - att.IQ.points = atts.find(e => e.attr_id === 'iq')?.calc?.points || 0 - att.HT.import = atts.find(e => e.attr_id === 'ht')?.calc?.value || 0 - att.HT.points = atts.find(e => e.attr_id === 'ht')?.calc?.points || 0 - att.WILL.import = atts.find(e => e.attr_id === 'will')?.calc?.value || 0 - att.WILL.points = atts.find(e => e.attr_id === 'will')?.calc?.points || 0 - att.PER.import = atts.find(e => e.attr_id === 'per')?.calc?.value || 0 - att.PER.points = atts.find(e => e.attr_id === 'per')?.calc?.points || 0 - att.QN.import = atts.find(e => e.attr_id === 'qn')?.calc?.value || 0 - att.QN.points = atts.find(e => e.attr_id === 'qn')?.calc?.points || 0 - - data.HP.max = atts.find(e => e.attr_id === 'hp')?.calc?.value || 0 - data.HP.points = atts.find(e => e.attr_id === 'hp')?.calc?.points || 0 - data.FP.max = atts.find(e => e.attr_id === 'fp')?.calc?.value || 0 - data.FP.points = atts.find(e => e.attr_id === 'fp')?.calc?.points || 0 - data.QP.max = atts.find(e => e.attr_id === 'qp')?.calc?.value || 0 - data.QP.points = atts.find(e => e.attr_id === 'qp')?.calc?.points || 0 - let hp = atts.find(e => e.attr_id === 'hp')?.calc?.current || 0 - let fp = atts.find(e => e.attr_id === 'fp')?.calc?.current || 0 - let qp = atts.find(e => e.attr_id === 'qp')?.calc?.current || 0 - - let saveCurrent = false - - if (!!data.lastImport && (data.HP.value != hp || data.FP.value != fp)) { - let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_HP_FP) - if (option == 0) { - saveCurrent = true - } - if (option == 2) { - saveCurrent = await new Promise((resolve, reject) => { - let d = new Dialog({ - title: 'Current HP & FP', - content: `Do you want to

Save the current HP (${data.HP.value}) & FP (${data.FP.value}) values or

Overwrite it with the import data, HP (${hp}) & FP (${fp})?

 `, - buttons: { - save: { - icon: '', - label: 'Save', - callback: () => resolve(true), - }, - overwrite: { - icon: '', - label: 'Overwrite', - callback: () => resolve(false), - }, - }, - default: 'save', - close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. - }) - d.render(true) - }) - } - } - if (!saveCurrent) { - data.HP.value = hp - data.FP.value = fp - } - data.QP.value = qp - - let bl_value = parseFloat(calc?.basic_lift.match(/[\d\.]+/g)) - let bl_unit = calc?.basic_lift.replace(bl_value + ' ', '') - - let lm = {} - lm.basiclift = (bl_value * 1).toString() + ' ' + bl_unit - lm.carryonback = (bl_value * 15).toString() + ' ' + bl_unit - lm.onehandedlift = (bl_value * 2).toString() + ' ' + bl_unit - lm.runningshove = (bl_value * 24).toString() + ' ' + bl_unit - lm.shiftslightly = (bl_value * 50).toString() + ' ' + bl_unit - lm.shove = (bl_value * 12).toString() + ' ' + bl_unit - lm.twohandedlift = (bl_value * 8).toString() + ' ' + bl_unit - - let bm = atts.find(e => e.attr_id === 'basic_move')?.calc?.value || 0 - data.basicmove.value = bm.toString() - data.basicmove.points = atts.find(e => e.attr_id === 'basic_move')?.calc?.points || 0 - let bs = atts.find(e => e.attr_id === 'basic_speed')?.calc?.value || 0 - data.basicspeed.value = bs.toString() - data.basicspeed.points = atts.find(e => e.attr_id === 'basic_speed')?.calc?.points || 0 - - data.thrust = calc?.thrust - data.swing = calc?.swing - data.currentmove = data.basicmove.value - data.frightcheck = atts.find(e => e.attr_id === 'fright_check')?.calc?.value || 0 - - data.hearing = atts.find(e => e.attr_id === 'hearing')?.calc?.value || 0 - data.tastesmell = atts.find(e => e.attr_id === 'taste_smell')?.calc?.value || 0 - data.touch = atts.find(e => e.attr_id === 'touch')?.calc?.value || 0 - data.vision = atts.find(e => e.attr_id === 'vision')?.calc?.value || 0 - - let cm = 0 - let cd = 0 - let es = {} - let ew = [1, 2, 3, 6, 10] - let index = 0 - let total_carried = this.calcTotalCarried(eqp) - for (let i = 0; i <= 4; i++) { - let e = new Encumbrance() - e.level = i - e.current = false - e.key = 'enc' + i - let weight_value = bl_value * ew[i] - // e.current = total_carried <= weight_value && (i == 4 || total_carried < bl_value*ew[i+1]); - e.current = - (total_carried < weight_value || i == 4 || bl_value == 0) && (i == 0 || total_carried > bl_value * ew[i - 1]) - e.weight = weight_value.toString() + ' ' + bl_unit - e.move = calc?.move[i].toString() - e.dodge = calc?.dodge[i] - if (e.current) { - cm = e.move - cd = e.dodge - } - GURPS.put(es, e, index++) - } - - return { - 'system.attributes': att, - 'system.HP': data.HP, - 'system.FP': data.FP, - 'system.basiclift': data.basiclift, - 'system.basicmove': data.basicmove, - 'system.basicspeed': data.basicspeed, - 'system.thrust': data.thrust, - 'system.swing': data.swing, - 'system.currentmove': data.currentmove, - 'system.frightcheck': data.frightcheck, - 'system.hearing': data.hearing, - 'system.tastesmell': data.tastesmell, - 'system.touch': data.touch, - 'system.vision': data.vision, - 'system.liftingmoving': lm, - 'system.currentmove': cm, - 'system.currentdodge': cd, - 'system.encumbrance': es, - 'system.QP': data.QP, - } - } - - calcTotalCarried(eqp) { - let t = 0 - if (!eqp) return t - for (let i of eqp) { - let w = 0 - w += parseFloat(i.weight || '0') * (i.type == 'equipment_container' ? 1 : i.quantity || 0) - if (i.children?.length) w += this.calcTotalCarried(i.children) - t += w - } - return t - } - - async importTraitsFromGCSv2(p, cd, md) { - if (!p) return - let ts = {} - ts.race = '' - ts.height = p.height || '' - ts.weight = p.weight || '' - ts.age = p.age || '' - ts.title = p.title || '' - ts.player = p.player_name || '' - ts.createdon = - new Date(cd).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' }).replace(' at', ',') || '' - ts.modifiedon = - new Date(md).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' }).replace(' at', ',') || '' - // ts.modifiedon = md || '' - ts.religion = p.religion || '' - ts.birthday = p.birthday || '' - ts.hand = p.handedness || '' - ts.techlevel = p.tech_level || '' - ts.gender = p.gender || '' - ts.eyes = p.eyes || '' - ts.hair = p.hair || '' - ts.skin = p.skin || '' - ts.sizeod = p.SM || '+0' - - const r = { - 'system.-=traits': null, - 'system.traits': ts, - } - - if (p.portrait) { - if (game.user.hasPermission('FILES_UPLOAD')) { - r.img = `data:image/png;base64,${p.portrait}.png` - } else { - await ui.notifications.error( - 'You do not have "FILES_UPLOAD" permission, portrait upload has failed. Please ask your GM to import your character, or acquire the correct permissions.' - ) - } - } - - return r - } - getPortraitPath() { if (game.settings.get(settings.SYSTEM_NAME, settings.SETTING_PORTRAIT_PATH) == 'global') return 'images/portraits/' return `worlds/${game.world.id}/images/portraits` @@ -1268,2284 +960,157 @@ export class GurpsActor extends Actor { .replace(/(^-+|-+$)/g, '') } - signedNum(x) { - if (x >= 0) return `+${x}` - else return x.toString() - } + /** + * Adds any assigned resource trackers to the actor data and sheet. + */ + async setResourceTrackers() { + // find those with non-blank slots + let templates = ResourceTrackerManager.getAllTemplates().filter(it => !!it.slot) - importSizeFromGCSv1(commit, profile, ads, skills, equipment) { - let ts = commit['system.traits'] - let final = profile.SM || 0 - let temp = [].concat(ads, skills, equipment) - let all = [] - for (let i of temp) { - all = all.concat(this.recursiveGet(i)) - } - for (let i of all) { - if (i.features?.length) - for (let f of i.features) { - if (f.type == 'attribute_bonus' && f.attribute == 'sm') - final += f.amount * (!!i.levels ? parseFloat(i.levels) : 1) - } - } - ts.sizemod = this.signedNum(final) - return { - 'system.-=traits': null, - 'system.traits': ts, - } - } + for (const template of templates) { + // find the matching data on this actor + let index = zeroFill(template.slot, 4) + let path = `additionalresources.tracker.${index}` + let tracker = foundry.utils.getProperty(this, 'system.' + path) - importAdsFromGCSv3(ads) { - let temp = [] - if (!!ads) - for (let i of ads) { - temp = temp.concat(this.importAd(i, '')) + while (!tracker) { + await this.addTracker() + tracker = foundry.utils.getProperty(this, 'system.' + path) } - return { - 'system.-=ads': null, - 'system.ads': this.foldList(temp), - } - } - importAd(i, p) { - let a = new Advantage() - a.name = i.name + (i.levels ? ' ' + i.levels.toString() : '') || 'Trait' - a.points = i.calc?.points - a.notes = i.calc?.resolved_notes ?? i.notes ?? '' - a.userdesc = i.userdesc + // skip if already set + if (!!tracker && tracker.name === template.tracker.name) { + return + } - if (i.cr != null) { - a.notes = '[' + game.i18n.localize('GURPS.CR' + i.cr.toString()) + ': ' + a.name + ']' - } - if (i.modifiers?.length) { - for (let j of i.modifiers) - if (!j.disabled) a.notes += `${!!a.notes ? '; ' : ''}${j.name}${!!j.notes ? ' (' + j.notes + ')' : ''}` - } - // Not certain if this is needed, or is it a type-o (note vs. notes) - if (!!a.note) a.notes += (!!a.notes ? '\n' : '') + a.note - - if (!!a.userdesc) a.notes += (!!a.notes ? '\n' : '') + a.userdesc - a.pageRef(i.reference) - a.uuid = i.id - a.parentuuid = p - - let old = this._findElementIn('ads', a.uuid) - this._migrateOtfsAndNotes(old, a, i.vtt_notes) - - let ch = [] - if (i.children?.length) { - for (let j of i.children) ch = ch.concat(this.importAd(j, i.id)) - } - return [a].concat(ch) - } + // if not blank, don't overwrite + if (!!tracker && !!tracker.name) { + ui.notifications?.warn( + `Will not overwrite Tracker ${template.slot} as its name is set to ${tracker.name}. Create Tracker for ${template.tracker.name} failed.` + ) + return + } - importSkillsFromGCSv2(sks) { - if (!sks) return - let temp = [] - for (let i of sks) { - temp = temp.concat(this.importSk(i, '')) - } - return { - 'system.-=skills': null, - 'system.skills': this.foldList(temp), + await this.applyTrackerTemplate(path, template) } } - importSk(i, p) { - let name = - i.name + (!!i.tech_level ? `/TL${i.tech_level}` : '') + (!!i.specialization ? ` (${i.specialization})` : '') || - 'Skill' - if (i.type == 'technique' && !!i.default) { - let addition = '' - addition = ' (' + i.default.name - if (!!i.default.specialization) { - addition += ' (' + i.default.specialization + ')' + /** + * Update this tracker slot with the contents of the template. + * @param {String} path JSON data path to the tracker; must start with 'additionalresources.tracker.' + * @param {*} template to apply + */ + async applyTrackerTemplate(path, template) { + // is there an initializer? If so calculate its value + let value = template.tracker.value + if (!!template.initialValue) { + value = parseInt(template.initialValue, 10) + if (Number.isNaN(value)) { + // try to use initialValue as a path to another value + value = foundry.utils.getProperty(this, 'system.' + template.initialValue) } - name += addition + ')' } - let s = new Skill(name, '') - s.pageRef(i.reference || '') - s.uuid = i.id - s.parentuuid = p - if (['skill', 'technique'].includes(i.type)) { - s.type = i.type.toUpperCase() - s.import = !!i.calc ? i.calc.level : '' - if (s.level == 0) s.level = '' - s.points = i.points - s.relativelevel = i.calc?.rsl - s.notes = i.calc?.resolved_notes ?? i.notes ?? '' - } else { - // Usually containers - s.level = '' - } - let old = this._findElementIn('skills', s.uuid) - this._migrateOtfsAndNotes(old, s, i.vtt_notes) + template.tracker.max = value + template.tracker.value = template.tracker.isDamageTracker ? template.tracker.min : value - let ch = [] - if (i.children?.length) { - for (let j of i.children) ch = ch.concat(this.importSk(j, i.id)) - } - return [s].concat(ch) - } + // remove whatever is there + await this.clearTracker(path) - importSpellsFromGCSv2(sps) { - if (!sps) return - let temp = [] - for (let i of sps) { - temp = temp.concat(this.importSp(i, '')) - } - return { - 'system.-=spells': null, - 'system.spells': this.foldList(temp), - } + // add the new tracker + /** @type {{ [key: string]: any }} */ + let update = {} + update[`system.${path}`] = template.tracker + await this.update(update) } - importSp(i, p) { - let s = new Spell() - s.name = i.name || 'Spell' - s.uuid = i.id - s.parentuuid = p - s.pageRef(i.reference || '') - if (['spell', 'ritual_magic_spell'].includes(i.type)) { - s.class = i.spell_class || '' - s.college = i.college || '' - s.cost = i.casting_cost || '' - s.maintain = i.maintenance_cost || '' - s.difficulty = i.difficulty.toUpperCase() - s.relativelevel = i.calc?.rsl - s.notes = i.calc?.resolved_notes ?? i.notes ?? '' - s.duration = i.duration || '' - s.points = i.points || '' - s.casttime = i.casting_time || '' - s.import = i.calc?.level || 0 - } - - let old = this._findElementIn('spells', s.uuid) - this._migrateOtfsAndNotes(old, s, i.vtt_notes) + /** + * Overwrites the tracker pointed to by the path with default/blank values. + * @param {String} path JSON data path to the tracker; must start with 'additionalresources.tracker.' + */ + async clearTracker(path) { + // verify that this is a Tracker + const prefix = 'additionalresources.tracker.' + if (!path.startsWith(prefix)) throw `Invalid actor data path, actor=[${this.id}] path=[${path}]` - let ch = [] - if (i.children?.length) { - for (let j of i.children) ch = ch.concat(this.importSp(j, i.id)) + /** @type {{[key: string]: string}} */ + let update = {} + update[`system.${path}`] = { + name: '', + alias: '', + pdf: '', + max: 0, + min: 0, + value: 0, + isDamageTracker: false, + isDamageType: false, + initialValue: '', + thresholds: [], } - return [s].concat(ch) + await this.update(update) } - importEquipmentFromGCSv2(eq, oeq) { - if (!eq && !oeq) return - let temp = [] - if (!!eq) - for (let i of eq) { - temp = temp.concat(this.importEq(i, '', true)) - } - if (!!oeq) - for (let i of oeq) { - temp = temp.concat(this.importEq(i, '', false)) - } - - recurselist(this.system.equipment?.carried, t => { - t.carried = true - if (!!t.save) temp.push(t) - }) - recurselist(this.system.equipment?.other, t => { - t.carried = false - if (!!t.save) temp.push(t) - }) - - temp.forEach(e => { - e.contains = {} - e.collapsed = {} - }) - - temp.forEach(e => { - if (!!e.parentuuid) { - let parent = null - parent = temp.find(f => f.uuid === e.parentuuid) - if (!!parent) GURPS.put(parent.contains, e) - else e.parentuuid = '' - } - }) + /** + * Removes the indicated tracker from the object, reindexing the keys. + * @param {String} path JSON data path to the tracker; must start with 'additionalresources.tracker.' + */ + async removeTracker(path) { + this.ignoreRender = true + const prefix = 'additionalresources.tracker.' - let equipment = { - carried: {}, - other: {}, - } - let cindex = 0 - let oindex = 0 - - temp.forEach(eqt => { - Equipment.calc(eqt) - if (!eqt.parentuuid) { - if (eqt.carried) GURPS.put(equipment.carried, eqt, cindex++) - else GURPS.put(equipment.other, eqt, oindex++) - } - }) - return { - 'system.-=equipment': null, - 'system.equipment': equipment, - } - } + // verify that this is a Tracker + if (!path.startsWith(prefix)) throw `Invalid actor data path, actor=[${this.id}] path=[${path}]` - importEq(i, p, carried) { - let e = new Equipment() - e.name = i.description || 'Equipment' - e.count = i.type == 'equipment_container' ? '1' : i.quantity || '0' - e.cost = - (parseFloat(i.calc?.extended_value) / (i.type == 'equipment_container' ? 1 : i.quantity || 1)).toString() || '' - e.carried = carried - e.equipped = i.equipped - e.techlevel = i.tech_level || '' - e.legalityclass = i.legality_class || '4' - e.categories = i.categories?.join(', ') || '' - e.uses = i.uses || 0 - e.maxuses = i.max_uses || 0 - e.uuid = i.id - e.parentuuid = p - e.notes = '' - e.notes = i.calc?.resolved_notes ?? i.notes ?? '' - if (i.modifiers?.length) { - for (let j of i.modifiers) - if (!j.disabled) e.notes += `${!!e.notes ? '; ' : ''}${j.name}${!!j.notes ? ' (' + j.notes + ')' : ''}` - } - if (!!e.note) e.notes += (!!e.notes ? '\n' : '') + e.note - e.weight = - (parseFloat(i.calc?.extended_weight) / (i.type == 'equipment_container' ? 1 : i.quantity || 1)).toString() || '0' - e.pageRef(i.reference || '') - let old = this._findElementIn('equipment.carried', e.uuid) - if (!old) old = this._findElementIn('equipment.other', e.uuid) - this._migrateOtfsAndNotes(old, e, i.vtt_notes) - if (!!old) { - e.carried = old.carried - e.equipped = old.equipped - e.parentuuid = old.parentuuid - if (old.ignoreImportQty) { - e.count = old.count - e.uses = old.uses - e.maxuses = old.maxuses - e.ignoreImportQty = true - } - } - let ch = [] - if (i.children?.length) { - for (let j of i.children) ch = ch.concat(this.importEq(j, i.id, carried)) - for (let j of ch) { - e.cost -= j.cost * j.count - e.weight -= j.weight * j.count - } - // let weight_reduction = 0; - // if (!!i.modifiers?.length) for (let m of i.modifiers) if (!m.disabled && !!m.features?.length) for (let mf of m.features) if (mf.type == "contained_weight_reduction") weight_reduction += parseFloat(mf.reduction); - // if (!!i.features?.length) for (let f of i.features) if (f.type == "contained_weight_reduction") weight_reduction += parseFloat(f.reduction); - // for (let j of ch) { - // e.cost -= j.cost*j.count; - // if (weight_reduction == 0) e.weight -= j.weight*j.count; - // else { - // weight_reduction -= j.weight*j.count; - // if (weight_reduction < 0) { - // e.weight += weight_reduction; - // weight_reduction = 0; - // } - // } - // } - } - return [e].concat(ch) - } + let key = path.replace(prefix, '') + let trackerData = this.system.additionalresources.tracker + delete trackerData[key] + let trackers = objectToArray(trackerData) + let data = arrayToObject(trackers) - importNotesFromGCSv2(notes) { - if (!notes) return - let temp = [] - for (let i of notes) { - temp = temp.concat(this.importNote(i, '')) - } - recurselist(this.system.notes, t => { - if (!!t.save) temp.push(t) - }) - return { - 'system.-=notes': null, - 'system.notes': this.foldList(temp), - } - } + // remove all trackers + await this.update({ 'system.additionalresources.-=tracker': null }) + // add the new "array" of trackers + if (data) this.update({ 'system.additionalresources.tracker': data }) + else this.update('system.additionalresources.tracker', {}) - importNote(i, p) { - let n = new Note() - n.notes = i.calc?.resolved_text ?? i.text ?? '' - n.uuid = i.id - n.parentuuid = p - n.pageRef(i.reference || '') - let old = this._findElementIn('notes', n.uuid) - this._migrateOtfsAndNotes(old, n) - let ch = [] - if (i.children?.length) { - for (let j of i.children) ch = ch.concat(this.importNote(j, i.id)) - } - return [n].concat(ch) + this._forceRender() } - async importProtectionFromGCSv2(hls) { - if (!hls) return - let data = this.system - if (!!data.additionalresources.ignoreinputbodyplan) return - - /** @type {HitLocations.HitLocation[]} */ - let locations = [] - for (let i of hls.locations) { - let l = new HitLocations.HitLocation(i.table_name) - l.import = i.calc?.dr.all?.toString() || '0' - for (let [key, value] of Object.entries(i.calc?.dr)) - if (key != 'all') { - let damtype = GURPS.DamageTables.damageTypeMap[key] - if (!l.split) l.split = {} - l.split[damtype] = +l.import + value - } - l.penalty = i.hit_penalty?.toString() || '0' - while (locations.filter(it => it.where == l.where).length > 0) { - l.where = l.where + '*' - } - locations.push(l) - } - let vitals = locations.filter(value => value.where === HitLocations.HitLocation.VITALS) - if (vitals.length === 0) { - let hl = new HitLocations.HitLocation(HitLocations.HitLocation.VITALS) - hl.penalty = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].penalty - hl.roll = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].roll - hl.import = '0' - locations.push(hl) - } - // Hit Locations MUST come from an existing bodyplan hit location table, or else ADD (and - // potentially other features) will not work. Sometime in the future, we will look at - // user-entered hit locations. - let bodyplan = hls.id // Was a body plan actually in the import? - if (bodyplan === 'snakemen') bodyplan = 'snakeman' - let table = HitLocations.hitlocationDictionary[bodyplan] // If so, try to use it. - - /** @type {HitLocations.HitLocation[]} */ - let locs = [] - locations.forEach(e => { - if (!!table && !!table[e.where]) { - // if e.where already exists in table, don't map - locs.push(e) - } else { - // map to new name(s) ... sometimes we map 'Legs' to ['Right Leg', 'Left Leg'], for example. - e.locations(false).forEach(l => locs.push(l)) // Map to new names - } - }) - locations = locs - - if (!table) { - locs = [] - locations.forEach(e => { - e.locations(true).forEach(l => locs.push(l)) // Map to new names, but include original to help match against tables - }) - bodyplan = this._getBodyPlan(locs) - table = HitLocations.hitlocationDictionary[bodyplan] - } - // update location's roll and penalty based on the bodyplan - - if (!!table) { - Object.values(locations).forEach(it => { - let [lbl, entry] = HitLocations.HitLocation.findTableEntry(table, it.where) - if (!!entry) { - it.where = lbl // It might be renamed (ex: Skull -> Brain) - if (!it.penalty) it.penalty = entry.penalty - if (!it.roll || it.roll.length === 0 || it.roll === HitLocations.HitLocation.DEFAULT) it.roll = entry.roll - } - }) - } - - // write the hit locations out in bodyplan hit location table order. If there are - // other entries, append them at the end. - /** @type {HitLocations.HitLocation[]} */ - let temp = [] - Object.keys(table).forEach(key => { - let results = Object.values(locations).filter(loc => loc.where === key) - if (results.length > 0) { - if (results.length > 1) { - // If multiple locs have same where, concat the DRs. Leg 7 & Leg 8 both map to "Leg 7-8" - let d = '' - - /** @type {string | null} */ - let last = null - results.forEach(r => { - if (r.import != last) { - d += '|' + r.import - last = r.import - } - }) + async addTracker() { + this.ignoreRender = true - if (!!d) d = d.substr(1) - results[0].import = d - } - temp.push(results[0]) - locations = locations.filter(it => it.where !== key) - } else { - // Didn't find loc that should be in the table. Make a default entry - temp.push(new HitLocations.HitLocation(key, '0', table[key].penalty, table[key].roll)) - } - }) - locations.forEach(it => temp.push(it)) + let trackerData = { name: '', value: 0, min: 0, max: 0, points: 0 } + let data = GurpsActor.addTrackerToDataObject(this.system, trackerData) - let prot = {} - let index = 0 - temp.forEach(it => GURPS.put(prot, it, index++)) + await this.update({ 'system.additionalresources.-=tracker': null }) + await this.update({ 'system.additionalresources.tracker': data }) - let saveprot = true - if (!!data.lastImport && !!data.additionalresources.bodyplan && bodyplan != data.additionalresources.bodyplan) { - let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_BODYPLAN) - if (option == 1) { - saveprot = false - } - if (option == 2) { - saveprot = await new Promise((resolve, reject) => { - let d = new Dialog({ - title: 'Hit Location Body Plan', - content: - `Do you want to

Save the current Body Plan (${game.i18n.localize( - 'GURPS.BODYPLAN' + data.additionalresources.bodyplan - )}) or ` + - `

Overwrite it with the Body Plan from the import: (${game.i18n.localize( - 'GURPS.BODYPLAN' + bodyplan - )})?

 `, - buttons: { - save: { - icon: '', - label: 'Save', - callback: () => resolve(false), - }, - overwrite: { - icon: '', - label: 'Overwrite', - callback: () => resolve(true), - }, - }, - default: 'save', - close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. - }) - d.render(true) - }) - } - } - if (saveprot) { - return { - 'system.-=hitlocations': null, - 'system.hitlocations': prot, - 'system.additionalresources.bodyplan': bodyplan, - } - } else return {} + this._forceRender() } - importPointTotalsFromGCSv2(total, atts, ads, skills, spells) { - if (!ads) ads = [] - if (!skills) skills = [] - if (!spells) spells = [] - let p_atts = 0 - let p_ads = 0 - let p_disads = 0 - let p_quirks = 0 - let p_skills = 0 - let p_spells = 0 - let p_unspent = total - let p_total = total - let p_race = 0 - for (let i of atts) p_atts += i.calc?.points - for (let i of ads) - [p_ads, p_disads, p_quirks, p_race] = this.adPointCount(i, p_ads, p_disads, p_quirks, p_race, true) - for (let i of skills) p_skills = this.skPointCount(i, p_skills) - for (let i of spells) p_spells = this.skPointCount(i, p_spells) - p_unspent -= p_atts + p_ads + p_disads + p_quirks + p_skills + p_spells + p_race - return { - 'system.totalpoints.attributes': p_atts, - 'system.totalpoints.ads': p_ads, - 'system.totalpoints.disads': p_disads, - 'system.totalpoints.quirks': p_quirks, - 'system.totalpoints.skills': p_skills, - 'system.totalpoints.spells': p_spells, - 'system.totalpoints.unspent': p_unspent, - 'system.totalpoints.total': p_total, - 'system.totalpoints.race': p_race, - } + static addTrackerToDataObject(data, trackerData) { + let trackers = GurpsActor.getTrackersAsArray(data) + trackers.push(trackerData) + return arrayToObject(trackers) } - importReactionsFromGCSv3(ads, skills, equipment) { - let rs = {} - let cs = {} - let index_r = 0 - let index_c = 0 - let temp = [].concat(ads, skills, equipment) - let all = [] - for (let i of temp) { - all = all.concat(this.recursiveGet(i)) - } - let temp_r = [] - let temp_c = [] - for (let i of all) { - if (i.features?.length) - for (let f of i.features) { - if (f.type == 'reaction_bonus') { - temp_r.push({ - modifier: f.amount * (f.per_level && !!i.levels ? parseInt(i.levels) : 1), - situation: f.situation, - }) - } else if (f.type == 'conditional_modifier') { - temp_c.push({ - modifier: f.amount * (f.per_level && !!i.levels ? parseInt(i.levels) : 1), - situation: f.situation, - }) - } - } - } - let temp_r2 = [] - let temp_c2 = [] - for (let i of temp_r) { - let existing_condition = temp_r2.find(e => e.situation == i.situation) - if (!!existing_condition) existing_condition.modifier += i.modifier - else temp_r2.push(i) - } - for (let i of temp_c) { - let existing_condition = temp_c2.find(e => e.situation == i.situation) - if (!!existing_condition) existing_condition.modifier += i.modifier - else temp_c2.push(i) - } - for (let i of temp_r2) { - let r = new Reaction() - r.modifier = i.modifier.toString() - r.situation = i.situation - GURPS.put(rs, r, index_r++) - } - for (let i of temp_c2) { - let c = new Modifier() - c.modifier = i.modifier.toString() - c.situation = i.situation - GURPS.put(cs, c, index_c++) - } - return { - 'system.-=reactions': null, - 'system.reactions': rs, - 'system.-=conditionalmods': null, - 'system.conditionalmods': cs, - } + static getTrackersAsArray(data) { + let trackerArray = data.additionalresources.tracker + if (!trackerArray) trackerArray = {} + return objectToArray(trackerArray) } - importCombatFromGCSv2(ads, skills, spells, equipment) { - let melee = {} - let ranged = {} - let m_index = 0 - let r_index = 0 - let temp = [].concat(ads, skills, spells, equipment) - let all = [] - for (let i of temp) { - all = all.concat(this.recursiveGet(i)) - } - for (let i of all) { - if (i.weapons?.length) - for (let w of i.weapons) { - if (w.type == 'melee_weapon') { - let m = new Melee() - m.name = i.name || i.description || '' - m.st = w.strength || '' - m.weight = i.weight || '' - m.techlevel = i.tech_level || '' - m.cost = i.value || '' - m.notes = i.notes || '' - m.pageRef(i.reference || '') - m.mode = w.usage || '' - m.import = w.calc?.level?.toString() || '0' - m.damage = w.calc?.damage || '' - m.reach = w.reach || '' - m.parry = w.calc?.parry || '' - m.block = w.calc?.block || '' - let old = this._findElementIn('melee', false, m.name, m.mode) - this._migrateOtfsAndNotes(old, m, i.vtt_notes, w.usage_notes) - - GURPS.put(melee, m, m_index++) - } else if (w.type == 'ranged_weapon') { - let r = new Ranged() - r.name = i.name || i.description || '' - r.st = w.strength || '' - r.bulk = w.bulk || '' - r.legalityclass = i.legality_class || '4' - r.ammo = 0 - r.notes = i.notes || '' - r.pageRef(i.reference || '') - r.mode = w.usage || '' - r.import = w.calc?.level || '0' - r.damage = w.calc?.damage || '' - r.acc = w.accuracy || '' - let m = r.acc.trim().match(/(\d+)([+-]\d+)/) - if (m) { - r.acc = m[1] - r.notes += ' [' + m[2] + ' ' + i18n('GURPS.acc') + ']' - } - r.rof = w.rate_of_fire || '' - r.shots = w.shots || '' - r.rcl = w.recoil || '' - r.range = w.calc?.range || w.range || '' - let old = this._findElementIn('ranged', false, r.name, r.mode) - this._migrateOtfsAndNotes(old, r, i.vtt_notes, w.usage_notes) - - GURPS.put(ranged, r, r_index++) - } - } - } - return { - 'system.-=melee': null, - 'system.melee': melee, - 'system.-=ranged': null, - 'system.ranged': ranged, + async setMoveDefault(value) { + this.ignoreRender = true + let move = this.system.move + for (const key in move) { + move[key].default = value === key } + await this.update({ 'system.-=move': null }) + await this.update({ 'system.move': move }) + this._forceRender() } - recursiveGet(i) { - if (!i) return [] - let ch = [] - if (i.children?.length) for (let j of i.children) ch = ch.concat(this.recursiveGet(j)) - if (i.modifiers?.length) for (let j of i.modifiers) ch = ch.concat(this.recursiveGet(j)) - if (!!i.disabled || (i.equipped != null && i.equipped == false)) return [] - return [i].concat(ch) - } - - adPointCount(i, ads, disads, quirks, race, toplevel = false) { - if (i.type == 'advantage_container' && i.container_type == 'race') race += i.calc?.points - else if (i.type == 'advantage_container' && i.container_type == 'alternative_abilities') ads += i.calc?.points - else if (i.type == 'advantage_container' && !!i.children?.length) { - var [a, d] = [0, 0] - for (let j of i.children) [a, d, quirks, race] = this.adPointCount(j, a, d, quirks, race) - if (toplevel) { - if (a > 0) ads += a - else disads += a - disads += d - } else ads += a + d - } else if (i.calc?.points == -1) quirks += i.calc?.points - else if (i.calc?.points > 0) ads += i.calc?.points - else disads += i.calc?.points - return [ads, disads, quirks, race] - } - - skPointCount(i, skills) { - if (i.type == ('skill_container' || 'spell_container') && i.children?.length) - for (let j of i.children) skills = this.skPointCount(j, skills) - else skills += i.points - return skills - } - - /** - * @param {string} json - * @param {string} importname - * @param {string | undefined} [importpath] - */ - async importFromGCSv2(json, importname, importpath, suppressMessage = false, GCAVersion, GCSVersion) { - let r - let msg = [] - let version = 'Direct GCS Import' - let exit = false - try { - r = JSON.parse(json) - } catch (err) { - msg.push(i18n('GURPS.importNoJSONDetected')) - exit = true - } - if (!!r) { - if (!r.calc) { - msg.push(i18n('GURPS.importOldGCSFile')) - exit = true - } - } - - if (msg.length > 0) { - ui.notifications?.error(msg.join('
')) - let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { - lines: msg, - version: version, - GCAVersion: GCAVersion, - GCSVersion: GCSVersion, - url: GURPS.USER_GUIDE_URL, - }) - ChatMessage.create({ - content: content, - user: game.user.id, - whisper: [game.user.id], - }) - if (exit) return false - } - - let nm = r['profile']['name'] - console.log("Importing '" + nm + "'") - let starttime = performance.now() - let commit = {} - - commit = { ...commit, ...{ 'system.lastImport': new Date().toString().split(' ').splice(1, 4).join(' ') } } - let ar = this.system.additionalresources || {} - ar.importname = importname || ar.importname - ar.importpath = importpath || ar.importpath - try { - commit = { ...commit, ...{ 'system.additionalresources': ar } } - commit = { ...commit, ...(await this.importAttributesFromGCSv2(r.attributes, r.equipment, r.calc)) } - commit = { ...commit, ...(await this.importTraitsFromGCSv2(r.profile, r.created_date, r.modified_date)) } - commit = { - ...commit, - ...this.importSizeFromGCSv1(commit, r.profile, r.traits || r.advantages, r.skills, r.equipment), - } - commit = { ...commit, ...this.importAdsFromGCSv3(r.traits || r.advantages) } - commit = { ...commit, ...this.importSkillsFromGCSv2(r.skills) } - commit = { ...commit, ...this.importSpellsFromGCSv2(r.spells) } - commit = { ...commit, ...this.importEquipmentFromGCSv2(r.equipment, r.other_equipment) } - commit = { ...commit, ...this.importNotesFromGCSv2(r.notes) } - - commit = { - ...commit, - ...(await this.importProtectionFromGCSv2(r.settings.body_type || r.settings.hit_locations)), - } - commit = { - ...commit, - ...this.importPointTotalsFromGCSv2(r.total_points, r.attributes, r.traits || r.advantages, r.skills, r.spells), - } - commit = { ...commit, ...this.importReactionsFromGCSv3(r.traits || r.advantages, r.skills, r.equipment) } - commit = { ...commit, ...this.importCombatFromGCSv2(r.traits || r.advantages, r.skills, r.spells, r.equipment) } - } catch (err) { - console.log(err.stack) - msg.push( - i18n_f('GURPS.importGenericError', { - name: nm, - error: err.name, - message: err.message, - }) - ) - let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { - lines: [msg], - version: version, - GCAVersion: GCAVersion, - GCSVersion: GCSVersion, - url: GURPS.USER_GUIDE_URL, - }) - ui.notifications?.warn(msg) - let chatData = { - user: game.user.id, - content: content, - whisper: [game.user.id], - } - ChatMessage.create(chatData, {}) - // Don't return - } - - console.log('Starting commit') - - let deletes = Object.fromEntries(Object.entries(commit).filter(([key, value]) => key.includes('.-='))) - let adds = Object.fromEntries(Object.entries(commit).filter(([key, value]) => !key.includes('.-='))) - - try { - this.ignoreRender = true - await this.internalUpdate(deletes, { diff: true }) - await this.internalUpdate(adds, { diff: false }) - // This has to be done after everything is loaded - await this.postImport() - this._forceRender() - - // Must update name outside of protection so that Actors list (and other external views) update correctly - if (!game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IGNORE_IMPORT_NAME)) { - await this.update({ name: nm, 'token.name': nm }) - } - - if (!suppressMessage) ui.notifications?.info(i18n_f('GURPS.importSuccessful', { name: nm })) - console.log( - 'Done importing (' + - Math.round(performance.now() - starttime) + - 'ms.) You can inspect the character data below:' - ) - console.log(this) - return true - } catch (err) { - console.log(err.stack) - let msg = [i18n_f('GURPS.importGenericError', { name: nm, error: err.name, message: err.message })] - if (err.message == 'Maximum depth exceeded') msg.push(i18n('GURPS.importTooManyContainers')) - ui.notifications?.warn(msg.join('
')) - let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { - lines: msg, - version: 'GCS Direct', - GCAVersion: GCAVersion, - GCSVersion: GCSVersion, - url: GURPS.USER_GUIDE_URL, - }) - - let user = game.user - let chatData = { - user: game.user.id, - content: content, - whisper: [game.user.id], - } - ChatMessage.create(chatData, {}) - return false - } - } - - // First attempt at import GCS FG XML export data. - /** - * @param {string} xml - * @param {string} importname - * @param {string | undefined} [importpath] - */ - async importFromGCSv1(xml, importname, importpath, suppressMessage = false) { - const GCA5Version = 'GCA5-14' - const GCAVersion = 'GCA-11' - const GCSVersion = 'GCS-5' - if (importname.endsWith('.gcs')) - return this.importFromGCSv2(xml, importname, importpath, suppressMessage, GCAVersion, GCSVersion) - var c, ra // The character json, release attributes - let isFoundryGCS = false - let isFoundryGCA = false - let isFoundryGCA5 = false - // need to remove

and replace

with newlines from "formatted text" - let origx = GURPS.cleanUpP(xml) - let x = xmlTextToJson(origx) - // @ts-ignore - let r = x.root - let msg = [] - let version = 'unknown' - let vernum = 1 - let exit = false - if (!r) { - if (importname.endsWith('.gca5')) msg.push(i18n('GURPS.importCannotImportGCADirectly')) - if (importname.endsWith('.gca4')) msg.push(i18n('GURPS.importCannotImportGCADirectly')) - else if (!xml.startsWith(' 0) { - ui.notifications?.error(msg.join('
')) - let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { - lines: msg, - version: version, - GCAVersion: GCAVersion, - GCSVersion: GCSVersion, - url: GURPS.USER_GUIDE_URL, - }) - - let user = game.user - ChatMessage.create({ - content: content, - user: game.user.id, - whisper: [game.user.id], - }) - if (exit) return false // Some errors cannot be forgiven ;-) - } - let nm = this.textFrom(c.name) - console.log("Importing '" + nm + "'") - let starttime = performance.now() - - let commit = {} - commit = { ...commit, ...{ 'system.lastImport': new Date().toString().split(' ').splice(1, 4).join(' ') } } - let ar = this.system.additionalresources || {} - ar.importname = importname || ar.importname - ar.importpath = importpath || ar.importpath - ar.importversion = ra.version - commit = { ...commit, ...{ 'system.additionalresources': ar } } - - try { - // This is going to get ugly, so break out various data into different methods - commit = { ...commit, ...(await this.importAttributesFromCGSv1(c.attributes)) } - commit = { ...commit, ...this.importSkillsFromGCSv1(c.abilities?.skilllist, isFoundryGCS) } - commit = { ...commit, ...this.importTraitsfromGCSv1(c.traits) } - commit = { ...commit, ...this.importCombatMeleeFromGCSv1(c.combat?.meleecombatlist, isFoundryGCS) } - commit = { ...commit, ...this.importCombatRangedFromGCSv1(c.combat?.rangedcombatlist, isFoundryGCS) } - commit = { ...commit, ...this.importSpellsFromGCSv1(c.abilities?.spelllist, isFoundryGCS) } - if (isFoundryGCS) { - commit = { ...commit, ...this.importAdsFromGCSv2(c.traits?.adslist) } - commit = { ...commit, ...this.importReactionsFromGCSv2(c.reactions) } - commit = { ...commit, ...this.importConditionalModifiersFromGCSv2(c.conditionalmods) } - } - if (isFoundryGCA) { - commit = { ...commit, ...this.importLangFromGCA(c.traits?.languagelist) } - commit = { ...commit, ...this.importAdsFromGCA(c.traits?.adslist, c.traits?.disadslist) } - commit = { ...commit, ...this.importReactionsFromGCA(c.traits?.reactionmodifiers, vernum) } - } - commit = { ...commit, ...this.importEncumbranceFromGCSv1(c.encumbrance) } - commit = { ...commit, ...this.importPointTotalsFromGCSv1(c.pointtotals) } - commit = { ...commit, ...this.importNotesFromGCSv1(c.description, c.notelist) } - commit = { ...commit, ...this.importEquipmentFromGCSv1(c.inventorylist, isFoundryGCS) } - commit = { ...commit, ...(await this.importProtectionFromGCSv1(c.combat?.protectionlist, isFoundryGCA)) } - } catch (err) { - console.log(err.stack) - let msg = i18n_f('GURPS.importGenericError', { name: nm, error: err.name, message: err.message }) - let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { - lines: [msg], - version: version, - GCAVersion: GCAVersion, - GCSVersion: GCSVersion, - url: GURPS.USER_GUIDE_URL, - }) - - ui.notifications?.warn(msg) - let user = game.user - let chatData = { - user: game.user.id, - content: content, - whisper: [game.user.id], - } - ChatMessage.create(chatData, {}) - // Don't return, because we want to see how much actually gets committed. - } - console.log('Starting commit') - - let deletes = Object.fromEntries(Object.entries(commit).filter(([key, value]) => key.includes('.-='))) - let adds = Object.fromEntries(Object.entries(commit).filter(([key, value]) => !key.includes('.-='))) - - try { - this.ignoreRender = true - await this.internalUpdate(deletes, { diff: false }) - await this.internalUpdate(adds, { diff: false }) - // This has to be done after everything is loaded - await this.postImport() - this._forceRender() - - // Must update name outside of protection so that Actors list (and other external views) update correctly - if (!game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IGNORE_IMPORT_NAME)) { - await this.update({ name: nm, 'token.name': nm }) - } - - if (!suppressMessage) ui.notifications?.info(i18n_f('GURPS.importSuccessful', { name: nm })) - console.log( - 'Done importing (' + - Math.round(performance.now() - starttime) + - 'ms.) You can inspect the character data below:' - ) - console.log(this) - return true - } catch (err) { - console.log(err.stack) - let msg = [i18n_f('GURPS.importGenericError', { name: nm, error: err.name, message: err.message })] - if (err.message == 'Maximum depth exceeded') msg.push(i18n('GURPS.importTooManyContainers')) - if (!supressMessage) ui.notifications?.warn(msg.join('
')) - let content = await renderTemplate('systems/gurps/templates/chat-import-actor-errors.html', { - lines: msg, - version: version, - GCAVersion: GCAVersion, - GCSVersion: GCSVersion, - url: GURPS.USER_GUIDE_URL, - }) - - let user = game.user - let chatData = { - user: game.user.id, - content: content, - whisper: [game.user.id], - } - ChatMessage.create(chatData, {}) - return false - } - } - - // hack to get to private text element created by xml->json method. - /** - * @param {{ [key: string]: any }} o - */ - textFrom(o) { - if (!o) return '' - let t = o['#text'] - if (!t) return '' - return t.trim() - } - - // similar hack to get text as integer. - /** - * @param {{ [key: string]: any }} o - */ - intFrom(o) { - if (!o) return 0 - let i = o['#text'] - if (!i) return 0 - return parseInt(i) - } - - /** - * @param {{[key: string] : any}} o - */ - floatFrom(o) { - if (!o) return 0 - let f = o['#text'].trim() - if (!f) return 0 - return f.includes(',') ? parseDecimalNumber(f, { thousands: '.', decimal: ',' }) : parseDecimalNumber(f) - } - - /** - * @param {string} list - * @param {string|boolean} uuid - */ - _findElementIn(list, uuid, name = '', mode = '') { - var foundkey - let l = foundry.utils.getProperty(this, 'system.' + list) - recurselist(l, (e, k, d) => { - if ((uuid && e.uuid == uuid) || (!!e.name && e.name.startsWith(name) && e.mode == mode)) foundkey = k - }) - return foundkey == null ? foundkey : foundry.utils.getProperty(this, 'system.' + list + '.' + foundkey) - } - - /** - * @param {{ [key: string]: any }} json - */ - importReactionsFromGCSv2(json) { - if (!json) return - let t = this.textFrom - let rs = {} - let index = 0 - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let r = new Reaction() - r.modifier = t(j.modifier) - r.situation = t(j.situation) - GURPS.put(rs, r, index++) - } - } - return { - 'system.-=reactions': null, - 'system.reactions': rs, - } - } - - importConditionalModifiersFromGCSv2(json) { - if (!json) return - let t = this.textFrom - let rs = {} - let index = 0 - for (let key in json) { - if (key.startsWith('id-')) { - let j = json[key] - let r = new Reaction() // ConditionalModifiers are the same format - r.modifier = t(j.modifier) - r.situation = t(j.situation) - GURPS.put(rs, r, index++) - } - } - return { - 'system.-=conditionalmods': null, - 'system.conditionalmods': rs, - } - } - - /** - * @param {{ [key: string]: any }} json - */ - importReactionsFromGCA(json, vernum) { - if (!json) return - let text = this.textFrom(json) - let a = vernum <= 9 ? text.split(',') : text.split('|') - let rs = {} - let index = 0 - a.forEach((/** @type {string} */ m) => { - if (!!m) { - let t = m.trim() - let i = t.indexOf(' ') - let mod = t.substring(0, i) - let sit = t.substr(i + 1) - let r = new Reaction(mod, sit) - GURPS.put(rs, r, index++) - } - }) - return { - 'system.-=reactions': null, - 'system.reactions': rs, - } - } - - importLangFromGCA(json) { - if (!json) return - let langs = {} - let index = 0 - let t = this.textFrom - for (let key in json) { - if (key.startsWith('id-')) { - let j = json[key] - let n = t(j.name) - let s = t(j.spoken) - let w = t(j.written) - let p = t(j.points) - let l = new Language(n, s, w, p) - GURPS.put(langs, l, index++) - } - } - return { - 'system.-=languages': null, - 'system.languages': langs, - } - } - - /** - * @param {{ attributes: Record; ads: Record; disads: Record; quirks: Record; skills: Record; spells: Record; unspentpoints: Record; totalpoints: Record; race: Record; }} json - */ - importPointTotalsFromGCSv1(json) { - if (!json) return - - let i = this.intFrom - return { - 'system.totalpoints.attributes': i(json.attributes), - 'system.totalpoints.ads': i(json.ads), - 'system.totalpoints.disads': i(json.disads), - 'system.totalpoints.quirks': i(json.quirks), - 'system.totalpoints.skills': i(json.skills), - 'system.totalpoints.spells': i(json.spells), - 'system.totalpoints.unspent': i(json.unspentpoints), - 'system.totalpoints.total': i(json.totalpoints), - 'system.totalpoints.race': i(json.race), - } - } - - /** - * @param {{ [key: string]: any }} descjson - * @param {{ [key: string]: any }} json - */ - importNotesFromGCSv1(descjson, json) { - if (!json) return - let t = this.textFrom - let temp = [] - if (!!descjson) { - // support for GCA description - - let n = new Note() - n.notes = t(descjson).replace(/\\r/g, '\n') - n.imported = true - temp.push(n) - } - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let n = /** @type {Note & { imported: boolean, uuid: string, parentuuid: string }} */ (new Note()) - //n.setNotes(t(j.text)); - n.notes = t(j.name) - let txt = t(j.text) - if (!!txt) n.notes = n.notes + '\n' + txt.replace(/\\r/g, '\n') - n.uuid = t(j.uuid) - n.parentuuid = t(j.parentuuid) - n.pageref = t(j.pageref) - let old = this._findElementIn('notes', n.uuid) - this._migrateOtfsAndNotes(old, n) - temp.push(n) - } - } - // Save the old User Entered Notes. - recurselist(this.system.notes, t => { - if (!!t.save) temp.push(t) - }) - return { - 'system.-=notes': null, - 'system.notes': this.foldList(temp), - } - } - - /** - * @param {{ [x: string]: any; bodyplan: Record; }} json - * @param {boolean} isFoundryGCA - */ - async importProtectionFromGCSv1(json, isFoundryGCA) { - if (!json) return - let t = this.textFrom - let data = this.system - if (!!data.additionalresources.ignoreinputbodyplan) return - - /** @type {HitLocations.HitLocation[]} */ - let locations = [] - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let hl = new HitLocations.HitLocation(t(j.location)) - let i = t(j.dr) - if (i.match(/^\d+ *(\+ *\d+ *)?$/)) i = eval(t(j.dr)) // supports "0 + 8" - hl.import = !i ? 0 : i - hl.penalty = t(j.db) - hl.setEquipment(t(j.text)) - - // Some hit location tables have two entries for the same location. The code requires - // each location to be unique. Append an asterisk to the location name in that case. Hexapods and ichthyoid - while (locations.filter(it => it.where == hl.where).length > 0) { - hl.where = hl.where + '*' - } - locations.push(hl) - } - } - - // Do the results contain vitals? If not, add it. - let vitals = locations.filter(value => value.where === HitLocations.HitLocation.VITALS) - if (vitals.length === 0) { - let hl = new HitLocations.HitLocation(HitLocations.HitLocation.VITALS) - hl.penalty = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].penalty - hl.roll = HitLocations.hitlocationRolls[HitLocations.HitLocation.VITALS].roll - hl.import = '0' - locations.push(hl) - } - - // Hit Locations MUST come from an existing bodyplan hit location table, or else ADD (and - // potentially other features) will not work. Sometime in the future, we will look at - // user-entered hit locations. - let bodyplan = t(json.bodyplan)?.toLowerCase() // Was a body plan actually in the import? - if (bodyplan === 'snakemen') bodyplan = 'snakeman' - let table = HitLocations.hitlocationDictionary[bodyplan] // If so, try to use it. - - /** @type {HitLocations.HitLocation[]} */ - let locs = [] - locations.forEach(e => { - if (!!table && !!table[e.where]) { - // if e.where already exists in table, don't map - locs.push(e) - } else { - // map to new name(s) ... sometimes we map 'Legs' to ['Right Leg', 'Left Leg'], for example. - e.locations(false).forEach(l => locs.push(l)) // Map to new names - } - }) - locations = locs - - if (!table) { - locs = [] - locations.forEach(e => { - e.locations(true).forEach(l => locs.push(l)) // Map to new names, but include original to help match against tables - }) - bodyplan = this._getBodyPlan(locs) - table = HitLocations.hitlocationDictionary[bodyplan] - } - // update location's roll and penalty based on the bodyplan - - if (!!table) { - Object.values(locations).forEach(it => { - let [lbl, entry] = HitLocations.HitLocation.findTableEntry(table, it.where) - if (!!entry) { - it.where = lbl // It might be renamed (ex: Skull -> Brain) - if (!it.penalty) it.penalty = entry.penalty - if (!it.roll || it.roll.length === 0 || it.roll === HitLocations.HitLocation.DEFAULT) it.roll = entry.roll - } - }) - } - - // write the hit locations out in bodyplan hit location table order. If there are - // other entries, append them at the end. - /** @type {HitLocations.HitLocation[]} */ - let temp = [] - Object.keys(table).forEach(key => { - let results = Object.values(locations).filter(loc => loc.where === key) - if (results.length > 0) { - if (results.length > 1) { - // If multiple locs have same where, concat the DRs. Leg 7 & Leg 8 both map to "Leg 7-8" - let d = '' - - /** @type {string | null} */ - let last = null - results.forEach(r => { - if (r.import != last) { - d += '|' + r.import - last = r.import - } - }) - - if (!!d) d = d.substr(1) - results[0].import = d - } - temp.push(results[0]) - locations = locations.filter(it => it.where !== key) - } else { - // Didn't find loc that should be in the table. Make a default entry - temp.push(new HitLocations.HitLocation(key, '0', table[key].penalty, table[key].roll)) - } - }) - locations.forEach(it => temp.push(it)) - - let prot = {} - let index = 0 - temp.forEach(it => GURPS.put(prot, it, index++)) - - let saveprot = true - if (!!data.lastImport && !!data.additionalresources.bodyplan && bodyplan != data.additionalresources.bodyplan) { - let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_BODYPLAN) - if (option == 1) { - saveprot = false - } - if (option == 2) { - saveprot = await new Promise((resolve, reject) => { - let d = new Dialog({ - title: 'Hit Location Body Plan', - content: - `Do you want to

Save the current Body Plan (${game.i18n.localize( - 'GURPS.BODYPLAN' + data.additionalresources.bodyplan - )}) or ` + - `

Overwrite it with the Body Plan from the import: (${game.i18n.localize( - 'GURPS.BODYPLAN' + bodyplan - )})?

 `, - buttons: { - save: { - icon: '', - label: 'Save', - callback: () => resolve(false), - }, - overwrite: { - icon: '', - label: 'Overwrite', - callback: () => resolve(true), - }, - }, - default: 'save', - close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. - }) - d.render(true) - }) - } - } - if (saveprot) - return { - 'system.-=hitlocations': null, - 'system.hitlocations': prot, - 'system.additionalresources.bodyplan': bodyplan, - } - else return {} - } - - /** - * - * @param {Array} locations - */ - _getBodyPlan(locations) { - // each key is a "body plan" name like "humanoid" or "quadruped" - let tableNames = Object.keys(HitLocations.hitlocationDictionary) - - // create a map of tableName:count - /** @type {Record} */ - let tableScores = {} - tableNames.forEach(it => (tableScores[it] = 0)) - - // increment the count for a tableScore if it contains the same hit location as "prot" - locations.forEach(function (hitLocation) { - tableNames.forEach(function (tableName) { - if (HitLocations.hitlocationDictionary[tableName].hasOwnProperty(hitLocation.where)) { - tableScores[tableName] = tableScores[tableName] + 1 - } - }) - }) - - // Select the tableScore with the highest score. - let match = -1 - let name = HitLocations.HitLocation.HUMANOID - Object.keys(tableScores).forEach(function (score) { - if (tableScores[score] > match) { - match = tableScores[score] - name = score - } - }) - - // In the case of a tie, select the one whose score is closest to the number of entries - // in the table. - let results = Object.keys(tableScores).filter(it => tableScores[it] === match) - if (results.length > 1) { - let diff = Number.MAX_SAFE_INTEGER - results.forEach(key => { - // find the smallest difference - let table = HitLocations.hitlocationDictionary[key] - if (Object.keys(table).length - match < diff) { - diff = Object.keys(table).length - match - name = key - } - }) - } - - return name - } - - /** - * @param {{ [key: string]: any }} json - * @param {boolean} isFoundryGCS - */ - importEquipmentFromGCSv1(json, isFoundryGCS) { - if (!json) return - let t = this.textFrom - let i = this.intFrom - let f = this.floatFrom - - /** - * @type {Equipment[]} - */ - let temp = [] - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let eqt = new Equipment() - eqt.name = t(j.name) - eqt.count = t(j.count) - eqt.cost = t(j.cost) - eqt.location = t(j.location) - let cstatus = i(j.carried) - eqt.carried = cstatus >= 1 - eqt.equipped = cstatus == 2 - eqt.techlevel = t(j.tl) - eqt.legalityclass = t(j.lc) - eqt.categories = t(j.type) - eqt.uses = t(j.uses) - eqt.maxuses = t(j.maxuses) - eqt.uuid = t(j.uuid) - eqt.parentuuid = t(j.parentuuid) - if (isFoundryGCS) { - eqt.notes = t(j.notes) - eqt.weight = t(j.weight) - } else { - eqt.setNotes(t(j.notes)) - eqt.weight = t(j.weightsum) // GCA sends calculated weight in 'weightsum' - } - eqt.pageRef(t(j.pageref)) - let old = this._findElementIn('equipment.carried', eqt.uuid) - if (!old) old = this._findElementIn('equipment.other', eqt.uuid) - this._migrateOtfsAndNotes(old, eqt) - if (!!old) { - eqt.carried = old.carried - eqt.equipped = old.equipped - eqt.parentuuid = old.parentuuid - if (old.ignoreImportQty) { - eqt.count = old.count - eqt.uses = old.uses - eqt.maxuses = old.maxuses - eqt.ignoreImportQty = true - } - } - temp.push(eqt) - } - } - - // Save the old User Entered Notes. - recurselist(this.system.equipment?.carried, t => { - t.carried = true - if (!!t.save) temp.push(t) - }) // Ensure carried eqt stays in carried - recurselist(this.system.equipment?.other, t => { - t.carried = false - if (!!t.save) temp.push(t) - }) - - temp.forEach(eqt => { - // Remove all entries from inside items because if they still exist, they will be added back in - eqt.contains = {} - eqt.collapsed = {} - }) - - // Put everything in it container (if found), otherwise at the top level - temp.forEach(eqt => { - if (!!eqt.parentuuid) { - let parent = null - parent = temp.find(e => e.uuid === eqt.parentuuid) - if (!!parent) GURPS.put(parent.contains, eqt) - else eqt.parentuuid = '' // Can't find a parent, so put it in the top list - } - }) - - let equipment = { - carried: {}, - other: {}, - } - let cindex = 0 - let oindex = 0 - - temp.forEach(eqt => { - Equipment.calc(eqt) - if (!eqt.parentuuid) { - if (eqt.carried) GURPS.put(equipment.carried, eqt, cindex++) - else GURPS.put(equipment.other, eqt, oindex++) - } - }) - return { - 'system.-=equipment': null, - 'system.equipment': equipment, - } - } - - // Fold a flat array into a hierarchical target object - /** - * @param {any[]} flat - */ - foldList(flat, target = {}) { - flat.forEach(obj => { - if (!!obj.parentuuid) { - const parent = flat.find(o => o.uuid == obj.parentuuid) - if (!!parent) { - if (!parent.contains) parent.contains = {} // lazy init for older characters - GURPS.put(parent.contains, obj) - } else obj.parentuuid = '' // Can't find a parent, so put it in the top list. should never happen with GCS - } - }) - let index = 0 - flat.forEach(obj => { - if (!obj.parentuuid) GURPS.put(target, obj, index++) - }) - return target - } - - /** - * @param {{ [x: string]: Record; }} json - */ - importEncumbranceFromGCSv1(json) { - if (!json) return - let t = this.textFrom - let es = {} - let index = 0 - let cm = 0 - let cd = 0 - for (let i = 0; i < 5; i++) { - let e = new Encumbrance() - e.level = i - let k = 'enc_' + i - let c = t(json[k]) - e.current = c === '1' - k = 'enc' + i - e.key = k - let k2 = k + '_weight' - e.weight = t(json[k2]) - k2 = k + '_move' - e.move = this.intFrom(json[k2]) - k2 = k + '_dodge' - e.dodge = this.intFrom(json[k2]) - if (e.current) { - cm = e.move - cd = e.dodge - } - GURPS.put(es, e, index++) - } - return { - 'system.currentmove': cm, - 'system.currentdodge': cd, - 'system.-=encumbrance': null, - 'system.encumbrance': es, - } - } - - /** - * Copy old OTFs to the new object, and update the displayable notes - * @param {Skill|Spell|Ranged|Melee} oldobj - * @param {Skill|Spell|Ranged|Melee} newobj - */ - _migrateOtfsAndNotes(oldobj = {}, newobj, importvttnotes = '', usagenotes = '') { - if (!!importvttnotes) newobj.notes += (!!newobj.notes ? ' ' : '') + importvttnotes - if (!!usagenotes) newobj.notes += (!!newobj.notes ? ' ' : '') + usagenotes - this._updateOtf('check', oldobj, newobj) - this._updateOtf('during', oldobj, newobj) - this._updateOtf('pass', oldobj, newobj) - this._updateOtf('fail', oldobj, newobj) - if (oldobj.notes?.startsWith(newobj.notes)) - // Must be done AFTER OTFs have been stripped out - newobj.notes = oldobj.notes - if (oldobj.name?.startsWith(newobj.name)) newobj.name = oldobj.name - } - - /** - * Search for specific format OTF in the notes (and vttnotes). - * If we find it in the notes, remove it and replace the notes with the shorter version - */ - _updateOtf(otfkey, oldobj, newobj) { - let objkey = otfkey + 'otf' - let oldotf = oldobj[objkey] - newobj[objkey] = oldotf - var notes, newotf - ;[notes, newotf] = this._removeOtf(otfkey, newobj.notes || '') - if (!!newotf) newobj[objkey] = newotf - newobj.notes = notes.trim() - } - - // Looking for OTFs in text. ex: c:[/qty -1] during:[/anim healing c] - _removeOtf(key, text) { - if (!text) return [text, null] - let otf = null - let found = true - while (found) { - found = false - var start - let patstart = text.toLowerCase().indexOf(key[0] + ':[') - if (patstart < 0) { - patstart = text.toLowerCase().indexOf(key + ':[') - if (patstart < 0) return [text, otf] - else start = patstart + key.length + 2 - } else start = patstart + 3 - let cnt = 1 - let i = start - if (i >= text.length) return [text, otf] - do { - let ch = text[i++] - if (ch == '[') cnt++ - if (ch == ']') cnt-- - } while (i < text.length && cnt > 0) - if (cnt == 0) { - found = true - otf = text.substring(start, i - 1) - let front = text.substring(0, patstart) - let end = text.substr(i) - if ((front == '' || front.endsWith(' ')) && end.startsWith(' ')) end = end.substring(1) - text = front + end - } else return [text, otf] - } - return [text, otf] - } - - /** - * @param {{ [key: string]: any }} json - * @param {boolean} isFoundryGCS - */ - importCombatMeleeFromGCSv1(json, isFoundryGCS) { - if (!json) return - let t = this.textFrom - let melee = {} - let index = 0 - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let oldnote = t(j.notes) - for (let k2 in j.meleemodelist) { - if (k2.startsWith('id-')) { - let j2 = j.meleemodelist[k2] - let m = new Melee() - m.name = t(j.name) - m.st = t(j.st) - m.weight = t(j.weight) - m.techlevel = t(j.tl) - m.cost = t(j.cost) - if (isFoundryGCS) { - m.notes = t(j2.notes) || oldnote - m.pageRef(t(j2.pageref)) - } else - try { - m.setNotes(t(j.text)) - } catch { - console.log(m) - console.log(t(j.text)) - } - m.mode = t(j2.name) - m.import = t(j2.level) - m.damage = t(j2.damage) - m.reach = t(j2.reach) - m.parry = t(j2.parry) - m.block = t(j2.block) - let old = this._findElementIn('melee', false, m.name, m.mode) - this._migrateOtfsAndNotes(old, m, t(j2.vtt_notes)) - - GURPS.put(melee, m, index++) - } - } - } - } - return { - 'system.-=melee': null, - 'system.melee': melee, - } - } - - /** - * @param {{ [key: string]: any }} json - * @param {boolean} isFoundryGCS - */ - importCombatRangedFromGCSv1(json, isFoundryGCS) { - if (!json) return - let t = this.textFrom - let ranged = {} - let index = 0 - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let oldnote = t(j.notes) - for (let k2 in j.rangedmodelist) { - if (k2.startsWith('id-')) { - let j2 = j.rangedmodelist[k2] - let r = new Ranged() - r.name = t(j.name) - r.st = t(j.st) - r.bulk = t(j.bulk) - r.legalityclass = t(j.lc) - r.ammo = t(j.ammo) - if (isFoundryGCS) { - r.notes = t(j2.notes) || oldnote - r.pageRef(t(j2.pageref)) - } else - try { - r.setNotes(t(j.text)) - } catch { - console.log(r) - console.log(t(j.text)) - } - r.mode = t(j2.name) - r.import = t(j2.level) - r.damage = t(j2.damage) - r.acc = t(j2.acc) - let m = r.acc.trim().match(/(\d+)([+-]\d+)/) - if (m) { - r.acc = m[1] - r.notes += ' [' + m[2] + ' ' + i18n('GURPS.acc') + ']' - } - r.rof = t(j2.rof) - r.shots = t(j2.shots) - r.rcl = t(j2.rcl) - let rng = t(j2.range) - r.range = rng - let old = this._findElementIn('ranged', false, r.name, r.mode) - this._migrateOtfsAndNotes(old, r, t(j2.vtt_notes)) - - GURPS.put(ranged, r, index++) - } - } - } - } - return { - 'system.-=ranged': null, - 'system.ranged': ranged, - } - } - - /** - * @param {{ race: Record; height: Record; weight: Record; age: Record; title: Record; player: Record; createdon: Record; modifiedon: Record; religion: Record; birthday: Record; hand: Record; sizemodifier: Record; tl: Record; appearance: Record; }} json - */ - importTraitsfromGCSv1(json) { - if (!json) return - let t = this.textFrom - let ts = {} - ts.race = t(json.race) - ts.height = t(json.height) - ts.weight = t(json.weight) - ts.age = t(json.age) - ts.title = t(json.title) - ts.player = t(json.player) - ts.createdon = t(json.createdon) - ts.modifiedon = t(json.modifiedon) - ts.religion = t(json.religion) - ts.birthday = t(json.birthday) - ts.hand = t(json.hand) - ts.sizemod = t(json.sizemodifier) - ts.techlevel = t(json.tl) - // @GENDER, Eyes: @EYES, Hair: @HAIR, Skin: @SKIN - let a = t(json.appearance) - ts.appearance = a - try { - let x = a.indexOf(', Eyes: ') - if (x >= 0) { - ts.gender = a.substring(0, x) - let y = a.indexOf(', Hair: ') - ts.eyes = a.substring(x + 8, y) - x = a.indexOf(', Skin: ') - ts.hair = a.substring(y + 8, x) - ts.skin = a.substr(x + 8) - } - } catch { - console.log('Unable to parse appearance traits for ') - console.log(this) - } - return { - 'system.-=traits': null, - 'system.traits': ts, - } - } - - // Import the section of the GCS FG XML file. - /** - * @param {{ [key: string]: any }} json - */ - async importAttributesFromCGSv1(json) { - if (!json) return - let i = this.intFrom // shortcut to make code smaller -- I reject your attempt to make the code smaller. Why does it need to be smaller? - let t = this.textFrom - let data = this.system - let att = data.attributes - - // attribute.values will be calculated in calculateDerivedValues() - att.ST.import = i(json.strength) - att.ST.points = i(json.strength_points) - att.DX.import = i(json.dexterity) - att.DX.points = i(json.dexterity_points) - att.IQ.import = i(json.intelligence) - att.IQ.points = i(json.intelligence_points) - att.HT.import = i(json.health) - att.HT.points = i(json.health_points) - att.WILL.import = i(json.will) - att.WILL.points = i(json.will_points) - att.PER.import = i(json.perception) - att.PER.points = i(json.perception_points) - - data.HP.max = i(json.hitpoints) - data.HP.points = i(json.hitpoints_points) - data.FP.max = i(json.fatiguepoints) - data.FP.points = i(json.fatiguepoints_points) - let hp = i(json.hps) - let fp = i(json.fps) - - let saveCurrent = false - if (!!data.lastImport && (data.HP.value != hp || data.FP.value != fp)) { - let option = game.settings.get(settings.SYSTEM_NAME, settings.SETTING_IMPORT_HP_FP) - if (option == 0) { - saveCurrent = true - } - if (option == 2) { - saveCurrent = await new Promise((resolve, reject) => { - let d = new Dialog({ - title: 'Current HP & FP', - content: `Do you want to

Save the current HP (${data.HP.value}) & FP (${data.FP.value}) values or

Overwrite it with the import data, HP (${hp}) & FP (${fp})?

 `, - buttons: { - save: { - icon: '', - label: 'Save', - callback: () => resolve(true), - }, - overwrite: { - icon: '', - label: 'Overwrite', - callback: () => resolve(false), - }, - }, - default: 'save', - close: () => resolve(false), // just assume overwrite. Error handling would be too much work right now. - }) - d.render(true) - }) - } - } - if (!saveCurrent) { - data.HP.value = hp - data.FP.value = fp - } - - let lm = {} - lm.basiclift = t(json.basiclift) - lm.carryonback = t(json.carryonback) - lm.onehandedlift = t(json.onehandedlift) - lm.runningshove = t(json.runningshove) - lm.shiftslightly = t(json.shiftslightly) - lm.shove = t(json.shove) - lm.twohandedlift = t(json.twohandedlift) - - data.basicmove.value = t(json.basicmove) - data.basicmove.points = i(json.basicmove_points) - // data.basicspeed.value = t(json.basicspeed) - data.basicspeed.value = this.floatFrom(json.basicspeed) - - data.basicspeed.points = i(json.basicspeed_points) - data.thrust = t(json.thrust) - data.swing = t(json.swing) - data.currentmove = t(json.move) - data.frightcheck = i(json.frightcheck) - - data.hearing = i(json.hearing) - data.tastesmell = i(json.tastesmell) - data.touch = i(json.touch) - data.vision = i(json.vision) - - return { - 'system.attributes': att, - 'system.HP': data.HP, - 'system.FP': data.FP, - 'system.basiclift': data.basiclift, - 'system.basicmove': data.basicmove, - 'system.basicspeed': data.basicspeed, - 'system.thrust': data.thrust, - 'system.swing': data.swing, - 'system.currentmove': data.currentmove, - 'system.frightcheck': data.frightcheck, - 'system.hearing': data.hearing, - 'system.tastesmell': data.tastesmell, - 'system.touch': data.touch, - 'system.vision': data.vision, - 'system.liftingmoving': lm, - } - } - - // create/update the skills. - // NOTE: For the update to work correctly, no two skills can have the same name. - // When reading data, use "this.system.skills", however, when updating, use "system.skills". - /** - * @param {{ [key: string]: any }} json - * @param {boolean} isFoundryGCS - */ - importSkillsFromGCSv1(json, isFoundryGCS) { - if (!json) return - let temp = [] - let t = this.textFrom /// shortcut to make code smaller - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let sk = new Skill() - sk.name = t(j.name) - sk.type = t(j.type) - sk.import = t(j.level) - if (sk.level == 0) sk.level = '' - sk.points = this.intFrom(j.points) - sk.relativelevel = t(j.relativelevel) - if (isFoundryGCS) { - sk.notes = t(j.notes) - sk.pageRef(t(j.pageref)) - } else sk.setNotes(t(j.text)) - if (!!j.pageref) sk.pageRef(t(j.pageref)) - sk.uuid = t(j.uuid) - sk.parentuuid = t(j.parentuuid) - let old = this._findElementIn('skills', sk.uuid) - this._migrateOtfsAndNotes(old, sk, t(j.vtt_notes)) - - temp.push(sk) - } - } - return { - 'system.-=skills': null, - 'system.skills': this.foldList(temp), - } - } - - // create/update the spells. - // NOTE: For the update to work correctly, no two spells can have the same name. - // When reading data, use "this.system.spells", however, when updating, use "system.spells". - /** - * @param {{ [key: string]: any }} json - * @param {boolean} isFoundryGCS - */ - importSpellsFromGCSv1(json, isFoundryGCS) { - if (!json) return - let temp = [] - let t = this.textFrom /// shortcut to make code smaller - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let sp = new Spell() - sp.name = t(j.name) - sp.class = t(j.class) - sp.college = t(j.college) - if (isFoundryGCS) { - sp.cost = t(j.cost) - sp.maintain = t(j.maintain) - sp.difficulty = t(j.difficulty) - sp.relativelevel = t(j.relativelevel) - sp.notes = t(j.notes) - } else { - let cm = t(j.costmaintain) - let i = cm.indexOf('/') - if (i >= 0) { - sp.cost = cm.substring(0, i) - sp.maintain = cm.substr(i + 1) - } else { - sp.cost = cm - } - sp.setNotes(t(j.text)) - } - sp.pageRef(t(j.pageref)) - sp.duration = t(j.duration) - sp.points = t(j.points) - sp.casttime = t(j.time) - sp.import = t(j.level) - sp.uuid = t(j.uuid) - sp.parentuuid = t(j.parentuuid) - let old = this._findElementIn('spells', sp.uuid) - this._migrateOtfsAndNotes(old, sp, t(j.vtt_notes)) - temp.push(sp) - } - } - return { - 'system.-=spells': null, - 'system.spells': this.foldList(temp), - } - } - - /** - * @param {{ [key: string]: any }} adsjson - * @param {{ [key: string]: any }} disadsjson - */ - importAdsFromGCA(adsjson, disadsjson) { - /** @type {Advantage[]} */ - let list = [] - this.importBaseAdvantages(list, adsjson) - this.importBaseAdvantages(list, disadsjson) - return { - 'system.-=ads': null, - 'system.ads': this.foldList(list), - } - } - - /** - * @param {Advantage[]} datalist - * @param {{ [key: string]: any }} json - */ - importBaseAdvantages(datalist, json) { - if (!json) return - let t = this.textFrom /// shortcut to make code smaller - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let a = new Advantage() - a.name = t(j.name) - a.points = this.intFrom(j.points) - a.setNotes(t(j.text)) - a.pageRef(t(j.pageref) || a.pageref) - a.uuid = t(j.uuid) - a.parentuuid = t(j.parentuuid) - let old = this._findElementIn('ads', a.uuid) - this._migrateOtfsAndNotes(old, a, t(j.vtt_notes)) - datalist.push(a) - } - } - } - - // In the new GCS import, all ads/disad/quirks/perks are in one list. - /** - * @param {{ [key: string]: any }} json - */ - importAdsFromGCSv2(json) { - let t = this.textFrom /// shortcut to make code smaller - let temp = [] - for (let key in json) { - if (key.startsWith('id-')) { - // Allows us to skip over junk elements created by xml->json code, and only select the skills. - let j = json[key] - let a = new Advantage() - a.name = t(j.name) - a.points = this.intFrom(j.points) - a.note = t(j.notes) - a.userdesc = t(j.userdesc) - a.notes = '' - if (!!a.note && !!a.userdesc) a.notes = a.note + '\n' + a.userdesc - else if (!!a.note) a.notes = a.note - else if (!!a.userdesc) a.notes = a.userdesc - a.pageRef(t(j.pageref)) - a.uuid = t(j.uuid) - a.parentuuid = t(j.parentuuid) - let old = this._findElementIn('ads', a.uuid) - this._migrateOtfsAndNotes(old, a, t(j.vtt_notes)) - temp.push(a) - } - } - return { - 'system.-=ads': null, - 'system.ads': this.foldList(temp), - } - } - - /** - * Adds any assigned resource trackers to the actor data and sheet. - */ - async setResourceTrackers() { - // find those with non-blank slots - let templates = ResourceTrackerManager.getAllTemplates().filter(it => !!it.slot) - - for (const template of templates) { - // find the matching data on this actor - let index = zeroFill(template.slot, 4) - let path = `additionalresources.tracker.${index}` - let tracker = foundry.utils.getProperty(this, 'system.' + path) - - while (!tracker) { - await this.addTracker() - tracker = foundry.utils.getProperty(this, 'system.' + path) - } - - // skip if already set - if (!!tracker && tracker.name === template.tracker.name) { - return - } - - // if not blank, don't overwrite - if (!!tracker && !!tracker.name) { - ui.notifications?.warn( - `Will not overwrite Tracker ${template.slot} as its name is set to ${tracker.name}. Create Tracker for ${template.tracker.name} failed.` - ) - return - } - - await this.applyTrackerTemplate(path, template) - } - } - - /** - * Update this tracker slot with the contents of the template. - * @param {String} path JSON data path to the tracker; must start with 'additionalresources.tracker.' - * @param {*} template to apply - */ - async applyTrackerTemplate(path, template) { - // is there an initializer? If so calculate its value - let value = template.tracker.value - if (!!template.initialValue) { - value = parseInt(template.initialValue, 10) - if (Number.isNaN(value)) { - // try to use initialValue as a path to another value - value = foundry.utils.getProperty(this, 'system.' + template.initialValue) - } - } - template.tracker.max = value - template.tracker.value = template.tracker.isDamageTracker ? template.tracker.min : value - - // remove whatever is there - await this.clearTracker(path) - - // add the new tracker - /** @type {{ [key: string]: any }} */ - let update = {} - update[`system.${path}`] = template.tracker - await this.update(update) - } - - /** - * Overwrites the tracker pointed to by the path with default/blank values. - * @param {String} path JSON data path to the tracker; must start with 'additionalresources.tracker.' - */ - async clearTracker(path) { - // verify that this is a Tracker - const prefix = 'additionalresources.tracker.' - if (!path.startsWith(prefix)) throw `Invalid actor data path, actor=[${this.id}] path=[${path}]` - - /** @type {{[key: string]: string}} */ - let update = {} - update[`system.${path}`] = { - name: '', - alias: '', - pdf: '', - max: 0, - min: 0, - value: 0, - isDamageTracker: false, - isDamageType: false, - initialValue: '', - thresholds: [], - } - await this.update(update) - } - - /** - * Removes the indicated tracker from the object, reindexing the keys. - * @param {String} path JSON data path to the tracker; must start with 'additionalresources.tracker.' - */ - async removeTracker(path) { - this.ignoreRender = true - const prefix = 'additionalresources.tracker.' - - // verify that this is a Tracker - if (!path.startsWith(prefix)) throw `Invalid actor data path, actor=[${this.id}] path=[${path}]` - - let key = path.replace(prefix, '') - let trackerData = this.system.additionalresources.tracker - delete trackerData[key] - let trackers = objectToArray(trackerData) - let data = arrayToObject(trackers) - - // remove all trackers - await this.update({ 'system.additionalresources.-=tracker': null }) - // add the new "array" of trackers - if (data) this.update({ 'system.additionalresources.tracker': data }) - else this.update('system.additionalresources.tracker', {}) - - this._forceRender() - } - - async addTracker() { - this.ignoreRender = true - - let trackerData = { name: '', value: 0, min: 0, max: 0, points: 0 } - let data = GurpsActor.addTrackerToDataObject(this.system, trackerData) - - await this.update({ 'system.additionalresources.-=tracker': null }) - await this.update({ 'system.additionalresources.tracker': data }) - - this._forceRender() - } - - static addTrackerToDataObject(data, trackerData) { - let trackers = GurpsActor.getTrackersAsArray(data) - trackers.push(trackerData) - return arrayToObject(trackers) - } - - static getTrackersAsArray(data) { - let trackerArray = data.additionalresources.tracker - if (!trackerArray) trackerArray = {} - return objectToArray(trackerArray) - } - - async setMoveDefault(value) { - this.ignoreRender = true - let move = this.system.move - for (const key in move) { - move[key].default = value === key - } - await this.update({ 'system.-=move': null }) - await this.update({ 'system.move': move }) - this._forceRender() - } - - // --- Functions to handle events on actor --- + // --- Functions to handle events on actor --- /** * @param {any[]} damageData @@ -3696,7 +1261,7 @@ export class GurpsActor extends Actor { delete item.editingActor this.ignoreRender = true if (item.id) await this._removeItemAdditions(item.id) - let _data = GurpsItem.asGurpsItem(item).system + // let _data = GurpsItem.asGurpsItem(item).system let oldkey = this._findEqtkeyForId('itemid', item.id) var oldeqt if (!!oldkey) oldeqt = foundry.utils.getProperty(this, oldkey) @@ -3768,11 +1333,11 @@ export class GurpsActor extends Actor { if (!!_data.system) _data = _data.system if (!!_data.eqt.parentuuid) { var found - recurselist(this.system.equipment.carried, (e, k, d) => { + recurselist(this.system.equipment.carried, (e, k, _d) => { if (e.uuid == _data.eqt.parentuuid) found = 'system.equipment.carried.' + k }) if (!found) - recurselist(this.system.equipment.other, (e, k, d) => { + recurselist(this.system.equipment.other, (e, k, _d) => { if (e.uuid == _data.eqt.parentuuid) found = 'system.equipment.other.' + k }) if (!!found) { @@ -3850,8 +1415,10 @@ export class GurpsActor extends Actor { if (carried && equipped) await this._addItemAdditions(item, eqtkey) } - for (const k in eqt.contains) await this._updateEqtStatus(eqt.contains[k], eqtkey + '.contains.' + k, carried, equipped) - for (const k in eqt.collapsed) await this._updateEqtStatus(eqt.collapsed[k], eqtkey + '.collapsed.' + k, carried, equipped) + for (const k in eqt.contains) + await this._updateEqtStatus(eqt.contains[k], eqtkey + '.contains.' + k, carried, equipped) + for (const k in eqt.collapsed) + await this._updateEqtStatus(eqt.collapsed[k], eqtkey + '.collapsed.' + k, carried, equipped) } /** @@ -3862,7 +1429,7 @@ export class GurpsActor extends Actor { async _addItemElement(itemData, eqtkey, key) { let found = false // @ts-ignore - recurselist(this.system[key], (e, k, d) => { + recurselist(this.system[key], (e, _k, _d) => { if (e.itemid == itemData._id) found = true }) if (found) return @@ -3938,7 +1505,7 @@ export class GurpsActor extends Actor { while (!!found) { found = false let list = foundry.utils.getProperty(this, key) - recurselist(list, (e, k, d) => { + recurselist(list, (e, k, _d) => { if (e.itemid == itemid) found = k }) if (!!found) { @@ -4023,7 +1590,7 @@ export class GurpsActor extends Actor { await this.updateParentOf(srckey, false) } let k = targetkey + '.contains.' + zeroFill(0) - let targ = foundry.utils.getProperty(this, targetkey) + // let targ = foundry.utils.getProperty(this, targetkey) await this.updateItemAdditionsBasedOn(object, targetkey) await GURPS.insertBeforeKey(this, k, object) @@ -4108,7 +1675,6 @@ export class GurpsActor extends Actor { this._forceRender() return true } - return false } /** @@ -4147,7 +1713,7 @@ export class GurpsActor extends Actor { get hitLocationsWithDR() { let myhitlocations = [] let table = this._hitLocationRolls - for (const [key, value] of Object.entries(this.system.hitlocations)) { + for (const [_key, value] of Object.entries(this.system.hitlocations)) { let rollText = value.roll if (!value.roll && !!table[value.where]) // Can happen if manually edited @@ -4197,7 +1763,7 @@ export class GurpsActor extends Actor { let txt = '' if (!!this.system.melee && !!this.system.equipment?.carried) Object.values(this.system.melee).forEach(melee => { - recurselist(this.system.equipment.carried, (e, k, d) => { + recurselist(this.system.equipment.carried, (e, _k, _d) => { if (!!e && !val && e.equipped && !!melee.name.match(makeRegexPatternFrom(e.name, false))) { let t = parseInt(melee[key]) if (!isNaN(t)) { @@ -4252,10 +1818,10 @@ export class GurpsActor extends Actor { * @param {string} pattern */ findEquipmentByName(pattern, otherFirst = false) { - while (pattern[0] == '/') pattern = pattern.substr(1) + while (pattern[0] == '/') pattern = pattern.substring(1) pattern = makeRegexPatternFrom(pattern, false) let pats = pattern - .substr(1) // remove the ^ from the beginning of the string + .substring(1) // remove the ^ from the beginning of the string .split('/') .map(e => new RegExp('^' + e, 'i')) // and apply it to each pattern /** @@ -4321,7 +1887,7 @@ export class GurpsActor extends Actor { if (best != prev) { for (let key in encs) { let enc = encs[key] - let t = 'system.encumbrance.' + key + '.current' + // let t = 'system.encumbrance.' + key + '.current' if (key === best) { enc.current = true this.system.currentmove = parseInt(enc.currentmove) diff --git a/module/actor/effect-modifier-control.js b/module/actor/effect-modifier-control.js index 85d82b977..d41d4817a 100644 --- a/module/actor/effect-modifier-control.js +++ b/module/actor/effect-modifier-control.js @@ -124,7 +124,7 @@ export class EffectModifierControl { this._ui.closeApp(closeOptions) } } - + refresh() { this._ui?.render(true) } diff --git a/module/actor/effect-modifier-popout.js b/module/actor/effect-modifier-popout.js index e1597ecc8..0e35de89e 100644 --- a/module/actor/effect-modifier-popout.js +++ b/module/actor/effect-modifier-popout.js @@ -56,7 +56,9 @@ export class EffectModifierPopout extends Application { : [] let mod = this.calculateRange(this.getToken(), target) if (mod && mod.modifier !== 0) - result.targetmodifiers.push(gurpslink(`[${mod.modifier} range to target ${target.actor?.name} (${mod.yards} ${canvas.scene.grid.units})]`)) + result.targetmodifiers.push( + gurpslink(`[${mod.modifier} range to target ${target.actor?.name} (${mod.yards} ${canvas.scene.grid.units})]`) + ) // Add the range to the target @@ -79,7 +81,7 @@ export class EffectModifierPopout extends Application { // const ruler = new Ruler() as Ruler & { totalDistance: number } const ruler = new RulerGURPS(game.user) - ruler._state = Ruler.STATES.MEASURING; + ruler._state = Ruler.STATES.MEASURING ruler.waypoints = [{ x: token1.x, y: token1.y }] ruler.measure({ x: token2.x, y: token2.y }, { gridSpaces: true }) const horizontalDistance = ruler.totalDistance @@ -90,7 +92,7 @@ export class EffectModifierPopout extends Application { const yards = ruler.convert_to_yards(dist, canvas.scene.grid.units) return { yards: Math.ceil(dist), - modifier: ruler.yardsToSpeedRangePenalty(yards) + modifier: ruler.yardsToSpeedRangePenalty(yards), } } diff --git a/module/actor/resource-tracker-editor.js b/module/actor/resource-tracker-editor.js index 1d1d906a4..5834f0928 100644 --- a/module/actor/resource-tracker-editor.js +++ b/module/actor/resource-tracker-editor.js @@ -57,7 +57,7 @@ export class ResourceTrackerEditor extends Application { * By default, do nothing. Each specific use will need its own update method. * @param {*} html */ - async _updateTracker(html) { } + async _updateTracker(html) {} /** @override */ activateListeners(html) { diff --git a/module/chat/anim.js b/module/chat/anim.js index ab9e5d066..16c6034b1 100644 --- a/module/chat/anim.js +++ b/module/chat/anim.js @@ -182,24 +182,23 @@ export class AnimChatProcessor extends ChatProcessor { async awaitClick(line) { if (line.match(/@\d+,\d+/)) { - console.log("Duplicate request for click: " + line) + console.log('Duplicate request for click: ' + line) return } ui.notifications.warn('Please click target') this.send() GURPS.IgnoreTokenSelect = true - + try { - const location = await warpgate.crosshairs.show( - { - interval: 0, - size: 1, - drawOutline: false, - lockSize: true, - labelOffset: { x:0, y:-150 }, - icon: 'icons/skills/targeting/crosshair-bars-yellow.webp', - //icon: 'icons/magic/symbols/runes-triangle-blue.webp', - label: 'Click to target', + const location = await warpgate.crosshairs.show({ + interval: 0, + size: 1, + drawOutline: false, + lockSize: true, + labelOffset: { x: 0, y: -150 }, + icon: 'icons/skills/targeting/crosshair-bars-yellow.webp', + //icon: 'icons/magic/symbols/runes-triangle-blue.webp', + label: 'Click to target', }) let grid_size = canvas.scene.grid.size canvas.tokens.targetObjects({ @@ -213,7 +212,7 @@ export class AnimChatProcessor extends ChatProcessor { line = line + ' @' + parseInt(location.x) + ',' + parseInt(location.y) this.registry.processLine(line) return - } catch (error) { + } catch (error) { GURPS.IgnoreTokenSelect = false console.log(error) } diff --git a/module/chat/chat-processors.js b/module/chat/chat-processors.js index ab6fffc36..9329c38ff 100644 --- a/module/chat/chat-processors.js +++ b/module/chat/chat-processors.js @@ -26,6 +26,7 @@ import SlamChatProcessor from '../chat/slam.js' import TrackerChatProcessor from '../chat/tracker.js' import { AnimChatProcessor } from '../chat/anim.js' import Maneuvers from '../actor/maneuver.js' +import { ActorImporter } from '../actor/actor-importer.js' export default function RegisterChatProcessors() { ChatProcessors.registerProcessor(new RollAgainstChatProcessor()) @@ -261,7 +262,7 @@ class ReimportChatProcessor extends ChatProcessor { if (!!actor) actors.push(actor) } if (actornames.length == 0) actors = allPlayerActors - actors.forEach(e => e.importCharacter()) + actors.forEach(e => new ActorImporter(e).importActor()) } } diff --git a/module/effects/effects.js b/module/effects/effects.js index d18bc6596..32b911c92 100644 --- a/module/effects/effects.js +++ b/module/effects/effects.js @@ -32,7 +32,7 @@ export class StatusEffect { this._statusEffects[key] = value } // Hack to add back in 'dead' status (to allow dead icon to show on token) - this._statusEffects['dead'] = {id: 'dead', name: 'EFFECT.StatusDead', img: 'icons/svg/skull.svg'} + this._statusEffects['dead'] = { id: 'dead', name: 'EFFECT.StatusDead', img: 'icons/svg/skull.svg' } // replace standard effects CONFIG.statusEffects = this.effects() diff --git a/module/journal.js b/module/journal.js index 58837ce8d..6a3389713 100644 --- a/module/journal.js +++ b/module/journal.js @@ -5,8 +5,8 @@ import { gurpslink } from '../module/utilities/gurpslink.js' export default class GurpsJournalEntry { static ready() { Hooks.on('renderJournalPageSheet', GurpsJournalEntry._renderJournalPageSheet) -// Hooks.on('getJournalSheetEntryContext', GurpsJournalEntry._getJournalSheetEntryContext) -// Hooks.on('renderJournalSheet', GurpsJournalEntry._renderJournalSheet) + // Hooks.on('getJournalSheetEntryContext', GurpsJournalEntry._getJournalSheetEntryContext) + // Hooks.on('renderJournalSheet', GurpsJournalEntry._renderJournalSheet) } /** @@ -22,7 +22,7 @@ export default class GurpsJournalEntry { if (!!h && h.length > 0) { //h.html(gurpslink(h[0].innerHTML)) GurpsWiring.hookupAllEvents(html) - + const dropHandler = function (event, app, options) { event.preventDefault() if (event.originalEvent) event = event.originalEvent @@ -43,16 +43,18 @@ export default class GurpsJournalEntry { let content = app.document.text.content if (content) cmd = '
' + cmd app.document.update({ 'text.content': content + cmd }) - } } - html.parent().parent().on('drop', event => dropHandler(event, app, options)) + html + .parent() + .parent() + .on('drop', event => dropHandler(event, app, options)) } }, 10) } - -/* static _renderJournalSheet(app, html, options) { + + /* static _renderJournalSheet(app, html, options) { console.log(app) } diff --git a/module/modifier-bucket/bucket-app.js b/module/modifier-bucket/bucket-app.js index 1e2a4f537..93590a424 100755 --- a/module/modifier-bucket/bucket-app.js +++ b/module/modifier-bucket/bucket-app.js @@ -236,7 +236,8 @@ class ModifierStack { reason = reason.replace('(' + i18n('GURPS.equipmentUserCreated') + ')', '').trim() // Remove User Created tag let i = list.findIndex(e => e.desc == reason && !e.desc.match(/\* *Cost/i)) // Don't double up on *Costs modifiers... so they will pay the full cost if (i > -1) { - if (replace) list.splice(i, 1) // only used by range modifier + if (replace) + list.splice(i, 1) // only used by range modifier else oldmod = list[i] // Must modify list (cannot use filter()) } let m = (mod + '').match(/([+-])?@margin/i) diff --git a/module/modifier-bucket/resolve-diceroll-app.js b/module/modifier-bucket/resolve-diceroll-app.js index abb5fc664..e7491aa8f 100644 --- a/module/modifier-bucket/resolve-diceroll-app.js +++ b/module/modifier-bucket/resolve-diceroll-app.js @@ -119,7 +119,7 @@ export default class ResolveDiceRoll extends Application { _applyCallback() { for (const diceTerm of this.diceTerms) { let result = this.getValues(diceTerm) - result.forEach( n => diceTerm.term.results.push( { active: true, result: n} )) + result.forEach(n => diceTerm.term.results.push({ active: true, result: n })) // diceTerm.term._loaded = result } // @ts-ignore diff --git a/module/pdf-refs.js b/module/pdf-refs.js index a41c3324f..629250dc3 100644 --- a/module/pdf-refs.js +++ b/module/pdf-refs.js @@ -123,8 +123,7 @@ export function handlePdf(links) { if (url) // url = 'http://www.warehouse23.com/products?taxons%5B%5D=558398545-sb' // The main GURPS page window.open(url, '_blank') - else - ui.notifications?.warn("Unable to match book code '" + book + "'.") + else ui.notifications?.warn("Unable to match book code '" + book + "'.") } }) } diff --git a/module/pdf/edit.js b/module/pdf/edit.js index 33e6373ef..815978e8e 100644 --- a/module/pdf/edit.js +++ b/module/pdf/edit.js @@ -1,10 +1,10 @@ export class PDFEditorSheet extends JournalPDFPageSheet { - constructor(object, options = { pageNumber: 1 }) { - super(object, options) - } + constructor(object, options = { pageNumber: 1 }) { + super(object, options) + } - get template() { - // return `systems/gurps/templates/pdf/edit.hbs` - return `systems/gurps/templates/pdf/${this.isEditable ? "edit" : "view"}.hbs` - } + get template() { + // return `systems/gurps/templates/pdf/edit.hbs` + return `systems/gurps/templates/pdf/${this.isEditable ? 'edit' : 'view'}.hbs` + } } diff --git a/module/utilities/gurpslink.js b/module/utilities/gurpslink.js index 281df38d5..d08c7e338 100644 --- a/module/utilities/gurpslink.js +++ b/module/utilities/gurpslink.js @@ -29,7 +29,7 @@ export function gurpslink(str, clrdmods = true, returnActions = false) { i = -1 found = -1 } - if (depth == -1) depth = 0 // we reset to starting condition after second ']' from OTF parse + if (depth == -1) depth = 0 // we reset to starting condition after second ']' from OTF parse } } if (returnActions === true) return actions diff --git a/styles/apps.css b/styles/apps.css index 86999b990..3a3202e6b 100644 --- a/styles/apps.css +++ b/styles/apps.css @@ -34,14 +34,17 @@ Global Override body { left: 0; } -.list_note>textarea { +.list_note > textarea { min-height: 3em; } /* GURPS App CSS */ .gga-app { justify-items: center; - background: url(/systems/gurps/icons/hex2.webp) repeat, url(/ui/parchment.jpg) repeat, #dcdcd0; + background: + url(/systems/gurps/icons/hex2.webp) repeat, + url(/ui/parchment.jpg) repeat, + #dcdcd0; color: black; } @@ -78,11 +81,11 @@ Global Override body { align-items: center; } -.gga-app .icon-prefix>input { +.gga-app .icon-prefix > input { padding-left: 2.2em; } -.gga-app .icon-prefix>span { +.gga-app .icon-prefix > span { position: absolute; left: 0; width: 2em; @@ -106,7 +109,7 @@ Global Override body { height: 15em; } -.gga-app .img-display>img { +.gga-app .img-display > img { display: block; height: 100%; opacity: 0; @@ -131,21 +134,21 @@ Global Override body { } .gga-group, -#calculation-results>div { +#calculation-results > div { border-right: 1px solid #999; height: 100%; padding: 0 0.5em; } -#calculation-results>div:first-child { +#calculation-results > div:first-child { padding-left: 0; } -#calculation-results>div:last-child { +#calculation-results > div:last-child { padding-right: 0; } -#calculation-results>div:last-child, +#calculation-results > div:last-child, .gga-group:last-child { border: none; } @@ -203,8 +206,8 @@ Global Override body { padding-bottom: 0.5em; } -.gga-group .shaded-group h4+aside, -.gga-group h4+aside { +.gga-group .shaded-group h4 + aside, +.gga-group h4 + aside { margin-top: -0.5em; } @@ -215,7 +218,7 @@ Global Override body { } /* striped table row appearance */ -.shaded-group>div:nth-child(odd), +.shaded-group > div:nth-child(odd), .gga-group .shaded { background-color: rgba(0, 0, 0, 0.1); } @@ -239,8 +242,8 @@ Global Override body { text-align: left; } -.grid-2col>*, -.gurps-3col>* { +.grid-2col > *, +.gurps-3col > * { align-self: center; height: 100%; display: flex; @@ -252,9 +255,9 @@ Global Override body { /* striped table row appearance */ /* .gurps-2col > *:nth-child(4n + 3), .gurps-2col > *:nth-child(4n + 4), */ -.gurps-3col>*:nth-of-type(6n + 4), -.gurps-3col>*:nth-of-type(6n + 5), -.gurps-3col>*:nth-of-type(6n + 6) { +.gurps-3col > *:nth-of-type(6n + 4), +.gurps-3col > *:nth-of-type(6n + 5), +.gurps-3col > *:nth-of-type(6n + 6) { background-color: rgba(0, 0, 0, 0.1); } @@ -264,23 +267,23 @@ Global Override body { grid-template-columns: auto 1fr min-content; } -.gurps-radio-col>*:nth-child(3n + 3) { +.gurps-radio-col > *:nth-child(3n + 3) { text-align: end; padding-right: 0.5em; flex-flow: nowrap; justify-content: flex-end; } -.gurps-radio-col>*:nth-child(3n + 2) { +.gurps-radio-col > *:nth-child(3n + 2) { text-align: center; } /* Apply Damage Dialog: Apply buttons panel */ -.gga-group .apply-results>* { +.gga-group .apply-results > * { margin-bottom: 0.2em; } -.gga-group .apply-results>*:last-child { +.gga-group .apply-results > *:last-child { margin-bottom: 0; } @@ -298,23 +301,23 @@ Global Override body { font-size: 12px; } -.gga-group .results-table>div:nth-child(3n + 1) { +.gga-group .results-table > div:nth-child(3n + 1) { text-transform: uppercase; font-size: smaller; } -.gga-group .results-table>div:nth-child(3n + 1), -.gga-group .results-table>div:nth-child(3n + 2) { +.gga-group .results-table > div:nth-child(3n + 1), +.gga-group .results-table > div:nth-child(3n + 2) { text-align: end; padding-right: 0.5em; } -.gga-group .results-table>div:nth-child(3n + 2) { +.gga-group .results-table > div:nth-child(3n + 2) { font-weight: bolder; font-size: small; } -.gga-group .results-table>div:nth-child(3n + 3) { +.gga-group .results-table > div:nth-child(3n + 3) { text-align: start; justify-content: center; padding-left: 1em; @@ -326,7 +329,7 @@ Global Override body { margin-top: 5px; } */ -.modtooltip .gga-group+.gga-group { +.modtooltip .gga-group + .gga-group { margin: unset; } @@ -356,8 +359,8 @@ Global Override body { grid-template-columns: 1fr 1fr; } -.gga-group .label-value-row>*:nth-child(4n + 3), -.gga-group .label-value-row>*:nth-child(4n + 4) { +.gga-group .label-value-row > *:nth-child(4n + 3), +.gga-group .label-value-row > *:nth-child(4n + 4) { background-color: rgba(0, 0, 0, 0.1); } @@ -417,12 +420,12 @@ ul#result-effects li { /* font-family: 'Font Awesome 5 Free', Roboto, sans-serif; */ } -[name='result-effect']>div { +[name='result-effect'] > div { display: flex; align-items: center; } -[name='result-effect']>div div:first-child { +[name='result-effect'] > div div:first-child { flex-grow: 1; } @@ -513,7 +516,7 @@ ul#result-effects li { /* transition: all 0.25s ease-in-out; */ } -.toggle:checked+.label-toggle+.collapsible-content { +.toggle:checked + .label-toggle + .collapsible-content { max-height: 130vh; } @@ -530,7 +533,7 @@ ul#result-effects li { float: right; } -.damage-message .toggle:checked+.label-toggle:after { +.damage-message .toggle:checked + .label-toggle:after { font: normal normal normal 12px/1; font-weight: 900; content: '\f077'; @@ -566,7 +569,7 @@ ul#result-effects li { float: right; } -.gga-chat-message .toggle:checked+.label-toggle:after { +.gga-chat-message .toggle:checked + .label-toggle:after { font: normal normal normal 12px/1; /* font-family: 'Font Awesome 5 Free'; */ font-weight: 900; @@ -590,8 +593,8 @@ ul#result-effects li { padding-right: 4px; } -.gga-app .collapsible-wrapper .collapsible-content .content-inner>*:nth-child(even), -.gga-group .collapsible-content>*:nth-child(even) { +.gga-app .collapsible-wrapper .collapsible-content .content-inner > *:nth-child(even), +.gga-group .collapsible-content > *:nth-child(even) { background: rgba(255, 255, 255, 0.25); } @@ -604,13 +607,15 @@ ul#result-effects li { padding-top: 2px; } -.gga-group .options-drawer .toggle:checked+.label-toggle+.collapsible-content, +.gga-group .options-drawer .toggle:checked + .label-toggle + .collapsible-content, .gga-app .collapsible-wrapper .collapsible-content { - box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.3) inset, 0px 1px 3px rgba(0, 0, 0, 0.3) inset, + box-shadow: + 1px 1px 3px rgba(0, 0, 0, 0.3) inset, + 0px 1px 3px rgba(0, 0, 0, 0.3) inset, 0px 1px 3px rgba(0, 0, 0, 0.3) inset; } -.gga-group .options-drawer .toggle:checked+.label-toggle+.collapsible-content { +.gga-group .options-drawer .toggle:checked + .label-toggle + .collapsible-content { max-height: 130vh; } @@ -628,7 +633,7 @@ ul#result-effects li { background: rgba(255, 255, 240, 0.3); } -.gga-app button.with-icon>i>span { +.gga-app button.with-icon > i > span { /* font-family: 'Font Awesome 5 Free', Roboto, sans-serif; */ font-weight: 400; } @@ -657,7 +662,9 @@ ul#result-effects li { .dragging { outline: 5px auto -webkit-focus-ring-color; - box-shadow: 0 0 2px 3px #78aeda, 0 0 2px #78aeda inset; + box-shadow: + 0 0 2px 3px #78aeda, + 0 0 2px #78aeda inset; border-radius: 3px; background-color: rgba(240, 128, 128, 0.6); } @@ -698,7 +705,9 @@ ul#result-effects li { border-radius: 6px; font-weight: normal; text-shadow: none; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -1px rgba(0, 0, 0, 0.3); + box-shadow: + 0 4px 6px -1px rgba(0, 0, 0, 0.5), + 0 2px 4px -1px rgba(0, 0, 0, 0.3); /* Position the tooltip text */ position: absolute; @@ -776,13 +785,13 @@ ul#result-effects li { left: calc(100% - 35px); } -#notes .tooltiptext.gga-manual>img, -#ranged .tooltiptext.gga-manual>img, -#melee .tooltiptext.gga-manual>img, -#advantages .tooltiptext.gga-manual>img, -#skills .tooltiptext.gga-manual>img, -#spells .tooltiptext.gga-manual>img, -.equipmentlist .tooltiptext.gga-manual>img { +#notes .tooltiptext.gga-manual > img, +#ranged .tooltiptext.gga-manual > img, +#melee .tooltiptext.gga-manual > img, +#advantages .tooltiptext.gga-manual > img, +#skills .tooltiptext.gga-manual > img, +#spells .tooltiptext.gga-manual > img, +.equipmentlist .tooltiptext.gga-manual > img { border: none; max-height: 100px; } @@ -862,7 +871,7 @@ ul#result-effects li { box-shadow: 0 0 5px red; } -#resources>*:first-child { +#resources > *:first-child { border-bottom: 1px solid white; } @@ -902,8 +911,8 @@ ul#result-effects li { border-right: 1px solid black; } -.resource-editor>*, -.tracked-resource>* { +.resource-editor > *, +.tracked-resource > * { margin: 0 0.25rem 0.25rem 0.25rem; } @@ -948,13 +957,13 @@ ul#result-effects li { text-align: center; } -.tracked-resource .spinner>button:first-of-type { +.tracked-resource .spinner > button:first-of-type { border-top-right-radius: 0; border-bottom-right-radius: 0; border-right: none; } -.tracked-resource .spinner>button:nth-of-type(2) { +.tracked-resource .spinner > button:nth-of-type(2) { border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: none; @@ -964,7 +973,7 @@ ul#result-effects li { margin-bottom: 0.15rem; } -.tracked-resource .spinner>button:last-of-type:not(.no-gap) { +.tracked-resource .spinner > button:last-of-type:not(.no-gap) { margin-left: 0.15rem; } @@ -1161,7 +1170,7 @@ active-effects-list .section h3 { cursor: pointer; } -.tracked-resource.inactive .condition-block>* { +.tracked-resource.inactive .condition-block > * { color: grey; } @@ -1275,7 +1284,9 @@ select#maneuver option { font-size: var(--font-size-smaller); min-inline-size: max-content; background-color: white; - box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -1px rgba(0, 0, 0, 0.3); + box-shadow: + 0 4px 6px -1px rgba(0, 0, 0, 0.5), + 0 2px 4px -1px rgba(0, 0, 0, 0.3); border: none; border-radius: 3px; } @@ -1429,7 +1440,7 @@ button.equipmentbutton:last-child { margin-left: 8px; } -.navigation-view>span:before { +.navigation-view > span:before { content: '\f101'; /* this is your text. You can also use UTF-8 character codes as I do here */ /* font-family: 'Font Awesome 5 Free', Roboto, sans-serif; */ @@ -1437,18 +1448,18 @@ button.equipmentbutton:last-child { color: white; } -.navigate-area input:checked+.navigate-bar>.navigation-view>span:before { +.navigate-area input:checked + .navigate-bar > .navigation-view > span:before { content: '\f100'; /* font-family: 'Font Awesome 5 Free', Roboto, sans-serif; */ font-weight: 900; color: white; } -.navigate-area input:checked+.navigate-bar { +.navigate-area input:checked + .navigate-bar { width: fit-content; } -.navigate-area input:checked+.navigate-bar>.navigate-container { +.navigate-area input:checked + .navigate-bar > .navigate-container { width: 0; overflow: hidden; } @@ -1584,7 +1595,7 @@ button.equipmentbutton:last-child { } } -#ui-bottom>div { +#ui-bottom > div { justify-content: unset; } @@ -1680,7 +1691,7 @@ button.equipmentbutton:last-child { text-overflow: ellipsis; } -.modifierbucket #current-actor>span { +.modifierbucket #current-actor > span { color: gold; background-color: black; } @@ -1783,7 +1794,7 @@ button.equipmentbutton:last-child { height: 100%; } -#modtooltipleftbottom>h4 { +#modtooltipleftbottom > h4 { background-color: darkred; } @@ -1802,8 +1813,8 @@ button.equipmentbutton:last-child { padding: 0 5px; } -#modtooltipright>div>*, -#modtooltipcenter>div>* { +#modtooltipright > div > *, +#modtooltipcenter > div > * { margin-top: 5px; } @@ -1824,7 +1835,7 @@ button.equipmentbutton:last-child { margin-bottom: 5px; } -.modtooltipgroup>* { +.modtooltipgroup > * { padding-left: 10px; } @@ -1873,7 +1884,7 @@ button.equipmentbutton:last-child { align-items: center; } -.modttlabel>div { +.modttlabel > div { color: #f0f0e0; background-color: rgb(28, 32, 36); border: 0 solid rgb(28, 32, 36); @@ -1915,7 +1926,9 @@ button.equipmentbutton:last-child { .modttt .modtooltip { padding: 0.35em; border-radius: 0.75em; - box-shadow: 0 4px 8px 4px rgba(0, 0, 0, 0.8), 0 6px 20px 0 rgba(0, 0, 0, 0.2); + box-shadow: + 0 4px 8px 4px rgba(0, 0, 0, 0.8), + 0 6px 20px 0 rgba(0, 0, 0, 0.2); } .modtooltip .plus, @@ -1932,12 +1945,12 @@ button.equipmentbutton:last-child { margin-top: 0.25em; } -.modtooltip .collapsible-wrapper>input { +.modtooltip .collapsible-wrapper > input { display: none; } .modtooltip .collapsible-wrapper .label-toggle, -.modtooltip .collapsible-wrapper>label { +.modtooltip .collapsible-wrapper > label { -webkit-appearance: menulist-button; border: 1px solid rgb(122, 121, 113); padding: 0.35em; @@ -1946,7 +1959,7 @@ button.equipmentbutton:last-child { /* font-family: 'Font Awesome 5 Free', Roboto, sans-serif; */ } -.modtooltip .collapsible-wrapper>label:after { +.modtooltip .collapsible-wrapper > label:after { font: normal normal normal 12px/1; /* font-family: 'Font Awesome 5 Free'; */ font-weight: 900; @@ -1954,12 +1967,12 @@ button.equipmentbutton:last-child { float: right; } -.modtooltip .collapsible-wrapper>input:checked+label { +.modtooltip .collapsible-wrapper > input:checked + label { border-bottom-left-radius: 0; border-bottom-right-radius: 0; } -.modtooltip .collapsible-wrapper>input:checked+label:after { +.modtooltip .collapsible-wrapper > input:checked + label:after { font: normal normal normal 12px/1; /* font-family: 'Font Awesome 5 Free'; */ font-weight: 900; @@ -2106,7 +2119,7 @@ button.equipmentbutton:last-child { font-size: 145%; } -.modtooltip .modifier-row>div { +.modtooltip .modifier-row > div { margin-bottom: 0.1m; } @@ -2120,7 +2133,7 @@ button.equipmentbutton:last-child { justify-content: stretch; } -.modtooltip .shaded-group>div { +.modtooltip .shaded-group > div { display: flex; flex-flow: row nowrap; justify-content: space-between; @@ -2140,7 +2153,7 @@ button.equipmentbutton:last-child { max-height: 25vh; } -.modifier-journals #entry-list>div:nth-child(3n + 3) { +.modifier-journals #entry-list > div:nth-child(3n + 3) { color: #555; font-size: var(--font-size-smaller); } @@ -2302,11 +2315,11 @@ button.equipmentbutton:last-child { align-items: center; } -#spells>div, +#spells > div, #notes .notesmenu { white-space: normal; } #spells .tooltip { min-width: 200px; -} \ No newline at end of file +} diff --git a/styles/simple.css b/styles/simple.css index 5f977b605..d25cfc363 100755 --- a/styles/simple.css +++ b/styles/simple.css @@ -2046,7 +2046,9 @@ body { .damage-all-message:hover, .damage-message:hover { - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); + box-shadow: + 0 4px 8px 0 rgba(0, 0, 0, 0.2), + 0 6px 20px 0 rgba(0, 0, 0, 0.19); } .roll-message .modifier-list { diff --git a/system.json b/system.json index 271841a1d..9fd60f212 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "id": "gurps", "title": "GURPS 4e Game Aid (Unofficial)", "description": "A game aid to help play GURPS 4e for Foundry VTT", - "version": "0.17.4", + "version": "0.17.5", "authors": [ { "name": "Chris Normand", @@ -24,7 +24,7 @@ ], "compatibility": { "minimum": "12", - "verified": "12.324" + "verified": "12.327" }, "esmodules": ["module/gurps.js", "lib/xregexp-all.js"], "scripts": ["scripts/jquery.tinycolorpicker.js"], @@ -77,7 +77,7 @@ "secondaryTokenAttribute": "FP", "url": "https://github.com/crnormand/gurps", "manifest": "https://raw.githubusercontent.com/crnormand/gurps/release/system.json", - "download": "https://github.com/crnormand/gurps/archive/0.17.4.zip", + "download": "https://github.com/crnormand/gurps/archive/0.17.5.zip", "socket": true, "license": "LICENSE.txt" } diff --git a/templates/die-roll-chat-message.hbs b/templates/die-roll-chat-message.hbs index 4045e7948..569648110 100755 --- a/templates/die-roll-chat-message.hbs +++ b/templates/die-roll-chat-message.hbs @@ -13,7 +13,7 @@ {{#if (gt finaltarget 0)}} - {{localize "GURPS.rollNewTarget" target=finaltarget}} + {{localize 'GURPS.rollNewTarget' target=finaltarget}} {{/if}} {{/if}}
@@ -22,20 +22,21 @@ {{rtotal}} {{#if isCritSuccess}} - {{localize "GURPS.rollCriticalSuccess"}} + {{localize 'GURPS.rollCriticalSuccess'}} {{else if isCritFailure}} - {{localize "GURPS.rollCriticalFailure"}} + {{localize 'GURPS.rollCriticalFailure'}} {{else if failure}} - {{localize "GURPS.rollFailure"}} + {{localize 'GURPS.rollFailure'}} {{else if (not failure)}} - {{localize "GURPS.rollSuccess"}} + {{localize 'GURPS.rollSuccess'}} {{/if}} - {{#if seventeen}} {{localize "GURPS.rollFail17"}} + {{#if seventeen}} + {{localize 'GURPS.rollFail17'}} {{else}} - {{#if (eq margin 0)}}{{localize "GURPS.rollJustMadeIt"}}{{/if}} - {{#if (gt margin 0)}}["{{localize "GURPS.rollMadeBy" margin=margin}}"{{otf}}]{{/if}} - {{#if (lt margin 0)}}["{{localize "GURPS.rollMissedBy" margin=margin}}"{{otf}}]{{/if}} + {{#if (eq margin 0)}}{{localize 'GURPS.rollJustMadeIt'}}{{/if}} + {{#if (gt margin 0)}}["{{localize 'GURPS.rollMadeBy' margin=margin}}"{{otf}}]{{/if}} + {{#if (lt margin 0)}}["{{localize 'GURPS.rollMissedBy' margin=margin}}"{{otf}}]{{/if}} {{/if}} @@ -47,7 +48,7 @@
- {{{localize "GURPS.rollTotalHits" link=(gurpslink '[PDF:B373]') rof=rof rcl=rcl rofrcl=rofrcl}}} + {{{localize 'GURPS.rollTotalHits' link=(gurpslink '[PDF:B373]') rof=rof rcl=rcl rofrcl=rofrcl}}}

@@ -56,7 +57,7 @@
{{#if loaded}}{{else}}{{/if}} - {{localize "GURPS.rollTotal" rolls=rolls rtotal=rtotal}} + {{localize 'GURPS.rollTotal' rolls=rolls rtotal=rtotal}}
{{/each}} {{#if followon}}{{#if (not failure)}} @@ -66,4 +67,4 @@ {{/if}}{{/if}}
- + \ No newline at end of file diff --git a/templates/modifier-bucket/bucket-app.html b/templates/modifier-bucket/bucket-app.html index e6544fb1c..40cdf2510 100755 --- a/templates/modifier-bucket/bucket-app.html +++ b/templates/modifier-bucket/bucket-app.html @@ -1,15 +1,15 @@
{{currentActor}}
{{#each damageAccumulators}} {{#if (eq ../accumulatorIndex @index)}} -
-
-
-
- {{multiplyDice formula count}} {{damagetype}} {{extdamagetype}} -
-
-
- {{/if}} {{/each}} +
+
+
+
+ {{multiplyDice formula count}} {{damagetype}} {{extdamagetype}} +
+
+
+ {{/if}} {{/each}}
{{stack.displaySum}} @@ -25,9 +25,9 @@
{{#if diceVisible}} -
- - -
+
+ + +
{{/if}} -
\ No newline at end of file + diff --git a/templates/resource-editor-popup.hbs b/templates/resource-editor-popup.hbs index df3293efb..ff574bef8 100755 --- a/templates/resource-editor-popup.hbs +++ b/templates/resource-editor-popup.hbs @@ -19,22 +19,34 @@
@@ -44,13 +56,21 @@
@@ -64,54 +84,55 @@
{{#if tracker.thresholds}} -
{{i18n 'GURPS.resourceCurrentValue'}}
-
{{i18n 'GURPS.condition'}}
-
{{i18n 'GURPS.color'}}
-
+
{{i18n 'GURPS.resourceCurrentValue'}}
+
{{i18n 'GURPS.condition'}}
+
{{i18n 'GURPS.color'}}
+
{{else}} -
-
-
-
+
+
+
+
{{/if}} {{#each tracker.thresholds}} -
- - -
-
- - -
- - - - -
- - -
-
- - -
+
+ + +
+
+ + +
+ + + + +
+ + +
+
+ + +
{{/each}}
+ style='width: -webkit-fill-available; padding-top: 0.5rem; margin: 0 -8px; padding-left: 8px; padding-right: 8px;' + >