Ajout des fonctions de gestion des soins
This commit is contained in:
76
lang/en.json
76
lang/en.json
@@ -18,6 +18,12 @@
|
|||||||
"Save": "Save",
|
"Save": "Save",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
"Close": "Close",
|
"Close": "Close",
|
||||||
|
"Dialog": {
|
||||||
|
"ConfirmDeleteTitle": "Confirm Deletion",
|
||||||
|
"ConfirmDeleteContent": "Are you sure you want to delete \"{name}\"?",
|
||||||
|
"Yes": "Yes",
|
||||||
|
"No": "No"
|
||||||
|
},
|
||||||
"Themes": {
|
"Themes": {
|
||||||
"BlackAndRed": "Classic Traveller Cover",
|
"BlackAndRed": "Classic Traveller Cover",
|
||||||
"Mwamba": "Oppa Mwamba Style",
|
"Mwamba": "Oppa Mwamba Style",
|
||||||
@@ -60,6 +66,7 @@
|
|||||||
"Weeks": "Weeks",
|
"Weeks": "Weeks",
|
||||||
"NewCareer": "New Career",
|
"NewCareer": "New Career",
|
||||||
"AddCareer": "Add Career",
|
"AddCareer": "Add Career",
|
||||||
|
"ThisTrait": "this trait",
|
||||||
"EditCareer": "Edit Career",
|
"EditCareer": "Edit Career",
|
||||||
"EditTrait": "Éditer Trait",
|
"EditTrait": "Éditer Trait",
|
||||||
"DeleteTrait": "Supprimer Trait",
|
"DeleteTrait": "Supprimer Trait",
|
||||||
@@ -343,7 +350,10 @@
|
|||||||
"EncumbranceDM": "Encumbrance (DM -2)",
|
"EncumbranceDM": "Encumbrance (DM -2)",
|
||||||
"FatigueDM": "Fatigue (DM -2)",
|
"FatigueDM": "Fatigue (DM -2)",
|
||||||
"Boon": "Boon",
|
"Boon": "Boon",
|
||||||
"Bane": "Bane"
|
"Bane": "Bane",
|
||||||
|
"CreatureSkill": "Skill",
|
||||||
|
"NoSkill": "No skill",
|
||||||
|
"Days": "Days"
|
||||||
},
|
},
|
||||||
"Timeframes": {
|
"Timeframes": {
|
||||||
"Normal": "Normal",
|
"Normal": "Normal",
|
||||||
@@ -355,7 +365,11 @@
|
|||||||
"ApplyDamages": "Apply Damages",
|
"ApplyDamages": "Apply Damages",
|
||||||
"Damages": "Roll damages",
|
"Damages": "Roll damages",
|
||||||
"Success": "Success",
|
"Success": "Success",
|
||||||
"Failure": "Failure"
|
"Failure": "Failure",
|
||||||
|
"Effect": "Effect",
|
||||||
|
"Dice": "Dice",
|
||||||
|
"Result": "Result",
|
||||||
|
"DiceModifier": "Dice Modifier"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Items": {
|
"Items": {
|
||||||
@@ -393,7 +407,7 @@
|
|||||||
"Informations": "Informations",
|
"Informations": "Informations",
|
||||||
"Improvement": "Improvement",
|
"Improvement": "Improvement",
|
||||||
"Interval": "Interval",
|
"Interval": "Interval",
|
||||||
"IsMelee": "IsMelee",
|
"IsMelee": "Melee Weapon",
|
||||||
"Items": "Items",
|
"Items": "Items",
|
||||||
"Level": "Level",
|
"Level": "Level",
|
||||||
"Location": "Location",
|
"Location": "Location",
|
||||||
@@ -410,6 +424,7 @@
|
|||||||
"Occupation": "Occupation",
|
"Occupation": "Occupation",
|
||||||
"OnHand": "On Hand",
|
"OnHand": "On Hand",
|
||||||
"Options": "Options",
|
"Options": "Options",
|
||||||
|
"PerDay": "per day",
|
||||||
"PSICost": "PSI Cost",
|
"PSICost": "PSI Cost",
|
||||||
"Powered": "Powered",
|
"Powered": "Powered",
|
||||||
"Processing": "Processing",
|
"Processing": "Processing",
|
||||||
@@ -461,11 +476,13 @@
|
|||||||
"TabAttacks": "Attacks",
|
"TabAttacks": "Attacks",
|
||||||
"TabTraits": "Traits",
|
"TabTraits": "Traits",
|
||||||
"TabInfo": "Information",
|
"TabInfo": "Information",
|
||||||
|
"TabCombat": "Combat",
|
||||||
"SkillName": "Skill",
|
"SkillName": "Skill",
|
||||||
"SkillLevel": "Level",
|
"SkillLevel": "Level",
|
||||||
"SkillNote": "Note",
|
"SkillNote": "Note",
|
||||||
"AttackName": "Attack",
|
"AttackName": "Attack",
|
||||||
"AttackDamage": "Damage",
|
"AttackDamage": "Damage",
|
||||||
|
"AttackSkill": "Skill",
|
||||||
"TraitName": "Trait",
|
"TraitName": "Trait",
|
||||||
"TraitValue": "Value",
|
"TraitValue": "Value",
|
||||||
"AddSkill": "Add a skill",
|
"AddSkill": "Add a skill",
|
||||||
@@ -480,6 +497,36 @@
|
|||||||
"SkillLabel": "Skill",
|
"SkillLabel": "Skill",
|
||||||
"RollTitle": "Creature roll"
|
"RollTitle": "Creature roll"
|
||||||
},
|
},
|
||||||
|
"SpeedBands": {
|
||||||
|
"Stoppped": "Stopped",
|
||||||
|
"Idle": "Idle",
|
||||||
|
"VerySlow": "Very Slow",
|
||||||
|
"Slow": "Slow",
|
||||||
|
"Medium": "Medium",
|
||||||
|
"High": "High",
|
||||||
|
"Fast": "Fast",
|
||||||
|
"VeryFast": "Very Fast",
|
||||||
|
"Subsonic": "Subsonic",
|
||||||
|
"Hypersonic": "Hypersonic"
|
||||||
|
},
|
||||||
|
"Vehicule": {
|
||||||
|
"Hull": "Hull",
|
||||||
|
"ArmorFront": "Front",
|
||||||
|
"ArmorSides": "Sides",
|
||||||
|
"ArmorRear": "Rear",
|
||||||
|
"Armor": "Armor",
|
||||||
|
"SpeedCruise": "Cruise Speed",
|
||||||
|
"SpeedMax": "Max Speed",
|
||||||
|
"Agility": "Agility",
|
||||||
|
"Crew": "Crew",
|
||||||
|
"Passengers": "Passengers",
|
||||||
|
"Cargo": "Cargo (t)",
|
||||||
|
"Shipping": "Shipping (t)",
|
||||||
|
"Cost": "Cost (Cr)",
|
||||||
|
"Autopilot": "Autopilot",
|
||||||
|
"TabStats": "Statistics",
|
||||||
|
"TabDescription": "Description"
|
||||||
|
},
|
||||||
"CreatureBehaviorType": {
|
"CreatureBehaviorType": {
|
||||||
"herbivore": "Herbivore",
|
"herbivore": "Herbivore",
|
||||||
"carnivore": "Carnivore",
|
"carnivore": "Carnivore",
|
||||||
@@ -500,6 +547,29 @@
|
|||||||
"necrophage": "Carrion-eater",
|
"necrophage": "Carrion-eater",
|
||||||
"reducteur": "Reducer",
|
"reducteur": "Reducer",
|
||||||
"opportuniste": "Opportunist"
|
"opportuniste": "Opportunist"
|
||||||
|
},
|
||||||
|
"Healing": {
|
||||||
|
"Title": "Healing",
|
||||||
|
"FirstAid": "First Aid",
|
||||||
|
"Surgery": "Surgery",
|
||||||
|
"MedicalCare": "Medical Care",
|
||||||
|
"NaturalHealing": "Natural Healing",
|
||||||
|
"WillRestore": "Will restore",
|
||||||
|
"SurgeryFailed": "Surgery failed - patient takes damage",
|
||||||
|
"ApplyHealing": "Apply Healing",
|
||||||
|
"ApplySurgeryDamage": "Apply Surgery Damage",
|
||||||
|
"SurgeryDamage": "surgery damage",
|
||||||
|
"ApplyToTarget": "Apply healing to selected target",
|
||||||
|
"NoMedicineSkill": "No Medicine Skill",
|
||||||
|
"Heals": "heals"
|
||||||
|
},
|
||||||
|
"Notifications": {
|
||||||
|
"HealingApplied": "{name} has been healed for {amount} points.",
|
||||||
|
"DamageApplied": "{name} has taken {amount} damage."
|
||||||
|
},
|
||||||
|
"Errors": {
|
||||||
|
"NoTokenSelected": "No token selected. Select a token on the scene before applying.",
|
||||||
|
"InvalidRollFormula": "Invalid roll formula."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TYPES.Actor.creature": "Creature"
|
"TYPES.Actor.creature": "Creature"
|
||||||
|
|||||||
76
lang/fr.json
76
lang/fr.json
@@ -18,6 +18,12 @@
|
|||||||
"Save": "Sauvegarder",
|
"Save": "Sauvegarder",
|
||||||
"Cancel": "Annuler",
|
"Cancel": "Annuler",
|
||||||
"Close": "Fermer",
|
"Close": "Fermer",
|
||||||
|
"Dialog": {
|
||||||
|
"ConfirmDeleteTitle": "Confirmer la suppression",
|
||||||
|
"ConfirmDeleteContent": "Êtes-vous sûr de vouloir supprimer \"{name}\" ?",
|
||||||
|
"Yes": "Oui",
|
||||||
|
"No": "Non"
|
||||||
|
},
|
||||||
"Themes": {
|
"Themes": {
|
||||||
"BlackAndRed": "Couverture Classique Traveller",
|
"BlackAndRed": "Couverture Classique Traveller",
|
||||||
"Mwamba": "Oppa Mwamba Style",
|
"Mwamba": "Oppa Mwamba Style",
|
||||||
@@ -60,6 +66,7 @@
|
|||||||
"Weeks": "Semaines",
|
"Weeks": "Semaines",
|
||||||
"NewCareer": "Nouvelle Carrière",
|
"NewCareer": "Nouvelle Carrière",
|
||||||
"AddCareer": "Ajouter Carrière",
|
"AddCareer": "Ajouter Carrière",
|
||||||
|
"ThisTrait": "ce trait",
|
||||||
"EditCareer": "Éditer Carrière",
|
"EditCareer": "Éditer Carrière",
|
||||||
"EditTrait": "Éditer Trait",
|
"EditTrait": "Éditer Trait",
|
||||||
"DeleteTrait": "Supprimer Trait",
|
"DeleteTrait": "Supprimer Trait",
|
||||||
@@ -343,7 +350,10 @@
|
|||||||
"EncumbranceDM": "Encombrement (MD -2)",
|
"EncumbranceDM": "Encombrement (MD -2)",
|
||||||
"FatigueDM": "Fatigue (MD -2)",
|
"FatigueDM": "Fatigue (MD -2)",
|
||||||
"Boon": "Avantage",
|
"Boon": "Avantage",
|
||||||
"Bane": "Désavantage"
|
"Bane": "Désavantage",
|
||||||
|
"CreatureSkill": "Compétence",
|
||||||
|
"NoSkill": "Aucune compétence",
|
||||||
|
"Days": "Jours"
|
||||||
},
|
},
|
||||||
"Timeframes": {
|
"Timeframes": {
|
||||||
"Normal": "Normal",
|
"Normal": "Normal",
|
||||||
@@ -355,7 +365,11 @@
|
|||||||
"ApplyDamages": "Appliquer Dégâts",
|
"ApplyDamages": "Appliquer Dégâts",
|
||||||
"Damages": "Lancer les Dégâts",
|
"Damages": "Lancer les Dégâts",
|
||||||
"Success": "Succès",
|
"Success": "Succès",
|
||||||
"Failure": "Échec"
|
"Failure": "Échec",
|
||||||
|
"Effect": "Effet",
|
||||||
|
"Dice": "Dés",
|
||||||
|
"Result": "Résultat",
|
||||||
|
"DiceModifier": "Modificateur de dés"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Items": {
|
"Items": {
|
||||||
@@ -393,7 +407,7 @@
|
|||||||
"Informations": "Informations",
|
"Informations": "Informations",
|
||||||
"Improvement": "Améliorations",
|
"Improvement": "Améliorations",
|
||||||
"Interval": "Intervalle",
|
"Interval": "Intervalle",
|
||||||
"IsMelee": "Est Mêlée",
|
"IsMelee": "Arme de Mêlée",
|
||||||
"Items": "Objets",
|
"Items": "Objets",
|
||||||
"Level": "Niveau",
|
"Level": "Niveau",
|
||||||
"Location": "Localisation",
|
"Location": "Localisation",
|
||||||
@@ -410,6 +424,7 @@
|
|||||||
"Occupation": "Profession",
|
"Occupation": "Profession",
|
||||||
"OnHand": "Sur Soi",
|
"OnHand": "Sur Soi",
|
||||||
"Options": "Options",
|
"Options": "Options",
|
||||||
|
"PerDay": "par jour",
|
||||||
"PSICost": "Coût PSI",
|
"PSICost": "Coût PSI",
|
||||||
"Powered": "Alimenté",
|
"Powered": "Alimenté",
|
||||||
"Processing": "Capacité de Traitement",
|
"Processing": "Capacité de Traitement",
|
||||||
@@ -461,11 +476,13 @@
|
|||||||
"TabAttacks": "Attaques",
|
"TabAttacks": "Attaques",
|
||||||
"TabTraits": "Traits",
|
"TabTraits": "Traits",
|
||||||
"TabInfo": "Informations",
|
"TabInfo": "Informations",
|
||||||
|
"TabCombat": "Combat",
|
||||||
"SkillName": "Compétence",
|
"SkillName": "Compétence",
|
||||||
"SkillLevel": "Niveau",
|
"SkillLevel": "Niveau",
|
||||||
"SkillNote": "Note",
|
"SkillNote": "Note",
|
||||||
"AttackName": "Attaque",
|
"AttackName": "Attaque",
|
||||||
"AttackDamage": "Dommages",
|
"AttackDamage": "Dommages",
|
||||||
|
"AttackSkill": "Compétence",
|
||||||
"TraitName": "Trait",
|
"TraitName": "Trait",
|
||||||
"TraitValue": "Valeur",
|
"TraitValue": "Valeur",
|
||||||
"AddSkill": "Ajouter une compétence",
|
"AddSkill": "Ajouter une compétence",
|
||||||
@@ -480,6 +497,36 @@
|
|||||||
"SkillLabel": "Compétence",
|
"SkillLabel": "Compétence",
|
||||||
"RollTitle": "Jet de créature"
|
"RollTitle": "Jet de créature"
|
||||||
},
|
},
|
||||||
|
"SpeedBands": {
|
||||||
|
"Stoppped": "Arrêté",
|
||||||
|
"Idle": "Au ralenti",
|
||||||
|
"VerySlow": "Très lent",
|
||||||
|
"Slow": "Lent",
|
||||||
|
"Medium": "Moyen",
|
||||||
|
"High": "Élevé",
|
||||||
|
"Fast": "Rapide",
|
||||||
|
"VeryFast": "Très rapide",
|
||||||
|
"Subsonic": "Subsonique",
|
||||||
|
"Hypersonic": "Hypersonique"
|
||||||
|
},
|
||||||
|
"Vehicule": {
|
||||||
|
"Hull": "Coque",
|
||||||
|
"ArmorFront": "Av.",
|
||||||
|
"ArmorSides": "Lat.",
|
||||||
|
"ArmorRear": "Arr.",
|
||||||
|
"Armor": "Armure",
|
||||||
|
"SpeedCruise": "Vitesse croisière",
|
||||||
|
"SpeedMax": "Vitesse max",
|
||||||
|
"Agility": "Agilité",
|
||||||
|
"Crew": "Équipage",
|
||||||
|
"Passengers": "Passagers",
|
||||||
|
"Cargo": "Cargo (t)",
|
||||||
|
"Shipping": "Expédition (t)",
|
||||||
|
"Cost": "Coût (Cr)",
|
||||||
|
"Autopilot": "Autopilote",
|
||||||
|
"TabStats": "Statistiques",
|
||||||
|
"TabDescription": "Description"
|
||||||
|
},
|
||||||
"CreatureBehaviorType": {
|
"CreatureBehaviorType": {
|
||||||
"herbivore": "Herbivore",
|
"herbivore": "Herbivore",
|
||||||
"carnivore": "Carnivore",
|
"carnivore": "Carnivore",
|
||||||
@@ -500,6 +547,29 @@
|
|||||||
"necrophage": "Nécrophage",
|
"necrophage": "Nécrophage",
|
||||||
"reducteur": "Réducteur",
|
"reducteur": "Réducteur",
|
||||||
"opportuniste": "Opportuniste"
|
"opportuniste": "Opportuniste"
|
||||||
|
},
|
||||||
|
"Healing": {
|
||||||
|
"Title": "Soins",
|
||||||
|
"FirstAid": "Premiers soins",
|
||||||
|
"Surgery": "Chirurgie",
|
||||||
|
"MedicalCare": "Soins médicaux",
|
||||||
|
"NaturalHealing": "Guérison naturelle",
|
||||||
|
"WillRestore": "Restaurera",
|
||||||
|
"SurgeryFailed": "Chirurgie échouée - patient subit des dégâts",
|
||||||
|
"ApplyHealing": "Appliquer les soins",
|
||||||
|
"ApplySurgeryDamage": "Appliquer les dégâts chirurgicaux",
|
||||||
|
"SurgeryDamage": "dégâts chirurgicaux",
|
||||||
|
"ApplyToTarget": "Appliquer les soins à la cible sélectionnée",
|
||||||
|
"NoMedicineSkill": "Pas de compétence Médecine",
|
||||||
|
"Heals": "soigne"
|
||||||
|
},
|
||||||
|
"Notifications": {
|
||||||
|
"HealingApplied": "{name} a été soigné(e) de {amount} points.",
|
||||||
|
"DamageApplied": "{name} a subi {amount} dégâts."
|
||||||
|
},
|
||||||
|
"Errors": {
|
||||||
|
"NoTokenSelected": "Aucun token sélectionné. Sélectionnez un token sur la scène avant d'appliquer.",
|
||||||
|
"InvalidRollFormula": "Formule de jet invalide."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"TYPES.Actor.creature": "Créature"
|
"TYPES.Actor.creature": "Créature"
|
||||||
|
|||||||
922
mgt2.bundle.js
922
mgt2.bundle.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -52,9 +52,32 @@ export class TravellerActor extends Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyDamage(amount) {
|
applyDamage(amount, { ignoreArmor = false } = {}) {
|
||||||
if (this.type === "character") {
|
if (this.type === "character") {
|
||||||
ActorCharacter.applyDamage(this, amount);
|
return ActorCharacter.applyDamage(this, amount, { ignoreArmor });
|
||||||
|
} else if (this.type === "creature") {
|
||||||
|
if (isNaN(amount) || amount === 0) return;
|
||||||
|
if (amount < 0) amount = Math.abs(amount);
|
||||||
|
const armorValue = ignoreArmor ? 0 : (this.system.armor ?? 0);
|
||||||
|
const effective = Math.max(0, amount - armorValue);
|
||||||
|
if (effective === 0) return;
|
||||||
|
const newValue = Math.max(0, (this.system.life.value ?? 0) - effective);
|
||||||
|
return this.update({ "system.life.value": newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
applyHealing(amount) {
|
||||||
|
if (this.type === "character") {
|
||||||
|
return ActorCharacter.applyHealing(this, amount);
|
||||||
|
} else if (this.type === "creature") {
|
||||||
|
if (isNaN(amount) || amount === 0) return;
|
||||||
|
if (amount < 0) amount = Math.abs(amount);
|
||||||
|
const maxValue = this.system.life.max ?? 0;
|
||||||
|
const current = this.system.life.value ?? 0;
|
||||||
|
const newValue = Math.min(current + amount, maxValue);
|
||||||
|
if (newValue !== current) {
|
||||||
|
return this.update({ "system.life.value": newValue });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,4 +70,35 @@ export class CharacterPrompts {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async openHealingDays() {
|
||||||
|
return await DialogV2.wait({
|
||||||
|
window: {
|
||||||
|
title: game.i18n.localize("MGT2.Healing.Title")
|
||||||
|
},
|
||||||
|
classes: ["mgt2-roll-dialog"],
|
||||||
|
content: `
|
||||||
|
<form>
|
||||||
|
<div style="padding: 12px;">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>${game.i18n.localize("MGT2.RollPrompt.Days") || "Jours"}</label>
|
||||||
|
<input type="number" name="days" value="1" min="1" max="999" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
`,
|
||||||
|
rejectClose: false,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
action: "submit",
|
||||||
|
label: game.i18n.localize("MGT2.Save"),
|
||||||
|
icon: '<i class="fa-solid fa-floppy-disk"></i>',
|
||||||
|
default: true,
|
||||||
|
callback: (event, button, dialog) => {
|
||||||
|
return new FormDataExtended(dialog.element.querySelector('form')).object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -331,7 +331,7 @@ export class ActorCharacter {
|
|||||||
// $this.update({ system: { characteristics: data } });
|
// $this.update({ system: { characteristics: data } });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static applyDamage($this, amount) {
|
static applyDamage($this, amount, { ignoreArmor = false } = {}) {
|
||||||
if (isNaN(amount) || amount === 0) return;
|
if (isNaN(amount) || amount === 0) return;
|
||||||
const rank1 = $this.system.config.damages.rank1;
|
const rank1 = $this.system.config.damages.rank1;
|
||||||
const rank2 = $this.system.config.damages.rank2;
|
const rank2 = $this.system.config.damages.rank2;
|
||||||
@@ -344,6 +344,12 @@ export class ActorCharacter {
|
|||||||
|
|
||||||
if (amount < 0) amount = Math.abs(amount);
|
if (amount < 0) amount = Math.abs(amount);
|
||||||
|
|
||||||
|
if (!ignoreArmor) {
|
||||||
|
const armorValue = $this.system.inventory?.armor ?? 0;
|
||||||
|
amount = Math.max(0, amount - armorValue);
|
||||||
|
if (amount === 0) return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const [key, rank] of Object.entries(data)) {
|
for (const [key, rank] of Object.entries(data)) {
|
||||||
if (rank.value > 0) {
|
if (rank.value > 0) {
|
||||||
if (rank.value >= amount) {
|
if (rank.value >= amount) {
|
||||||
@@ -361,6 +367,48 @@ export class ActorCharacter {
|
|||||||
$this.update({ system: { characteristics: data } });
|
$this.update({ system: { characteristics: data } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static applyHealing($this, amount, type) {
|
||||||
|
if (isNaN(amount) || amount === 0) return;
|
||||||
|
|
||||||
|
const rank1 = $this.system.config.damages.rank1;
|
||||||
|
const rank2 = $this.system.config.damages.rank2;
|
||||||
|
const rank3 = $this.system.config.damages.rank3;
|
||||||
|
|
||||||
|
// Data to restore (reverse cascade: END → DEX → STR)
|
||||||
|
const data = {};
|
||||||
|
const rankOrder = [rank3, rank2, rank1]; // Reverse order for healing
|
||||||
|
const maxValues = {
|
||||||
|
[rank1]: $this.system.characteristics[rank1].max,
|
||||||
|
[rank2]: $this.system.characteristics[rank2].max,
|
||||||
|
[rank3]: $this.system.characteristics[rank3].max
|
||||||
|
};
|
||||||
|
|
||||||
|
if (amount < 0) amount = Math.abs(amount);
|
||||||
|
|
||||||
|
// Distribute healing from lowest rank first (END → DEX → STR typically)
|
||||||
|
for (const rank of rankOrder) {
|
||||||
|
const current = $this.system.characteristics[rank].value;
|
||||||
|
const max = maxValues[rank];
|
||||||
|
|
||||||
|
if (current < max && amount > 0) {
|
||||||
|
const canRestore = max - current;
|
||||||
|
const restore = Math.min(amount, canRestore);
|
||||||
|
|
||||||
|
if (!data[rank]) {
|
||||||
|
data[rank] = { value: current };
|
||||||
|
}
|
||||||
|
data[rank].value += restore;
|
||||||
|
data[rank].dm = this.getModifier(data[rank].value);
|
||||||
|
amount -= restore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only update if something was restored
|
||||||
|
if (Object.keys(data).length > 0) {
|
||||||
|
return $this.update({ system: { characteristics: data } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static getContainers($this) {
|
static getContainers($this) {
|
||||||
const containers = [];
|
const containers = [];
|
||||||
for (let item of $this.items) {
|
for (let item of $this.items) {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
traitEdit: TravellerCharacterSheet.#onTraitEdit,
|
traitEdit: TravellerCharacterSheet.#onTraitEdit,
|
||||||
traitDelete: TravellerCharacterSheet.#onTraitDelete,
|
traitDelete: TravellerCharacterSheet.#onTraitDelete,
|
||||||
openEditor: TravellerCharacterSheet.#onOpenEditor,
|
openEditor: TravellerCharacterSheet.#onOpenEditor,
|
||||||
|
heal: TravellerCharacterSheet.#onHeal,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +55,11 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
async _prepareContext() {
|
async _prepareContext() {
|
||||||
const context = await super._prepareContext();
|
const context = await super._prepareContext();
|
||||||
const actor = this.document;
|
const actor = this.document;
|
||||||
|
const enrich = (html) => foundry.applications.ux.TextEditor.implementation.enrichHTML(html ?? "", { async: true });
|
||||||
|
|
||||||
|
context.enrichedBiography = await enrich(actor.system.biography);
|
||||||
|
context.enrichedNotes = await enrich(actor.system.notes);
|
||||||
|
context.enrichedFinanceNotes = await enrich(actor.system.finance?.notes);
|
||||||
context.settings = {
|
context.settings = {
|
||||||
weightUnit: "kg",
|
weightUnit: "kg",
|
||||||
usePronouns: game.settings.get("mgt2", "usePronouns"),
|
usePronouns: game.settings.get("mgt2", "usePronouns"),
|
||||||
@@ -152,9 +157,10 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
|
|
||||||
if (item.hasOwnProperty("equipped")) {
|
if (item.hasOwnProperty("equipped")) {
|
||||||
i._canEquip = true;
|
i._canEquip = true;
|
||||||
i._toggleClass = item.equipped ? "active" : "";
|
i.toggleClass = item.equipped ? "active" : "";
|
||||||
} else {
|
} else {
|
||||||
i._canEquip = false;
|
i._canEquip = false;
|
||||||
|
i.toggleClass = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (i.type) {
|
switch (i.type) {
|
||||||
@@ -288,7 +294,6 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
this._bindClassEvent(html, ".item-create", "click", TravellerCharacterSheet.#onCreateItem);
|
this._bindClassEvent(html, ".item-create", "click", TravellerCharacterSheet.#onCreateItem);
|
||||||
this._bindClassEvent(html, ".item-edit", "click", TravellerCharacterSheet.#onEditItem);
|
this._bindClassEvent(html, ".item-edit", "click", TravellerCharacterSheet.#onEditItem);
|
||||||
this._bindClassEvent(html, ".item-delete", "click", TravellerCharacterSheet.#onDeleteItem);
|
this._bindClassEvent(html, ".item-delete", "click", TravellerCharacterSheet.#onDeleteItem);
|
||||||
this._bindClassEvent(html, ".item-equip", "click", TravellerCharacterSheet.#onEquipItem);
|
|
||||||
this._bindClassEvent(html, ".item-storage-in", "click", TravellerCharacterSheet.#onItemStorageIn);
|
this._bindClassEvent(html, ".item-storage-in", "click", TravellerCharacterSheet.#onItemStorageIn);
|
||||||
this._bindClassEvent(html, ".item-storage-out", "click", TravellerCharacterSheet.#onItemStorageOut);
|
this._bindClassEvent(html, ".item-storage-out", "click", TravellerCharacterSheet.#onItemStorageOut);
|
||||||
this._bindClassEvent(html, ".software-eject", "click", TravellerCharacterSheet.#onSoftwareEject);
|
this._bindClassEvent(html, ".software-eject", "click", TravellerCharacterSheet.#onSoftwareEject);
|
||||||
@@ -452,17 +457,34 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
if (item) item.sheet.render(true);
|
if (item) item.sheet.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async #confirmDelete(name) {
|
||||||
|
return foundry.applications.api.DialogV2.confirm({
|
||||||
|
window: { title: game.i18n.localize("MGT2.Dialog.ConfirmDeleteTitle") },
|
||||||
|
content: `<p>${game.i18n.format("MGT2.Dialog.ConfirmDeleteContent", { name })}</p>`,
|
||||||
|
yes: { label: game.i18n.localize("MGT2.Dialog.Yes"), icon: "fas fa-trash" },
|
||||||
|
no: { label: game.i18n.localize("MGT2.Dialog.No"), icon: "fas fa-times" },
|
||||||
|
rejectClose: false,
|
||||||
|
modal: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static async #onDeleteItem(event, target) {
|
static async #onDeleteItem(event, target) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const li = target.closest("[data-item-id]");
|
const li = target.closest("[data-item-id]");
|
||||||
if (!li?.dataset.itemId) return;
|
if (!li?.dataset.itemId) return;
|
||||||
|
const item = this.actor.items.get(li.dataset.itemId);
|
||||||
|
if (!item) return;
|
||||||
|
const confirmed = await TravellerCharacterSheet.#confirmDelete(item.name);
|
||||||
|
if (!confirmed) return;
|
||||||
this.actor.deleteEmbeddedDocuments("Item", [li.dataset.itemId]);
|
this.actor.deleteEmbeddedDocuments("Item", [li.dataset.itemId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #onEquipItem(event, target) {
|
static async #onEquipItem(event, target) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const li = target.closest("[data-item-id]");
|
const li = target.closest("[data-item-id]");
|
||||||
const item = this.actor.getEmbeddedDocument("Item", li?.dataset.itemId);
|
const itemId = li?.dataset.itemId;
|
||||||
|
if (!itemId) return;
|
||||||
|
const item = this.actor.items.get(itemId);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
await item.update({ "system.equipped": !item.system.equipped });
|
await item.update({ "system.equipped": !item.system.equipped });
|
||||||
}
|
}
|
||||||
@@ -530,6 +552,9 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
const container = containers.find(x => x._id === this.actor.system.containerView);
|
const container = containers.find(x => x._id === this.actor.system.containerView);
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
|
const confirmed = await TravellerCharacterSheet.#confirmDelete(container.name);
|
||||||
|
if (!confirmed) return;
|
||||||
|
|
||||||
const containerItems = this.actor.items.filter(
|
const containerItems = this.actor.items.filter(
|
||||||
x => x.system.hasOwnProperty("container") && x.system.container.id === container._id
|
x => x.system.hasOwnProperty("container") && x.system.container.id === container._id
|
||||||
);
|
);
|
||||||
@@ -564,6 +589,7 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
encumbrance: this.actor.system.states.encumbrance,
|
encumbrance: this.actor.system.states.encumbrance,
|
||||||
difficulty: null,
|
difficulty: null,
|
||||||
damageFormula: null,
|
damageFormula: null,
|
||||||
|
isMelee: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const cardButtons = [];
|
const cardButtons = [];
|
||||||
@@ -631,6 +657,9 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
|
|
||||||
if (itemObj?.system.hasOwnProperty("damage")) {
|
if (itemObj?.system.hasOwnProperty("damage")) {
|
||||||
rollOptions.damageFormula = itemObj.system.damage;
|
rollOptions.damageFormula = itemObj.system.damage;
|
||||||
|
if (itemObj.type === "weapon") {
|
||||||
|
rollOptions.isMelee = itemObj.system.range?.isMelee === true;
|
||||||
|
}
|
||||||
if (itemObj.type === "disease") {
|
if (itemObj.type === "disease") {
|
||||||
if (itemObj.system.subType === "disease")
|
if (itemObj.system.subType === "disease")
|
||||||
rollOptions.rollTypeName = game.i18n.localize("MGT2.DiseaseSubType.disease");
|
rollOptions.rollTypeName = game.i18n.localize("MGT2.DiseaseSubType.disease");
|
||||||
@@ -695,13 +724,13 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
rollModifiers.push(game.i18n.localize("MGT2.Actor.Fatigue") + " -2");
|
rollModifiers.push(game.i18n.localize("MGT2.Actor.Fatigue") + " -2");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userRollData.customDM) {
|
const customDMVal = parseInt(userRollData.customDM ?? "0", 10);
|
||||||
const s = userRollData.customDM.trim();
|
if (!isNaN(customDMVal) && customDMVal !== 0) {
|
||||||
if (/^[0-9]/.test(s)) rollFormulaParts.push("+");
|
rollFormulaParts.push(customDMVal > 0 ? `+${customDMVal}` : `${customDMVal}`);
|
||||||
rollFormulaParts.push(s);
|
rollModifiers.push(game.i18n.localize("MGT2.RollPrompt.CustomDM") + " " + (customDMVal > 0 ? `+${customDMVal}` : `${customDMVal}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MGT2Helper.hasValue(userRollData, "difficulty")) rollOptions.difficulty = userRollData.difficulty;
|
if (MGT2Helper.hasValue(userRollData, "difficulty") && userRollData.difficulty !== "") rollOptions.difficulty = userRollData.difficulty;
|
||||||
|
|
||||||
const rollFormula = rollFormulaParts.join("");
|
const rollFormula = rollFormulaParts.join("");
|
||||||
if (!Roll.validate(rollFormula)) {
|
if (!Roll.validate(rollFormula)) {
|
||||||
@@ -715,37 +744,74 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
await this.token.combatant.update({ initiative: roll.total });
|
await this.token.combatant.update({ initiative: roll.total });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Compute effect and effective damage formula ──────────────────────
|
||||||
|
let rollSuccess = false;
|
||||||
|
let rollFailure = false;
|
||||||
|
let rollEffect = undefined;
|
||||||
|
let rollEffectStr = undefined;
|
||||||
|
let difficultyValue = null;
|
||||||
|
|
||||||
|
if (MGT2Helper.hasValue(rollOptions, "difficulty")) {
|
||||||
|
difficultyValue = MGT2Helper.getDifficultyValue(rollOptions.difficulty);
|
||||||
|
rollEffect = roll.total - difficultyValue;
|
||||||
|
rollEffectStr = (rollEffect >= 0 ? "+" : "") + rollEffect;
|
||||||
|
rollSuccess = rollEffect >= 0;
|
||||||
|
rollFailure = !rollSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build effective damage formula: base + effect + STR DM (melee)
|
||||||
|
let effectiveDamageFormula = rollOptions.damageFormula || null;
|
||||||
|
if (effectiveDamageFormula) {
|
||||||
|
if (rollEffect !== undefined && rollEffect !== 0) {
|
||||||
|
effectiveDamageFormula += (rollEffect >= 0 ? "+" : "") + rollEffect;
|
||||||
|
}
|
||||||
|
if (rollOptions.isMelee) {
|
||||||
|
const strDm = this.actor.system.characteristics.strength?.dm ?? 0;
|
||||||
|
if (strDm !== 0) effectiveDamageFormula += (strDm >= 0 ? "+" : "") + strDm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Build roll breakdown tooltip ─────────────────────────────────────
|
||||||
|
const diceRawTotal = roll.dice.reduce((s, d) => s + d.total, 0);
|
||||||
|
const breakdownParts = [game.i18n.localize("MGT2.Chat.Roll.Dice") + " " + diceRawTotal];
|
||||||
|
for (const mod of rollModifiers) breakdownParts.push(mod);
|
||||||
|
if (rollEffectStr !== undefined)
|
||||||
|
breakdownParts.push(game.i18n.localize("MGT2.Chat.Roll.Effect") + " " + rollEffectStr);
|
||||||
|
const rollBreakdown = breakdownParts.join(" | ");
|
||||||
|
|
||||||
const chatData = {
|
const chatData = {
|
||||||
user: game.user.id,
|
user: game.user.id,
|
||||||
speaker: this.actor ? ChatMessage.getSpeaker({ actor: this.actor }) : null,
|
speaker: this.actor ? ChatMessage.getSpeaker({ actor: this.actor }) : null,
|
||||||
formula: roll._formula,
|
formula: roll._formula,
|
||||||
tooltip: await roll.getTooltip(),
|
tooltip: await roll.getTooltip(),
|
||||||
total: Math.round(roll.total * 100) / 100,
|
total: Math.round(roll.total * 100) / 100,
|
||||||
|
rollBreakdown,
|
||||||
showButtons: true,
|
showButtons: true,
|
||||||
showLifeButtons: false,
|
showLifeButtons: false,
|
||||||
showRollRequest: false,
|
showRollRequest: false,
|
||||||
rollTypeName: rollOptions.rollTypeName,
|
rollTypeName: rollOptions.rollTypeName,
|
||||||
rollObjectName: rollOptions.rollObjectName,
|
rollObjectName: rollOptions.rollObjectName,
|
||||||
rollModifiers: rollModifiers,
|
rollModifiers: rollModifiers,
|
||||||
showRollDamage: rollOptions.damageFormula !== null && rollOptions.damageFormula !== "",
|
// Show damage button only if there's a formula AND (no difficulty check OR roll succeeded)
|
||||||
|
showRollDamage: !!effectiveDamageFormula && (!difficultyValue || rollSuccess),
|
||||||
cardButtons: cardButtons,
|
cardButtons: cardButtons,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (MGT2Helper.hasValue(rollOptions, "difficulty")) {
|
if (MGT2Helper.hasValue(rollOptions, "difficulty")) {
|
||||||
chatData.rollDifficulty = rollOptions.difficulty;
|
chatData.rollDifficulty = rollOptions.difficulty;
|
||||||
chatData.rollDifficultyLabel = MGT2Helper.getDifficultyDisplay(rollOptions.difficulty);
|
chatData.rollDifficultyLabel = MGT2Helper.getDifficultyDisplay(rollOptions.difficulty);
|
||||||
if (roll.total >= MGT2Helper.getDifficultyValue(rollOptions.difficulty))
|
chatData.rollEffect = rollEffect;
|
||||||
chatData.rollSuccess = true;
|
chatData.rollEffectStr = rollEffectStr;
|
||||||
else
|
chatData.rollSuccess = rollSuccess || undefined;
|
||||||
chatData.rollFailure = true;
|
chatData.rollFailure = rollFailure || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const html = await foundry.applications.handlebars.renderTemplate("systems/mgt2/templates/chat/roll.html", chatData);
|
const html = await foundry.applications.handlebars.renderTemplate("systems/mgt2/templates/chat/roll.html", chatData);
|
||||||
chatData.content = html;
|
chatData.content = html;
|
||||||
|
|
||||||
let flags = null;
|
let flags = null;
|
||||||
if (rollOptions.damageFormula) {
|
if (effectiveDamageFormula) {
|
||||||
flags = { mgt2: { damage: { formula: rollOptions.damageFormula, rollObjectName: rollOptions.rollObjectName, rollTypeName: rollOptions.rollTypeName } } };
|
flags = { mgt2: { damage: { formula: effectiveDamageFormula, rollObjectName: rollOptions.rollObjectName, rollTypeName: rollOptions.rollTypeName } } };
|
||||||
}
|
}
|
||||||
if (cardButtons.length > 0) {
|
if (cardButtons.length > 0) {
|
||||||
if (!flags) flags = { mgt2: {} };
|
if (!flags) flags = { mgt2: {} };
|
||||||
@@ -816,6 +882,8 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
|
|
||||||
static async #onTraitDelete(event, target) {
|
static async #onTraitDelete(event, target) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
const confirmed = await TravellerCharacterSheet.#confirmDelete(game.i18n.localize("MGT2.Actor.ThisTrait"));
|
||||||
|
if (!confirmed) return;
|
||||||
const element = target.closest("[data-traits-part]");
|
const element = target.closest("[data-traits-part]");
|
||||||
const index = Number(element.dataset.traitsPart);
|
const index = Number(element.dataset.traitsPart);
|
||||||
const traits = foundry.utils.deepClone(this.actor.system.personal.traits);
|
const traits = foundry.utils.deepClone(this.actor.system.personal.traits);
|
||||||
@@ -832,4 +900,323 @@ export default class TravellerCharacterSheet extends MGT2ActorSheet {
|
|||||||
this.actor.system.personal.speciesText.descriptionLong
|
this.actor.system.personal.speciesText.descriptionLong
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async #onHeal(event, target) {
|
||||||
|
event.preventDefault();
|
||||||
|
const healType = target.dataset.healType;
|
||||||
|
|
||||||
|
if (canvas.tokens.controlled.length === 0) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("MGT2.Errors.NoTokenSelected"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (healType === "firstaid") {
|
||||||
|
// Find Medicine skill to pre-select
|
||||||
|
// Use normalized string matching to handle accents
|
||||||
|
const medSkill = this.actor.items.find(i => {
|
||||||
|
if (i.type !== "talent" || i.system.subType !== "skill") return false;
|
||||||
|
const normalized = i.name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
||||||
|
return normalized.includes("medecin") || normalized.includes("medicine");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only EDU characteristic available for First Aid
|
||||||
|
const characteristics = [
|
||||||
|
{ _id: "education", name: game.i18n.localize("MGT2.Characteristics.education.name") }
|
||||||
|
];
|
||||||
|
|
||||||
|
const rollOptions = {
|
||||||
|
rollTypeName: game.i18n.localize("MGT2.Healing.FirstAid"),
|
||||||
|
rollObjectName: this.actor.name,
|
||||||
|
characteristics: characteristics, // Only EDU
|
||||||
|
characteristic: "education", // Pre-selected
|
||||||
|
skill: medSkill?.id ?? "", // Medicine skill ID for pre-selection (must match _id in array)
|
||||||
|
skillName: medSkill?.name ?? game.i18n.localize("MGT2.Healing.NoMedicineSkill"), // Display name
|
||||||
|
skillLevel: medSkill?.system.level ?? -3, // -3 if not found
|
||||||
|
skills: medSkill ? [{ _id: medSkill.id, name: medSkill.name, level: medSkill.system.level }] : [],
|
||||||
|
difficulty: "Average", // First Aid difficulty is 8 (Average)
|
||||||
|
showHeal: true,
|
||||||
|
healType: MGT2.HealingType.FIRST_AID,
|
||||||
|
};
|
||||||
|
const userRollData = await RollPromptHelper.roll(rollOptions);
|
||||||
|
if (userRollData) {
|
||||||
|
// Build formula with all DMs — same pattern as standard skill roll
|
||||||
|
const rollFormulaParts = [];
|
||||||
|
const rollModifiers = [];
|
||||||
|
|
||||||
|
if (userRollData.diceModifier) {
|
||||||
|
rollFormulaParts.push("3d6");
|
||||||
|
rollFormulaParts.push(userRollData.diceModifier);
|
||||||
|
} else {
|
||||||
|
rollFormulaParts.push("2d6");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRollData.characteristic) {
|
||||||
|
const c = this.actor.system.characteristics[userRollData.characteristic];
|
||||||
|
rollFormulaParts.push(MGT2Helper.getFormulaDM(c.dm));
|
||||||
|
rollModifiers.push(game.i18n.localize(`MGT2.Characteristics.${userRollData.characteristic}.name`) + MGT2Helper.getDisplayDM(c.dm));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRollData.skill && userRollData.skill !== "") {
|
||||||
|
if (userRollData.skill === "NP") {
|
||||||
|
rollFormulaParts.push("-3");
|
||||||
|
rollModifiers.push(game.i18n.localize("MGT2.Items.NotProficient"));
|
||||||
|
} else {
|
||||||
|
const skillObj = this.actor.getEmbeddedDocument("Item", userRollData.skill);
|
||||||
|
rollFormulaParts.push(MGT2Helper.getFormulaDM(skillObj.system.level));
|
||||||
|
rollModifiers.push(skillObj.getRollDisplay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRollData.customDM && userRollData.customDM !== "") {
|
||||||
|
let s = userRollData.customDM.trim();
|
||||||
|
if (/^[0-9]/.test(s)) rollFormulaParts.push("+");
|
||||||
|
rollFormulaParts.push(s);
|
||||||
|
rollModifiers.push("DM " + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rollFormula = rollFormulaParts.join("");
|
||||||
|
const roll = await new Roll(rollFormula, this.actor.getRollData()).roll();
|
||||||
|
|
||||||
|
// Difficulty for First Aid is Average (8)
|
||||||
|
const difficulty = 8;
|
||||||
|
const effect = roll.total - difficulty;
|
||||||
|
const isSuccess = effect >= 0;
|
||||||
|
const healing = isSuccess ? Math.max(1, effect) : 0;
|
||||||
|
|
||||||
|
const cardButtons = isSuccess
|
||||||
|
? [{ label: game.i18n.localize("MGT2.Healing.ApplyHealing"), action: "healing" }]
|
||||||
|
: [];
|
||||||
|
|
||||||
|
const chatData = {
|
||||||
|
user: game.user.id,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
formula: roll._formula,
|
||||||
|
tooltip: await roll.getTooltip(),
|
||||||
|
total: Math.round(roll.total * 100) / 100,
|
||||||
|
rollTypeName: game.i18n.localize("MGT2.Healing.FirstAid"),
|
||||||
|
rollObjectName: this.actor.name,
|
||||||
|
rollModifiers: rollModifiers,
|
||||||
|
rollDifficulty: difficulty,
|
||||||
|
rollDifficultyLabel: MGT2Helper.getDifficultyDisplay("Average"),
|
||||||
|
rollEffectStr: isSuccess ? effect.toString() : undefined,
|
||||||
|
healingAmount: isSuccess ? healing : undefined,
|
||||||
|
rollSuccess: isSuccess || undefined,
|
||||||
|
rollFailure: !isSuccess || undefined,
|
||||||
|
showButtons: isSuccess,
|
||||||
|
hasDamage: false,
|
||||||
|
showRollDamage: false,
|
||||||
|
cardButtons: cardButtons,
|
||||||
|
};
|
||||||
|
|
||||||
|
const html = await foundry.applications.handlebars.renderTemplate("systems/mgt2/templates/chat/roll.html", chatData);
|
||||||
|
chatData.content = html;
|
||||||
|
chatData.flags = { mgt2: { healing: { amount: healing } } };
|
||||||
|
|
||||||
|
return roll.toMessage(chatData);
|
||||||
|
}
|
||||||
|
} else if (healType === "surgery") {
|
||||||
|
// Find Medicine skill to pre-select (same as first aid)
|
||||||
|
const medSkill = this.actor.items.find(i => {
|
||||||
|
if (i.type !== "talent" || i.system.subType !== "skill") return false;
|
||||||
|
const normalized = i.name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
||||||
|
return normalized.includes("medecin") || normalized.includes("medicine");
|
||||||
|
});
|
||||||
|
|
||||||
|
const characteristics = [
|
||||||
|
{ _id: "education", name: game.i18n.localize("MGT2.Characteristics.education.name") }
|
||||||
|
];
|
||||||
|
|
||||||
|
const rollOptions = {
|
||||||
|
rollTypeName: game.i18n.localize("MGT2.Healing.Surgery"),
|
||||||
|
rollObjectName: this.actor.name,
|
||||||
|
characteristics: characteristics,
|
||||||
|
characteristic: "education",
|
||||||
|
skill: medSkill?.id ?? "",
|
||||||
|
skillName: medSkill?.name ?? game.i18n.localize("MGT2.Healing.NoMedicineSkill"),
|
||||||
|
skillLevel: medSkill?.system.level ?? -3,
|
||||||
|
skills: medSkill ? [{ _id: medSkill.id, name: medSkill.name, level: medSkill.system.level }] : [],
|
||||||
|
difficulty: "Average",
|
||||||
|
showHeal: true,
|
||||||
|
healType: MGT2.HealingType.SURGERY,
|
||||||
|
};
|
||||||
|
const userRollData = await RollPromptHelper.roll(rollOptions);
|
||||||
|
if (userRollData) {
|
||||||
|
// Build formula with all DMs — same pattern as standard skill roll
|
||||||
|
const rollFormulaParts = [];
|
||||||
|
const rollModifiers = [];
|
||||||
|
|
||||||
|
if (userRollData.diceModifier) {
|
||||||
|
rollFormulaParts.push("3d6");
|
||||||
|
rollFormulaParts.push(userRollData.diceModifier);
|
||||||
|
} else {
|
||||||
|
rollFormulaParts.push("2d6");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRollData.characteristic) {
|
||||||
|
const c = this.actor.system.characteristics[userRollData.characteristic];
|
||||||
|
rollFormulaParts.push(MGT2Helper.getFormulaDM(c.dm));
|
||||||
|
rollModifiers.push(game.i18n.localize(`MGT2.Characteristics.${userRollData.characteristic}.name`) + MGT2Helper.getDisplayDM(c.dm));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRollData.skill && userRollData.skill !== "") {
|
||||||
|
if (userRollData.skill === "NP") {
|
||||||
|
rollFormulaParts.push("-3");
|
||||||
|
rollModifiers.push(game.i18n.localize("MGT2.Items.NotProficient"));
|
||||||
|
} else {
|
||||||
|
const skillObj = this.actor.getEmbeddedDocument("Item", userRollData.skill);
|
||||||
|
rollFormulaParts.push(MGT2Helper.getFormulaDM(skillObj.system.level));
|
||||||
|
rollModifiers.push(skillObj.getRollDisplay());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userRollData.customDM && userRollData.customDM !== "") {
|
||||||
|
let s = userRollData.customDM.trim();
|
||||||
|
if (/^[0-9]/.test(s)) rollFormulaParts.push("+");
|
||||||
|
rollFormulaParts.push(s);
|
||||||
|
rollModifiers.push("DM " + s);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rollFormula = rollFormulaParts.join("");
|
||||||
|
const roll = await new Roll(rollFormula, this.actor.getRollData()).roll();
|
||||||
|
|
||||||
|
// Difficulty for Surgery is Average (8)
|
||||||
|
const difficulty = 8;
|
||||||
|
const effect = roll.total - difficulty;
|
||||||
|
const isSuccess = effect >= 0;
|
||||||
|
|
||||||
|
// Success: heal Math.max(1, effect); Failure: patient takes 3 + |effect| damage
|
||||||
|
const healing = isSuccess ? Math.max(1, effect) : 0;
|
||||||
|
const surgeryDamage = isSuccess ? 0 : 3 + Math.abs(effect);
|
||||||
|
|
||||||
|
const cardButtons = [];
|
||||||
|
if (isSuccess) {
|
||||||
|
cardButtons.push({ label: game.i18n.localize("MGT2.Healing.ApplyHealing"), action: "healing" });
|
||||||
|
} else {
|
||||||
|
cardButtons.push({ label: game.i18n.localize("MGT2.Healing.ApplySurgeryDamage"), action: "surgeryDamage" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatData = {
|
||||||
|
user: game.user.id,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
formula: roll._formula,
|
||||||
|
tooltip: await roll.getTooltip(),
|
||||||
|
total: Math.round(roll.total * 100) / 100,
|
||||||
|
rollTypeName: game.i18n.localize("MGT2.Healing.Surgery"),
|
||||||
|
rollObjectName: this.actor.name,
|
||||||
|
rollModifiers: rollModifiers,
|
||||||
|
rollDifficulty: difficulty,
|
||||||
|
rollDifficultyLabel: MGT2Helper.getDifficultyDisplay("Average"),
|
||||||
|
rollEffectStr: effect.toString(),
|
||||||
|
healingAmount: isSuccess ? healing : undefined,
|
||||||
|
surgeryDamageAmount: isSuccess ? undefined : surgeryDamage,
|
||||||
|
rollSuccess: isSuccess || undefined,
|
||||||
|
rollFailure: !isSuccess || undefined,
|
||||||
|
showButtons: true,
|
||||||
|
hasDamage: false,
|
||||||
|
showRollDamage: false,
|
||||||
|
cardButtons: cardButtons,
|
||||||
|
};
|
||||||
|
|
||||||
|
const html = await foundry.applications.handlebars.renderTemplate("systems/mgt2/templates/chat/roll.html", chatData);
|
||||||
|
chatData.content = html;
|
||||||
|
chatData.flags = { mgt2: { surgery: { healing, surgeryDamage } } };
|
||||||
|
|
||||||
|
return roll.toMessage(chatData);
|
||||||
|
}
|
||||||
|
} else if (healType === "medical") {
|
||||||
|
const result = await CharacterPrompts.openHealingDays();
|
||||||
|
if (result) {
|
||||||
|
const endMD = this.actor.system.characteristics.endurance.dm;
|
||||||
|
const medSkill = this.actor.items.find(i =>
|
||||||
|
i.type === "talent" &&
|
||||||
|
i.system.subType === "skill" &&
|
||||||
|
(i.name.toLowerCase().includes("medecin") || i.name.toLowerCase().includes("medicine"))
|
||||||
|
);
|
||||||
|
const skillValue = medSkill ? medSkill.system.level : 0;
|
||||||
|
const days = result.days;
|
||||||
|
const healingPerDay = Math.max(1, 3 + endMD + skillValue);
|
||||||
|
const totalHealing = healingPerDay * days;
|
||||||
|
|
||||||
|
const rollModifiers = [
|
||||||
|
`3 (base)`,
|
||||||
|
`${endMD >= 0 ? "+" : ""}${endMD} END`,
|
||||||
|
`+${skillValue} ${medSkill?.name ?? "Médecine"}`,
|
||||||
|
`× ${days} ${game.i18n.localize("MGT2.RollPrompt.Days").toLowerCase()}`
|
||||||
|
];
|
||||||
|
|
||||||
|
const templateData = {
|
||||||
|
rollObjectName: this.actor.name,
|
||||||
|
rollTypeName: game.i18n.localize("MGT2.Healing.MedicalCare"),
|
||||||
|
rollModifiers,
|
||||||
|
formula: `${healingPerDay} ${game.i18n.localize("MGT2.Items.PerDay")}`,
|
||||||
|
tooltip: "",
|
||||||
|
total: totalHealing,
|
||||||
|
rollSuccess: true,
|
||||||
|
showButtons: true,
|
||||||
|
cardButtons: [
|
||||||
|
{ action: "healing", label: game.i18n.localize("MGT2.Healing.ApplyHealing") }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const content = await renderTemplate(
|
||||||
|
"systems/mgt2/templates/chat/roll.html",
|
||||||
|
templateData
|
||||||
|
);
|
||||||
|
await ChatMessage.create({
|
||||||
|
user: game.user.id,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
content,
|
||||||
|
flags: { mgt2: { healing: { amount: totalHealing } } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (healType === "natural") {
|
||||||
|
const result = await CharacterPrompts.openHealingDays();
|
||||||
|
if (result) {
|
||||||
|
const endMD = this.actor.system.characteristics.endurance.dm;
|
||||||
|
let totalAmount = 0;
|
||||||
|
const rolls = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < result.days; i++) {
|
||||||
|
const roll = await new Roll("1d6").evaluate();
|
||||||
|
const dayHealing = Math.max(1, roll.total + endMD);
|
||||||
|
rolls.push({ roll, dayHealing });
|
||||||
|
totalAmount += dayHealing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build roll details
|
||||||
|
const rollDisplay = rolls.map((r, idx) =>
|
||||||
|
`<div><strong>${game.i18n.localize("MGT2.RollPrompt.Days")} ${idx + 1}:</strong> 1d6 = ${r.roll.total} + ${endMD > 0 ? "+" : ""}${endMD} = <strong>${r.dayHealing}</strong></div>`
|
||||||
|
).join("");
|
||||||
|
|
||||||
|
const chatData = {
|
||||||
|
user: game.user.id,
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
|
||||||
|
content: `<div class="mgt2-chat-roll">
|
||||||
|
<div class="mgt2-roll-header">
|
||||||
|
<span class="mgt2-roll-char-name">${this.actor.name}</span>
|
||||||
|
<div class="mgt2-roll-meta">
|
||||||
|
<span class="mgt2-roll-type">${game.i18n.localize("MGT2.Healing.NaturalHealing")}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mgt2-roll-modifier">${result.days} ${game.i18n.localize("MGT2.RollPrompt.Days")}</div>
|
||||||
|
<div style="padding: 8px 0; font-size: 0.9em;">
|
||||||
|
${rollDisplay}
|
||||||
|
</div>
|
||||||
|
<div class="mgt2-effect is-success">
|
||||||
|
${game.i18n.localize("MGT2.Chat.Roll.Effect")} <span class="mgt2-effect-value">${totalAmount}</span>
|
||||||
|
</div>
|
||||||
|
</div>`,
|
||||||
|
flags: { mgt2: { healing: { amount: totalAmount } } }
|
||||||
|
};
|
||||||
|
await ChatMessage.create(chatData);
|
||||||
|
|
||||||
|
// Apply healing immediately
|
||||||
|
await this.actor.applyHealing(totalAmount);
|
||||||
|
ui.notifications.info(
|
||||||
|
game.i18n.format("MGT2.Notifications.HealingApplied",
|
||||||
|
{ name: this.actor.name, amount: totalAmount })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import MGT2ActorSheet from "./base-actor-sheet.mjs";
|
import MGT2ActorSheet from "./base-actor-sheet.mjs";
|
||||||
|
import { RollPromptHelper } from "../../roll-prompt.js";
|
||||||
|
import { MGT2Helper } from "../../helper.js";
|
||||||
|
|
||||||
|
const { renderTemplate } = foundry.applications.handlebars;
|
||||||
|
|
||||||
/** Convert Traveller dice notation (e.g. "2D", "4D+2", "3D6") to FoundryVTT formula */
|
/** Convert Traveller dice notation (e.g. "2D", "4D+2", "3D6") to FoundryVTT formula */
|
||||||
function normalizeDice(formula) {
|
function normalizeDice(formula) {
|
||||||
@@ -46,13 +50,16 @@ export default class TravellerCreatureSheet extends MGT2ActorSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
tabGroups = { primary: "skills" }
|
tabGroups = { primary: "combat" }
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _prepareContext() {
|
async _prepareContext() {
|
||||||
const context = await super._prepareContext();
|
const context = await super._prepareContext();
|
||||||
const actor = this.document;
|
const actor = this.document;
|
||||||
|
const enrich = (html) => foundry.applications.ux.TextEditor.implementation.enrichHTML(html ?? "", { async: true });
|
||||||
|
|
||||||
|
context.enrichedBiography = await enrich(actor.system.biography);
|
||||||
|
context.enrichedNotes = await enrich(actor.system.notes);
|
||||||
context.sizeLabel = this._getSizeLabel(actor.system.life.max);
|
context.sizeLabel = this._getSizeLabel(actor.system.life.max);
|
||||||
context.sizeTraitLabel = this._getSizeTrait(actor.system.life.max);
|
context.sizeTraitLabel = this._getSizeTrait(actor.system.life.max);
|
||||||
context.config = CONFIG.MGT2;
|
context.config = CONFIG.MGT2;
|
||||||
@@ -88,101 +95,36 @@ export default class TravellerCreatureSheet extends MGT2ActorSheet {
|
|||||||
return "Grand (+6)";
|
return "Grand (+6)";
|
||||||
}
|
}
|
||||||
|
|
||||||
// ───────────────────────────────────────────────────────── Roll Handlers
|
// ───────────────────────────────────────────────────────── Roll Helpers
|
||||||
|
|
||||||
/** Roll an attack (damage) with optional difficulty dialog */
|
static async #postCreatureRoll({ actor, roll, rollLabel, dm, difficulty, difficultyLabel, rollMode, extraTooltip }) {
|
||||||
static async #onRollAttack(event, target) {
|
const diffTarget = MGT2Helper.getDifficultyValue(difficulty ?? "Average");
|
||||||
const index = parseInt(target.dataset.index ?? 0);
|
const hasDifficulty = !!difficulty;
|
||||||
const actor = this.document;
|
const success = hasDifficulty ? roll.total >= diffTarget : true;
|
||||||
const attack = actor.system.attacks[index];
|
const effect = roll.total - diffTarget;
|
||||||
if (!attack) return;
|
const effectStr = (effect >= 0 ? "+" : "") + effect;
|
||||||
|
|
||||||
const rollFormula = normalizeDice(attack.damage);
|
const diceRawTotal = roll.dice.reduce((s, d) => s + d.total, 0);
|
||||||
|
const breakdownParts = [game.i18n.localize("MGT2.Chat.Roll.Dice") + " " + diceRawTotal];
|
||||||
const roll = await new Roll(rollFormula).evaluate();
|
if (dm !== 0) breakdownParts.push(`DM ${dm >= 0 ? "+" : ""}${dm}`);
|
||||||
const total = roll.total;
|
if (hasDifficulty) breakdownParts.push(game.i18n.localize("MGT2.Chat.Roll.Effect") + " " + effectStr);
|
||||||
|
if (extraTooltip) breakdownParts.push(extraTooltip);
|
||||||
await roll.toMessage({
|
const rollBreakdown = breakdownParts.join(" | ");
|
||||||
speaker: ChatMessage.getSpeaker({ actor }),
|
|
||||||
flavor: `<strong>${actor.name}</strong> — ${attack.name}`,
|
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Roll a skill check (2d6 + level vs difficulty) */
|
|
||||||
static async #onRollSkill(event, target) {
|
|
||||||
const index = parseInt(target.dataset.index ?? 0);
|
|
||||||
const actor = this.document;
|
|
||||||
const skill = actor.system.skills[index];
|
|
||||||
if (!skill) return;
|
|
||||||
|
|
||||||
const htmlContent = await renderTemplate(
|
|
||||||
"systems/mgt2/templates/actors/creature-roll-prompt.html",
|
|
||||||
{
|
|
||||||
skillName: skill.name,
|
|
||||||
skillLevel: skill.level,
|
|
||||||
config: CONFIG.MGT2
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = await foundry.applications.api.DialogV2.wait({
|
|
||||||
window: { title: game.i18n.localize("MGT2.Creature.RollSkill") + " — " + skill.name },
|
|
||||||
content: htmlContent,
|
|
||||||
rejectClose: false,
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
action: "boon",
|
|
||||||
label: game.i18n.localize("MGT2.RollPrompt.Boon"),
|
|
||||||
callback: (event, button, dialog) => {
|
|
||||||
const fd = new foundry.applications.ux.FormDataExtended(dialog.element.querySelector("form")).object;
|
|
||||||
fd.diceModifier = "dl";
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "roll",
|
|
||||||
label: game.i18n.localize("MGT2.RollPrompt.Roll"),
|
|
||||||
icon: '<i class="fa-solid fa-dice"></i>',
|
|
||||||
default: true,
|
|
||||||
callback: (event, button, dialog) =>
|
|
||||||
new foundry.applications.ux.FormDataExtended(dialog.element.querySelector("form")).object
|
|
||||||
},
|
|
||||||
{
|
|
||||||
action: "bane",
|
|
||||||
label: game.i18n.localize("MGT2.RollPrompt.Bane"),
|
|
||||||
callback: (event, button, dialog) => {
|
|
||||||
const fd = new foundry.applications.ux.FormDataExtended(dialog.element.querySelector("form")).object;
|
|
||||||
fd.diceModifier = "dh";
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result) return;
|
|
||||||
|
|
||||||
const dm = parseInt(result.dm ?? 0) + (skill.level ?? 0);
|
|
||||||
const modifier = result.diceModifier ?? "";
|
|
||||||
const difficultyTarget = parseInt(result.difficulty ?? 8);
|
|
||||||
const difficultyLabel = result.difficultyLabel ?? "";
|
|
||||||
|
|
||||||
const diceFormula = modifier ? `3d6${modifier}` : "2d6";
|
|
||||||
const fullFormula = dm !== 0 ? `${diceFormula} + ${dm}` : diceFormula;
|
|
||||||
|
|
||||||
const roll = await new Roll(fullFormula).evaluate();
|
|
||||||
const success = roll.total >= difficultyTarget;
|
|
||||||
|
|
||||||
const chatData = {
|
const chatData = {
|
||||||
creatureName: actor.name,
|
creatureName: actor.name,
|
||||||
creatureImg: actor.img,
|
creatureImg: actor.img,
|
||||||
rollLabel: skill.name.toUpperCase(),
|
rollLabel,
|
||||||
formula: fullFormula,
|
formula: roll.formula,
|
||||||
total: roll.total,
|
total: roll.total,
|
||||||
tooltip: await roll.getTooltip(),
|
tooltip: await roll.getTooltip(),
|
||||||
difficulty: difficultyTarget,
|
rollBreakdown,
|
||||||
difficultyLabel,
|
difficulty: hasDifficulty ? diffTarget : null,
|
||||||
success,
|
difficultyLabel: difficultyLabel ?? MGT2Helper.getDifficultyDisplay(difficulty),
|
||||||
failure: !success,
|
success: hasDifficulty ? success : null,
|
||||||
|
failure: hasDifficulty ? !success : null,
|
||||||
|
effect: hasDifficulty ? effect : null,
|
||||||
|
effectStr: hasDifficulty ? effectStr : null,
|
||||||
modifiers: dm !== 0 ? [`DM ${dm >= 0 ? "+" : ""}${dm}`] : [],
|
modifiers: dm !== 0 ? [`DM ${dm >= 0 ? "+" : ""}${dm}`] : [],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -195,8 +137,125 @@ export default class TravellerCreatureSheet extends MGT2ActorSheet {
|
|||||||
content: chatContent,
|
content: chatContent,
|
||||||
speaker: ChatMessage.getSpeaker({ actor }),
|
speaker: ChatMessage.getSpeaker({ actor }),
|
||||||
rolls: [roll],
|
rolls: [roll],
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
rollMode: rollMode ?? game.settings.get("core", "rollMode"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return { success, effect, total: roll.total };
|
||||||
|
}
|
||||||
|
|
||||||
|
// ───────────────────────────────────────────────────────── Roll Handlers
|
||||||
|
|
||||||
|
/** Roll a skill check (2d6 + level vs difficulty) — uses unified dialog */
|
||||||
|
static async #onRollSkill(event, target) {
|
||||||
|
const index = parseInt(target.dataset.index ?? 0);
|
||||||
|
const actor = this.document;
|
||||||
|
const skill = actor.system.skills[index];
|
||||||
|
if (!skill) return;
|
||||||
|
|
||||||
|
const result = await RollPromptHelper.roll({
|
||||||
|
isCreature: true,
|
||||||
|
showSkillSelector: false,
|
||||||
|
skillName: skill.name,
|
||||||
|
skillLevel: skill.level,
|
||||||
|
difficulty: "Average",
|
||||||
|
title: game.i18n.localize("MGT2.Creature.RollSkill") + " — " + skill.name,
|
||||||
|
});
|
||||||
|
if (!result) return;
|
||||||
|
|
||||||
|
const customDM = parseInt(result.customDM ?? "0", 10) || 0;
|
||||||
|
const skillLevel = parseInt(skill.level ?? 0, 10) || 0;
|
||||||
|
const dm = skillLevel + customDM;
|
||||||
|
const diceModifier = result.diceModifier ?? "";
|
||||||
|
|
||||||
|
// Build formula exactly like character-sheet: parts joined without spaces
|
||||||
|
const parts = [];
|
||||||
|
if (diceModifier) {
|
||||||
|
parts.push("3d6", diceModifier);
|
||||||
|
} else {
|
||||||
|
parts.push("2d6");
|
||||||
|
}
|
||||||
|
if (dm !== 0) parts.push(MGT2Helper.getFormulaDM(dm));
|
||||||
|
const fullFormula = parts.join("");
|
||||||
|
|
||||||
|
const roll = await new Roll(fullFormula).evaluate();
|
||||||
|
const rollLabel = `${skill.name.toUpperCase()} (${skillLevel >= 0 ? "+" : ""}${skillLevel})`;
|
||||||
|
|
||||||
|
const tooltipParts = [`Dés: ${roll.dice.reduce((s, d) => s + d.total, 0)}`];
|
||||||
|
if (skillLevel !== 0) tooltipParts.push(`${skill.name} ${skillLevel >= 0 ? "+" : ""}${skillLevel}`);
|
||||||
|
if (customDM !== 0) tooltipParts.push(`MD perso ${customDM >= 0 ? "+" : ""}${customDM}`);
|
||||||
|
|
||||||
|
await TravellerCreatureSheet.#postCreatureRoll({
|
||||||
|
actor, roll, rollLabel,
|
||||||
|
dm,
|
||||||
|
difficulty: result.difficulty,
|
||||||
|
rollMode: result.rollMode,
|
||||||
|
extraTooltip: tooltipParts.join(" | "),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Roll an attack: dialog with skill selector, then roll 2d6+skill+DM vs difficulty; on success roll damage */
|
||||||
|
static async #onRollAttack(event, target) {
|
||||||
|
const index = parseInt(target.dataset.index ?? 0);
|
||||||
|
const actor = this.document;
|
||||||
|
const attack = actor.system.attacks[index];
|
||||||
|
if (!attack) return;
|
||||||
|
|
||||||
|
const skills = actor.system.skills ?? [];
|
||||||
|
|
||||||
|
const result = await RollPromptHelper.roll({
|
||||||
|
isCreature: true,
|
||||||
|
showSkillSelector: true,
|
||||||
|
creatureSkills: skills,
|
||||||
|
selectedSkillIndex: attack.skill ?? -1,
|
||||||
|
difficulty: "Average",
|
||||||
|
title: game.i18n.localize("MGT2.Creature.RollAttack") + " — " + attack.name,
|
||||||
|
});
|
||||||
|
if (!result) return;
|
||||||
|
|
||||||
|
const skillIndex = parseInt(result.creatureSkillIndex ?? "-1", 10);
|
||||||
|
const chosenSkill = (skillIndex >= 0 && skillIndex < skills.length) ? skills[skillIndex] : null;
|
||||||
|
const skillLevel = parseInt(chosenSkill?.level ?? 0, 10) || 0;
|
||||||
|
const customDM = parseInt(result.customDM ?? "0", 10) || 0;
|
||||||
|
const dm = skillLevel + customDM;
|
||||||
|
const diceModifier = result.diceModifier ?? "";
|
||||||
|
|
||||||
|
// Build formula exactly like character-sheet: parts joined without spaces
|
||||||
|
const parts = [];
|
||||||
|
if (diceModifier) {
|
||||||
|
parts.push("3d6", diceModifier);
|
||||||
|
} else {
|
||||||
|
parts.push("2d6");
|
||||||
|
}
|
||||||
|
if (dm !== 0) parts.push(MGT2Helper.getFormulaDM(dm));
|
||||||
|
const fullFormula = parts.join("");
|
||||||
|
|
||||||
|
const roll = await new Roll(fullFormula).evaluate();
|
||||||
|
const rollLabel = chosenSkill
|
||||||
|
? `${attack.name} — ${chosenSkill.name} (${skillLevel >= 0 ? "+" : ""}${skillLevel})`
|
||||||
|
: attack.name;
|
||||||
|
|
||||||
|
const tooltipParts = [`Dés: ${roll.dice.reduce((s, d) => s + d.total, 0)}`];
|
||||||
|
if (chosenSkill) tooltipParts.push(`${chosenSkill.name} ${skillLevel >= 0 ? "+" : ""}${skillLevel}`);
|
||||||
|
if (customDM !== 0) tooltipParts.push(`MD perso ${customDM >= 0 ? "+" : ""}${customDM}`);
|
||||||
|
|
||||||
|
const { success } = await TravellerCreatureSheet.#postCreatureRoll({
|
||||||
|
actor, roll, rollLabel,
|
||||||
|
dm,
|
||||||
|
difficulty: result.difficulty,
|
||||||
|
rollMode: result.rollMode,
|
||||||
|
extraTooltip: tooltipParts.join(" | "),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Roll damage only on success
|
||||||
|
if (success && attack.damage) {
|
||||||
|
const dmgFormula = normalizeDice(attack.damage);
|
||||||
|
const dmgRoll = await new Roll(dmgFormula).evaluate();
|
||||||
|
await dmgRoll.toMessage({
|
||||||
|
speaker: ChatMessage.getSpeaker({ actor }),
|
||||||
|
flavor: `<strong>${actor.name}</strong> — ${game.i18n.localize("MGT2.Chat.Weapon.Damage")}: ${attack.name} (${attack.damage})`,
|
||||||
|
rollMode: result.rollMode ?? game.settings.get("core", "rollMode"),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ───────────────────────────────────────────────────────── CRUD Handlers
|
// ───────────────────────────────────────────────────────── CRUD Handlers
|
||||||
@@ -223,7 +282,7 @@ export default class TravellerCreatureSheet extends MGT2ActorSheet {
|
|||||||
_getDefaultRow(prop) {
|
_getDefaultRow(prop) {
|
||||||
switch (prop) {
|
switch (prop) {
|
||||||
case "skills": return { name: "", level: 0, note: "" };
|
case "skills": return { name: "", level: 0, note: "" };
|
||||||
case "attacks": return { name: "", damage: "1D", description: "" };
|
case "attacks": return { name: "", damage: "1D", skill: -1, description: "" };
|
||||||
case "traits": return { name: "", value: "", description: "" };
|
case "traits": return { name: "", value: "", description: "" };
|
||||||
default: return {};
|
default: return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ export default class TravellerItemSheet extends HandlebarsApplicationMixin(found
|
|||||||
skills.sort(MGT2Helper.compareByName);
|
skills.sort(MGT2Helper.compareByName);
|
||||||
skills = [{ _id: "NP", name: game.i18n.localize("MGT2.Items.NotProficient") }].concat(skills);
|
skills = [{ _id: "NP", name: game.i18n.localize("MGT2.Items.NotProficient") }].concat(skills);
|
||||||
|
|
||||||
|
const enrich = (html) => foundry.applications.ux.TextEditor.implementation.enrichHTML(html ?? "", { async: true });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
item: item,
|
item: item,
|
||||||
document: item,
|
document: item,
|
||||||
@@ -91,6 +93,10 @@ export default class TravellerItemSheet extends HandlebarsApplicationMixin(found
|
|||||||
weight: weight,
|
weight: weight,
|
||||||
unitlabels: { weight: MGT2Helper.getWeightLabel() },
|
unitlabels: { weight: MGT2Helper.getWeightLabel() },
|
||||||
skills: skills,
|
skills: skills,
|
||||||
|
enrichedDescription: await enrich(item.system.description),
|
||||||
|
enrichedDescriptionLong: await enrich(item.system.descriptionLong),
|
||||||
|
enrichedNotes: await enrich(item.system.notes),
|
||||||
|
enrichedLockedDescription: await enrich(item.system.lockedDescription),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +132,27 @@ export default class TravellerItemSheet extends HandlebarsApplicationMixin(found
|
|||||||
bind(".options-delete", TravellerItemSheet.#onOptionDelete);
|
bind(".options-delete", TravellerItemSheet.#onOptionDelete);
|
||||||
bind(".modifiers-create", TravellerItemSheet.#onModifierCreate);
|
bind(".modifiers-create", TravellerItemSheet.#onModifierCreate);
|
||||||
bind(".modifiers-delete", TravellerItemSheet.#onModifierDelete);
|
bind(".modifiers-delete", TravellerItemSheet.#onModifierDelete);
|
||||||
|
|
||||||
|
// Activate ProseMirror editors for HTMLField fields
|
||||||
|
for (const btn of html.querySelectorAll(".editor-edit")) {
|
||||||
|
btn.addEventListener("click", async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const editorWrapper = btn.closest(".editor");
|
||||||
|
if (!editorWrapper) return;
|
||||||
|
const editorContent = editorWrapper.querySelector(".editor-content");
|
||||||
|
if (!editorContent || editorContent.classList.contains("ProseMirror")) return;
|
||||||
|
const target = editorContent.dataset.edit;
|
||||||
|
const value = foundry.utils.getProperty(this.document, target) ?? "";
|
||||||
|
btn.remove();
|
||||||
|
editorWrapper.classList.add("prosemirror");
|
||||||
|
await ProseMirrorEditor.create(editorContent, value, {
|
||||||
|
document: this.document,
|
||||||
|
fieldName: target,
|
||||||
|
plugins: {},
|
||||||
|
collaborate: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_activateTabGroups() {
|
_activateTabGroups() {
|
||||||
|
|||||||
@@ -21,4 +21,15 @@ export default class TravellerVehiculeSheet extends MGT2ActorSheet {
|
|||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
tabGroups = { primary: "stats" }
|
tabGroups = { primary: "stats" }
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext() {
|
||||||
|
const context = await super._prepareContext();
|
||||||
|
const actor = this.document;
|
||||||
|
const enrich = (html) => foundry.applications.ux.TextEditor.implementation.enrichHTML(html ?? "", { async: true });
|
||||||
|
|
||||||
|
context.enrichedDescription = await enrich(actor.system.description);
|
||||||
|
context.enrichedNotes = await enrich(actor.system.notes);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,11 +20,17 @@ export class ChatHelper {
|
|||||||
|
|
||||||
element.querySelectorAll('button[data-action="healing"]').forEach(el => {
|
element.querySelectorAll('button[data-action="healing"]').forEach(el => {
|
||||||
el.addEventListener('click', async event => {
|
el.addEventListener('click', async event => {
|
||||||
ui.notifications.warn("healing");
|
await this._applyChatCardHealing(message, event);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
element.querySelectorAll('button[data-index]').forEach(el => {
|
element.querySelectorAll('button[data-action="surgeryDamage"]').forEach(el => {
|
||||||
|
el.addEventListener('click', async event => {
|
||||||
|
await this._applyChatCardSurgeryDamage(message, event);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
element.querySelectorAll('button[data-index]:not([data-action])').forEach(el => {
|
||||||
el.addEventListener('click', async event => {
|
el.addEventListener('click', async event => {
|
||||||
await this._processRollButtonEvent(message, event);
|
await this._processRollButtonEvent(message, event);
|
||||||
});
|
});
|
||||||
@@ -90,10 +96,41 @@ export class ChatHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static _applyChatCardDamage(message, event) {
|
static _applyChatCardDamage(message, event) {
|
||||||
|
if (canvas.tokens.controlled.length === 0) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("MGT2.Errors.NoTokenSelected"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const roll = message.rolls[0];
|
const roll = message.rolls[0];
|
||||||
return Promise.all(canvas.tokens.controlled.map(t => {
|
return Promise.all(canvas.tokens.controlled.map(t => {
|
||||||
const a = t.actor;
|
const a = t.actor;
|
||||||
return a.applyDamage(roll.total);
|
return a.applyDamage(roll.total);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _applyChatCardHealing(message, event) {
|
||||||
|
if (canvas.tokens.controlled.length === 0) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("MGT2.Errors.NoTokenSelected"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// For First Aid/Surgery healing, use amount from flags; otherwise use roll total
|
||||||
|
const amount = message.flags?.mgt2?.healing?.amount
|
||||||
|
?? message.flags?.mgt2?.surgery?.healing
|
||||||
|
?? Math.max(1, message.rolls[0].total);
|
||||||
|
return Promise.all(canvas.tokens.controlled.map(t => {
|
||||||
|
const a = t.actor;
|
||||||
|
return a.applyHealing(amount);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
static _applyChatCardSurgeryDamage(message, event) {
|
||||||
|
if (canvas.tokens.controlled.length === 0) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("MGT2.Errors.NoTokenSelected"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const amount = message.flags?.mgt2?.surgery?.surgeryDamage ?? 3;
|
||||||
|
return Promise.all(canvas.tokens.controlled.map(t => {
|
||||||
|
const a = t.actor;
|
||||||
|
return a.applyDamage(amount, { ignoreArmor: true });
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ MGT2.SpeedBands = Object.freeze({
|
|||||||
VerySlow: "MGT2.SpeedBands.VerySlow",
|
VerySlow: "MGT2.SpeedBands.VerySlow",
|
||||||
Slow: "MGT2.SpeedBands.Slow",
|
Slow: "MGT2.SpeedBands.Slow",
|
||||||
Medium: "MGT2.SpeedBands.Medium",
|
Medium: "MGT2.SpeedBands.Medium",
|
||||||
High: "MGT2.SpeedBands.High.",
|
High: "MGT2.SpeedBands.High",
|
||||||
Fast: "MGT2.SpeedBands.Fast",
|
Fast: "MGT2.SpeedBands.Fast",
|
||||||
VeryFast: "MGT2.SpeedBands.VeryFast",
|
VeryFast: "MGT2.SpeedBands.VeryFast",
|
||||||
Subsonic: "MGT2.SpeedBands.Subsonic",
|
Subsonic: "MGT2.SpeedBands.Subsonic",
|
||||||
@@ -177,4 +177,11 @@ MGT2.CreatureBehaviorSubType = Object.freeze({
|
|||||||
necrophage: "MGT2.CreatureBehaviorSubType.necrophage",
|
necrophage: "MGT2.CreatureBehaviorSubType.necrophage",
|
||||||
reducteur: "MGT2.CreatureBehaviorSubType.reducteur",
|
reducteur: "MGT2.CreatureBehaviorSubType.reducteur",
|
||||||
opportuniste: "MGT2.CreatureBehaviorSubType.opportuniste"
|
opportuniste: "MGT2.CreatureBehaviorSubType.opportuniste"
|
||||||
|
});
|
||||||
|
|
||||||
|
MGT2.HealingType = Object.freeze({
|
||||||
|
FIRST_AID: "MGT2.Healing.FirstAid",
|
||||||
|
SURGERY: "MGT2.Healing.Surgery",
|
||||||
|
MEDICAL_CARE: "MGT2.Healing.MedicalCare",
|
||||||
|
NATURAL_HEALING: "MGT2.Healing.NaturalHealing"
|
||||||
});
|
});
|
||||||
@@ -47,7 +47,9 @@ export default class CharacterData extends foundry.abstract.TypeDataModel {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
health: new fields.SchemaField({
|
health: new fields.SchemaField({
|
||||||
radiations: new fields.NumberField({ required: false, initial: 0, min: 0, integer: true })
|
radiations: new fields.NumberField({ required: false, initial: 0, min: 0, integer: true }),
|
||||||
|
lastFirstAidDate: new fields.StringField({ required: false, blank: true, trim: true }),
|
||||||
|
healingRecoveryMode: new fields.StringField({ required: false, blank: true, trim: true, initial: "" })
|
||||||
}),
|
}),
|
||||||
study: new fields.SchemaField({
|
study: new fields.SchemaField({
|
||||||
skill: new fields.StringField({ required: false, blank: true, trim: true, initial: "" }),
|
skill: new fields.StringField({ required: false, blank: true, trim: true, initial: "" }),
|
||||||
@@ -61,7 +63,7 @@ export default class CharacterData extends foundry.abstract.TypeDataModel {
|
|||||||
debt: new fields.NumberField({ required: true, initial: 0, min: 0, integer: true }),
|
debt: new fields.NumberField({ required: true, initial: 0, min: 0, integer: true }),
|
||||||
livingCost: new fields.NumberField({ required: true, initial: 0, min: 0, integer: true }),
|
livingCost: new fields.NumberField({ required: true, initial: 0, min: 0, integer: true }),
|
||||||
monthlyShipPayments: new fields.NumberField({ required: true, initial: 0, min: 0, integer: true }),
|
monthlyShipPayments: new fields.NumberField({ required: true, initial: 0, min: 0, integer: true }),
|
||||||
notes: new fields.StringField({ required: false, blank: true, trim: true, initial: "" })
|
notes: new fields.HTMLField({ required: false, blank: true, trim: true })
|
||||||
}),
|
}),
|
||||||
containerView: new fields.StringField({ required: false, blank: true, trim: true, initial: "" }),
|
containerView: new fields.StringField({ required: false, blank: true, trim: true, initial: "" }),
|
||||||
containerDropIn: new fields.StringField({ required: false, blank: true, trim: true, initial: "" }),
|
containerDropIn: new fields.StringField({ required: false, blank: true, trim: true, initial: "" }),
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export default class CreatureData extends foundry.abstract.TypeDataModel {
|
|||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
name: new fields.StringField({ required: true, blank: true, trim: true, initial: "" }),
|
name: new fields.StringField({ required: true, blank: true, trim: true, initial: "" }),
|
||||||
damage: new fields.StringField({ required: true, blank: true, trim: true, initial: "1D" }),
|
damage: new fields.StringField({ required: true, blank: true, trim: true, initial: "1D" }),
|
||||||
|
skill: new fields.NumberField({ required: false, initial: -1, integer: true }),
|
||||||
description: new fields.StringField({ required: false, blank: true, trim: true, initial: "" })
|
description: new fields.StringField({ required: false, blank: true, trim: true, initial: "" })
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function createCharacteristicField(show = true, showMax = false) {
|
|||||||
export class ItemBaseData extends foundry.abstract.TypeDataModel {
|
export class ItemBaseData extends foundry.abstract.TypeDataModel {
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
return {
|
return {
|
||||||
description: new fields.StringField({ required: false, blank: true, trim: true, nullable: true }),
|
description: new fields.HTMLField({ required: false, blank: true, trim: true }),
|
||||||
subType: new fields.StringField({ required: false, blank: false, nullable: true })
|
subType: new fields.StringField({ required: false, blank: false, nullable: true })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default class ItemContainerData extends ItemBaseData {
|
|||||||
schema.weight = new fields.NumberField({ required: false, initial: 0, integer: false });
|
schema.weight = new fields.NumberField({ required: false, initial: 0, integer: false });
|
||||||
schema.weightless = new fields.BooleanField({ required: false, initial: false });
|
schema.weightless = new fields.BooleanField({ required: false, initial: false });
|
||||||
schema.locked = new fields.BooleanField({ required: false, initial: false }); // GM only
|
schema.locked = new fields.BooleanField({ required: false, initial: false }); // GM only
|
||||||
schema.lockedDescription = new fields.StringField({ required: false, blank: true, trim: true, nullable: true });
|
schema.lockedDescription = new fields.HTMLField({ required: false, blank: true, trim: true });
|
||||||
return schema;
|
return schema;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const fields = foundry.data.fields;
|
|||||||
export default class SpeciesData extends foundry.abstract.TypeDataModel {
|
export default class SpeciesData extends foundry.abstract.TypeDataModel {
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
return {
|
return {
|
||||||
description: new fields.StringField({ required: false, blank: true, trim: true, nullable: true }),
|
description: new fields.HTMLField({ required: false, blank: true, trim: true }),
|
||||||
descriptionLong: new fields.HTMLField({ required: false, blank: true, trim: true }),
|
descriptionLong: new fields.HTMLField({ required: false, blank: true, trim: true }),
|
||||||
traits: new fields.ArrayField(
|
traits: new fields.ArrayField(
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ export default class VehiculeData extends foundry.abstract.TypeDataModel {
|
|||||||
}),
|
}),
|
||||||
skills: new fields.SchemaField({
|
skills: new fields.SchemaField({
|
||||||
autopilot: new fields.NumberField({ required: true, initial: 0, integer: true })
|
autopilot: new fields.NumberField({ required: true, initial: 0, integer: true })
|
||||||
})
|
}),
|
||||||
|
description: new fields.HTMLField({ required: false, blank: true, trim: true }),
|
||||||
|
notes: new fields.HTMLField({ required: false, blank: true, trim: true })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,19 +5,39 @@ const { FormDataExtended } = foundry.applications.ux;
|
|||||||
export class RollPromptHelper {
|
export class RollPromptHelper {
|
||||||
|
|
||||||
static async roll(options) {
|
static async roll(options) {
|
||||||
|
// Backward compat: allow (actor, options) or just (options)
|
||||||
|
if (options.rollTypeName || options.characteristics || options.skill !== undefined) {
|
||||||
|
// Normal call with options
|
||||||
|
} else {
|
||||||
|
// Called with (actor, options)
|
||||||
|
options = arguments[1] || options;
|
||||||
|
}
|
||||||
|
|
||||||
const htmlContent = await renderTemplate('systems/mgt2/templates/roll-prompt.html', {
|
const htmlContent = await renderTemplate('systems/mgt2/templates/roll-prompt.html', {
|
||||||
config: CONFIG.MGT2,
|
config: CONFIG.MGT2,
|
||||||
characteristics: options.characteristics,
|
// Character-mode fields
|
||||||
characteristic: options.characteristic,
|
characteristics: options.characteristics ?? [],
|
||||||
skills: options.skills,
|
characteristic: options.characteristic ?? "",
|
||||||
skill: options.skill,
|
skills: options.skills ?? [],
|
||||||
fatigue: options.fatigue,
|
skill: options.skill ?? "",
|
||||||
encumbrance: options.encumbrance,
|
fatigue: options.fatigue ?? false,
|
||||||
difficulty: options.difficulty
|
encumbrance: options.encumbrance ?? false,
|
||||||
|
difficulty: options.difficulty ?? "Average",
|
||||||
|
timeframe: options.timeframe ?? "Normal",
|
||||||
|
customDM: options.customDM ?? "0",
|
||||||
|
rollMode: options.rollMode ?? "publicroll",
|
||||||
|
// Creature-mode flags
|
||||||
|
isCreature: options.isCreature ?? false,
|
||||||
|
creatureSkills: options.creatureSkills ?? [],
|
||||||
|
selectedSkillIndex: options.selectedSkillIndex ?? -1,
|
||||||
|
showSkillSelector: options.showSkillSelector ?? false,
|
||||||
|
skillName: options.skillName ?? "",
|
||||||
|
skillLevel: options.skillLevel ?? 0,
|
||||||
|
// Healing fields
|
||||||
|
showHeal: options.showHeal ?? false,
|
||||||
|
healType: options.healType ?? null
|
||||||
});
|
});
|
||||||
|
|
||||||
const theme = game.settings.get("mgt2", "theme");
|
|
||||||
|
|
||||||
return await DialogV2.wait({
|
return await DialogV2.wait({
|
||||||
window: { title: options.title ?? options.rollTypeName ?? game.i18n.localize("MGT2.RollPrompt.Roll") },
|
window: { title: options.title ?? options.rollTypeName ?? game.i18n.localize("MGT2.RollPrompt.Roll") },
|
||||||
classes: ["mgt2-roll-dialog"],
|
classes: ["mgt2-roll-dialog"],
|
||||||
@@ -54,4 +74,4 @@ export class RollPromptHelper {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export const preloadHandlebarsTemplates = async function() {
|
|||||||
"systems/mgt2/templates/items/weapon-sheet.html",
|
"systems/mgt2/templates/items/weapon-sheet.html",
|
||||||
"systems/mgt2/templates/items/parts/sheet-configuration.html",
|
"systems/mgt2/templates/items/parts/sheet-configuration.html",
|
||||||
"systems/mgt2/templates/items/parts/sheet-physical-item.html",
|
"systems/mgt2/templates/items/parts/sheet-physical-item.html",
|
||||||
|
"systems/mgt2/templates/items/parts/sheet-physical-item-tab.html",
|
||||||
"systems/mgt2/templates/roll-prompt.html",
|
"systems/mgt2/templates/roll-prompt.html",
|
||||||
"systems/mgt2/templates/chat/roll.html",
|
"systems/mgt2/templates/chat/roll.html",
|
||||||
//"systems/mgt2/templates/chat/roll-characteristic.html",
|
//"systems/mgt2/templates/chat/roll-characteristic.html",
|
||||||
@@ -26,10 +27,10 @@ export const preloadHandlebarsTemplates = async function() {
|
|||||||
"systems/mgt2/templates/actors/actor-config-characteristic-sheet.html",
|
"systems/mgt2/templates/actors/actor-config-characteristic-sheet.html",
|
||||||
"systems/mgt2/templates/actors/trait-sheet.html",
|
"systems/mgt2/templates/actors/trait-sheet.html",
|
||||||
"systems/mgt2/templates/actors/creature-sheet.html",
|
"systems/mgt2/templates/actors/creature-sheet.html",
|
||||||
"systems/mgt2/templates/actors/creature-roll-prompt.html",
|
|
||||||
"systems/mgt2/templates/chat/creature-roll.html",
|
"systems/mgt2/templates/chat/creature-roll.html",
|
||||||
"systems/mgt2/templates/editor-fullview.html"
|
"systems/mgt2/templates/editor-fullview.html"
|
||||||
];
|
];
|
||||||
|
|
||||||
return loadTemplates(templatePaths);
|
const loader = foundry.applications?.handlebars?.loadTemplates ?? loadTemplates;
|
||||||
|
return loader(templatePaths);
|
||||||
};
|
};
|
||||||
@@ -213,6 +213,7 @@ ul
|
|||||||
flex-direction: row
|
flex-direction: row
|
||||||
align-content: flex-start
|
align-content: flex-start
|
||||||
flex-wrap: nowrap
|
flex-wrap: nowrap
|
||||||
|
min-height: 330px
|
||||||
.tab
|
.tab
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
@@ -277,3 +278,15 @@ ul
|
|||||||
flex-shrink: 0
|
flex-shrink: 0
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: row
|
flex-direction: row
|
||||||
|
|
||||||
|
|
||||||
|
// ── HTMLField editor min-height in notes/biography/finance tabs ──────────────
|
||||||
|
.mgt2.character
|
||||||
|
.tab[data-tab="notes"],
|
||||||
|
.tab[data-tab="biography"],
|
||||||
|
.tab[data-tab="finance"]
|
||||||
|
.editor,
|
||||||
|
.editor-content,
|
||||||
|
prose-mirror
|
||||||
|
min-height: 300px !important
|
||||||
|
height: auto !important
|
||||||
|
|||||||
@@ -294,6 +294,41 @@ li.chat-message
|
|||||||
color: #EE4050
|
color: #EE4050
|
||||||
border-top: 1px solid rgba(238,64,80,0.2)
|
border-top: 1px solid rgba(238,64,80,0.2)
|
||||||
|
|
||||||
|
// ── Effect line ──
|
||||||
|
.mgt2-effect
|
||||||
|
text-align: center
|
||||||
|
font-size: 0.72rem
|
||||||
|
font-weight: 600
|
||||||
|
letter-spacing: 1.5px
|
||||||
|
text-transform: uppercase
|
||||||
|
padding: 2px 10px 4px 10px
|
||||||
|
border-bottom: 2px solid transparent
|
||||||
|
|
||||||
|
.mgt2-effect-value
|
||||||
|
font-size: 1rem
|
||||||
|
font-weight: 900
|
||||||
|
margin-left: 4px
|
||||||
|
|
||||||
|
.mgt2-healing-amount
|
||||||
|
font-size: 0.75rem
|
||||||
|
font-weight: 600
|
||||||
|
margin-left: 6px
|
||||||
|
opacity: 0.85
|
||||||
|
|
||||||
|
&.is-success
|
||||||
|
color: #1a8840
|
||||||
|
border-bottom-color: rgba(26,136,64,0.25)
|
||||||
|
|
||||||
|
.mgt2-effect-value
|
||||||
|
color: #1a8840
|
||||||
|
|
||||||
|
&.is-failure
|
||||||
|
color: #EE4050
|
||||||
|
border-bottom-color: rgba(238,64,80,0.25)
|
||||||
|
|
||||||
|
.mgt2-effect-value
|
||||||
|
color: #EE4050
|
||||||
|
|
||||||
// ── Action buttons ──
|
// ── Action buttons ──
|
||||||
.mgt2-buttons
|
.mgt2-buttons
|
||||||
display: flex
|
display: flex
|
||||||
|
|||||||
@@ -105,15 +105,19 @@
|
|||||||
flex-direction: row
|
flex-direction: row
|
||||||
align-items: center
|
align-items: center
|
||||||
gap: 0.5rem
|
gap: 0.5rem
|
||||||
flex-wrap: wrap
|
flex-wrap: nowrap
|
||||||
|
|
||||||
label
|
label
|
||||||
|
flex: 0 0 auto
|
||||||
font-size: 0.75rem
|
font-size: 0.75rem
|
||||||
text-transform: uppercase
|
text-transform: uppercase
|
||||||
color: var(--mgt2-color-primary)
|
color: var(--mgt2-color-primary)
|
||||||
font-weight: 700
|
font-weight: 700
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
.behavior-select
|
.behavior-select
|
||||||
|
flex: 1 1 auto
|
||||||
|
min-width: 0
|
||||||
background: var(--mgt2-bgcolor-form)
|
background: var(--mgt2-bgcolor-form)
|
||||||
color: var(--mgt2-color-form)
|
color: var(--mgt2-color-form)
|
||||||
border: 1px solid var(--mgt2-color-primary)
|
border: 1px solid var(--mgt2-color-primary)
|
||||||
@@ -122,24 +126,29 @@
|
|||||||
padding: 1px 4px
|
padding: 1px 4px
|
||||||
|
|
||||||
.behavior-sep
|
.behavior-sep
|
||||||
|
flex: 0 0 auto
|
||||||
color: var(--mgt2-color-form)
|
color: var(--mgt2-color-form)
|
||||||
opacity: 0.5
|
opacity: 0.5
|
||||||
|
|
||||||
.creature-size-badge
|
.creature-size-badge
|
||||||
margin-left: auto
|
flex: 0 0 auto
|
||||||
|
white-space: nowrap
|
||||||
font-size: 0.75rem
|
font-size: 0.75rem
|
||||||
font-style: italic
|
font-style: italic
|
||||||
color: var(--mgt2-color-secondary)
|
color: var(--mgt2-bgcolor-form)
|
||||||
background: var(--mgt2-bgcolor-primary)
|
background: var(--mgt2-bgcolor-primary)
|
||||||
border: 1px solid var(--mgt2-color-secondary)
|
border: 1px solid var(--mgt2-color-primary)
|
||||||
border-radius: 3px
|
border-radius: 3px
|
||||||
padding: 1px 6px
|
padding: 1px 6px
|
||||||
|
|
||||||
// ── Body / Tabs ────────────────────────────────────
|
// ── Body / Tabs ────────────────────────────────────
|
||||||
|
// min-height ensures all 4 sidebar tabs are always visible
|
||||||
|
// (4 tabs × 54px each + 8px padding = 224px)
|
||||||
.creature-body
|
.creature-body
|
||||||
flex: 1
|
flex: 1
|
||||||
overflow-y: auto
|
overflow-y: auto
|
||||||
padding: 0.5rem 0.75rem
|
padding: 0.5rem 0.75rem
|
||||||
|
min-height: 228px
|
||||||
|
|
||||||
.tab
|
.tab
|
||||||
display: none
|
display: none
|
||||||
@@ -199,3 +208,18 @@
|
|||||||
|
|
||||||
.mgt2-roll-header-text
|
.mgt2-roll-header-text
|
||||||
flex: 1
|
flex: 1
|
||||||
|
|
||||||
|
// ── Section headers: use shared .header class (same as character sheet) ──────
|
||||||
|
|
||||||
|
// ── HTMLField editor min-height in info tab ──────────────────────────────────
|
||||||
|
.mgt2.creature
|
||||||
|
// Section headers (skills/attacks/traits) — margin between successive sections
|
||||||
|
.table-container + .header
|
||||||
|
margin-top: 8px
|
||||||
|
|
||||||
|
.tab[data-tab="info"]
|
||||||
|
.editor,
|
||||||
|
.editor-content,
|
||||||
|
prose-mirror
|
||||||
|
min-height: 300px !important
|
||||||
|
height: auto !important
|
||||||
|
|||||||
@@ -31,15 +31,15 @@
|
|||||||
|
|
||||||
.dialog-content, .standard-form
|
.dialog-content, .standard-form
|
||||||
background: #ffffff !important
|
background: #ffffff !important
|
||||||
padding: 14px 18px 10px !important
|
padding: 8px 14px 6px !important
|
||||||
|
|
||||||
// Form group rows
|
// Form group rows
|
||||||
.form-group
|
.form-group
|
||||||
display: flex !important
|
display: flex !important
|
||||||
align-items: center !important
|
align-items: center !important
|
||||||
gap: 10px !important
|
gap: 8px !important
|
||||||
margin-bottom: 8px !important
|
margin-bottom: 3px !important
|
||||||
padding: 4px 0 !important
|
padding: 2px 0 !important
|
||||||
border-bottom: 1px solid #e8e0e0 !important
|
border-bottom: 1px solid #e8e0e0 !important
|
||||||
|
|
||||||
&:last-child
|
&:last-child
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
border: 1px solid #ccbbbb !important
|
border: 1px solid #ccbbbb !important
|
||||||
color: #0A0405 !important
|
color: #0A0405 !important
|
||||||
border-radius: 3px !important
|
border-radius: 3px !important
|
||||||
padding: 5px 10px !important
|
padding: 3px 8px !important
|
||||||
font-family: 'Barlow Condensed', sans-serif !important
|
font-family: 'Barlow Condensed', sans-serif !important
|
||||||
font-size: 0.9rem !important
|
font-size: 0.9rem !important
|
||||||
transition: border-color 150ms ease !important
|
transition: border-color 150ms ease !important
|
||||||
@@ -80,8 +80,8 @@
|
|||||||
background: #fdf8f8 !important
|
background: #fdf8f8 !important
|
||||||
border: 1px solid #e0c8c8 !important
|
border: 1px solid #e0c8c8 !important
|
||||||
border-radius: 5px !important
|
border-radius: 5px !important
|
||||||
padding: 10px 14px !important
|
padding: 5px 10px !important
|
||||||
margin-bottom: 8px !important
|
margin-bottom: 4px !important
|
||||||
|
|
||||||
legend
|
legend
|
||||||
color: #EE4050 !important
|
color: #EE4050 !important
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
.dialog-buttons, .form-footer, footer
|
.dialog-buttons, .form-footer, footer
|
||||||
background: #f5eeee !important
|
background: #f5eeee !important
|
||||||
border-top: 2px solid #EE4050 !important
|
border-top: 2px solid #EE4050 !important
|
||||||
padding: 10px 14px !important
|
padding: 7px 14px !important
|
||||||
display: flex !important
|
display: flex !important
|
||||||
gap: 8px !important
|
gap: 8px !important
|
||||||
justify-content: center !important
|
justify-content: center !important
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
border: 1px solid #ccbbbb !important
|
border: 1px solid #ccbbbb !important
|
||||||
color: #3a2020 !important
|
color: #3a2020 !important
|
||||||
border-radius: 4px !important
|
border-radius: 4px !important
|
||||||
padding: 7px 14px !important
|
padding: 5px 12px !important
|
||||||
font-family: 'Barlow Condensed', sans-serif !important
|
font-family: 'Barlow Condensed', sans-serif !important
|
||||||
font-size: 0.82rem !important
|
font-size: 0.82rem !important
|
||||||
font-weight: 700 !important
|
font-weight: 700 !important
|
||||||
|
|||||||
@@ -343,3 +343,76 @@
|
|||||||
.itemsheet-panel
|
.itemsheet-panel
|
||||||
display: contents !important
|
display: contents !important
|
||||||
|
|
||||||
|
|
||||||
|
// ── Details tab: 2-column grid layout ────────────────────────────────────────
|
||||||
|
.itemsheet
|
||||||
|
.item-details-grid
|
||||||
|
display: grid !important
|
||||||
|
grid-template-columns: 1fr 1fr !important
|
||||||
|
gap: 4px 16px !important
|
||||||
|
align-items: start !important
|
||||||
|
|
||||||
|
// Traits table spans full width
|
||||||
|
.table-container
|
||||||
|
grid-column: 1 / -1 !important
|
||||||
|
margin-top: 10px !important
|
||||||
|
|
||||||
|
// ── Field row: label + input on the same line ─────────────────────────────────
|
||||||
|
.itemsheet
|
||||||
|
.field-row
|
||||||
|
display: flex !important
|
||||||
|
align-items: center !important
|
||||||
|
gap: 8px !important
|
||||||
|
min-height: 28px !important
|
||||||
|
|
||||||
|
label
|
||||||
|
flex: 0 0 100px !important
|
||||||
|
min-width: 0 !important
|
||||||
|
margin-bottom: 0 !important
|
||||||
|
white-space: nowrap !important
|
||||||
|
overflow: hidden !important
|
||||||
|
text-overflow: ellipsis !important
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
input[type="number"],
|
||||||
|
select
|
||||||
|
flex: 1 !important
|
||||||
|
width: auto !important
|
||||||
|
height: 24px !important
|
||||||
|
padding: 2px 6px !important
|
||||||
|
|
||||||
|
input.short
|
||||||
|
flex: 0 0 56px !important
|
||||||
|
width: 56px !important
|
||||||
|
|
||||||
|
.range-inputs
|
||||||
|
display: flex !important
|
||||||
|
gap: 4px !important
|
||||||
|
flex: 1 !important
|
||||||
|
|
||||||
|
input
|
||||||
|
flex: 0 0 52px !important
|
||||||
|
width: 52px !important
|
||||||
|
|
||||||
|
select
|
||||||
|
flex: 1 !important
|
||||||
|
|
||||||
|
// Full-width row (e.g. storage)
|
||||||
|
&.full
|
||||||
|
grid-column: 1 / -1 !important
|
||||||
|
|
||||||
|
// Checkbox row variant
|
||||||
|
.field-row--check
|
||||||
|
label
|
||||||
|
flex: unset !important
|
||||||
|
display: flex !important
|
||||||
|
align-items: center !important
|
||||||
|
gap: 6px !important
|
||||||
|
cursor: pointer !important
|
||||||
|
|
||||||
|
// ── Description tab: editor min-height ───────────────────────────────────────
|
||||||
|
.itemsheet
|
||||||
|
.tab[data-tab="tab1"]
|
||||||
|
.editor,
|
||||||
|
.editor-container
|
||||||
|
min-height: 200px !important
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// nav (left: 100% of character-body) can extend to the right of the window border.
|
// nav (left: 100% of character-body) can extend to the right of the window border.
|
||||||
// Layered !important beats Foundry's unlayered overflow:hidden per CSS cascade spec.
|
// Layered !important beats Foundry's unlayered overflow:hidden per CSS cascade spec.
|
||||||
|
|
||||||
.mgt2.character, .mgt2.creature
|
.mgt2.character, .mgt2.creature, .mgt2.vehicule
|
||||||
overflow: visible !important
|
overflow: visible !important
|
||||||
> .window-content
|
> .window-content
|
||||||
overflow: visible !important
|
overflow: visible !important
|
||||||
@@ -18,13 +18,16 @@
|
|||||||
position: relative !important
|
position: relative !important
|
||||||
overflow: visible !important
|
overflow: visible !important
|
||||||
|
|
||||||
|
.mgt2.vehicule .vehicule-content
|
||||||
|
position: relative !important
|
||||||
|
overflow: visible !important
|
||||||
|
|
||||||
// ── Vertical sidebar tab navigation (outside window, right side) ──
|
// ── Vertical sidebar tab navigation (outside window, right side) ──
|
||||||
.mgt2
|
.mgt2
|
||||||
nav.sheet-sidebar.tabs
|
nav.sheet-sidebar.tabs
|
||||||
position: absolute !important
|
position: absolute !important
|
||||||
left: 100% !important
|
left: 100% !important
|
||||||
top: 0 !important
|
top: 0 !important
|
||||||
bottom: 0 !important
|
|
||||||
width: 62px !important
|
width: 62px !important
|
||||||
flex: none !important
|
flex: none !important
|
||||||
display: flex !important
|
display: flex !important
|
||||||
|
|||||||
203
src/sass/components/_vehicule.sass
Normal file
203
src/sass/components/_vehicule.sass
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
// ─────────────────────────────────────────────────
|
||||||
|
// Vehicule Sheet Styles
|
||||||
|
// ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
.vehicule-sheet
|
||||||
|
|
||||||
|
// ── Header ────────────────────────────────────────
|
||||||
|
.vehicule-header
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
align-items: flex-start
|
||||||
|
gap: 0.75rem
|
||||||
|
padding: 0.5rem 0.75rem
|
||||||
|
background: var(--mgt2-bgcolor-form)
|
||||||
|
border-bottom: 2px solid var(--mgt2-color-primary)
|
||||||
|
flex-shrink: 0
|
||||||
|
|
||||||
|
.vehicule-header-img
|
||||||
|
flex: 0 0 90px
|
||||||
|
img.profile
|
||||||
|
width: 90px
|
||||||
|
height: 90px
|
||||||
|
object-fit: cover
|
||||||
|
border: 2px solid var(--mgt2-color-primary)
|
||||||
|
border-radius: 4px
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
.vehicule-header-body
|
||||||
|
flex: 1
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
gap: 0.4rem
|
||||||
|
min-width: 0
|
||||||
|
|
||||||
|
.vehicule-name
|
||||||
|
font-family: "Barlow Condensed", sans-serif
|
||||||
|
font-size: 1.6rem
|
||||||
|
font-weight: 700
|
||||||
|
font-style: italic
|
||||||
|
color: var(--mgt2-color-form)
|
||||||
|
background: transparent
|
||||||
|
border: none
|
||||||
|
border-bottom: 1px solid var(--mgt2-color-primary)
|
||||||
|
width: 100%
|
||||||
|
padding: 0
|
||||||
|
&:focus
|
||||||
|
outline: none
|
||||||
|
border-bottom-color: var(--mgt2-color-secondary)
|
||||||
|
|
||||||
|
.vehicule-header-stats
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
align-items: flex-start
|
||||||
|
gap: 0.75rem
|
||||||
|
flex-wrap: wrap
|
||||||
|
|
||||||
|
// ── Stat boxes (hull, armor) ────────────────────────
|
||||||
|
.vehicule-stat-box
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
align-items: center
|
||||||
|
background: var(--mgt2-bgcolor-primary)
|
||||||
|
border: 1px solid var(--mgt2-color-primary)
|
||||||
|
border-radius: 4px
|
||||||
|
padding: 3px 8px
|
||||||
|
min-width: 4rem
|
||||||
|
|
||||||
|
label
|
||||||
|
font-family: "Barlow Condensed", sans-serif
|
||||||
|
font-size: 0.65rem
|
||||||
|
font-weight: 700
|
||||||
|
text-transform: uppercase
|
||||||
|
color: var(--mgt2-color-primary)
|
||||||
|
line-height: 1.2
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
.vehicule-stat-value
|
||||||
|
display: flex
|
||||||
|
align-items: center
|
||||||
|
gap: 2px
|
||||||
|
|
||||||
|
span
|
||||||
|
color: var(--mgt2-color-primary)
|
||||||
|
font-weight: 700
|
||||||
|
|
||||||
|
input[type="number"]
|
||||||
|
width: 2.8rem
|
||||||
|
text-align: center
|
||||||
|
background: transparent
|
||||||
|
border: none
|
||||||
|
color: var(--mgt2-color-form)
|
||||||
|
font-family: "Rubik", monospace
|
||||||
|
font-size: 1rem
|
||||||
|
font-weight: 600
|
||||||
|
padding: 0
|
||||||
|
&:focus
|
||||||
|
outline: none
|
||||||
|
border-bottom: 1px solid var(--mgt2-color-secondary)
|
||||||
|
|
||||||
|
.vehicule-hull
|
||||||
|
min-width: 6rem
|
||||||
|
.vehicule-stat-value input[type="number"]
|
||||||
|
width: 2.5rem
|
||||||
|
|
||||||
|
// ── Armor group ────────────────────────────────────
|
||||||
|
.vehicule-armor-group
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
gap: 2px
|
||||||
|
|
||||||
|
.vehicule-armor-label
|
||||||
|
font-family: "Barlow Condensed", sans-serif
|
||||||
|
font-size: 0.65rem
|
||||||
|
font-weight: 700
|
||||||
|
text-transform: uppercase
|
||||||
|
color: var(--mgt2-color-primary)
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
.vehicule-armor-row
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
gap: 4px
|
||||||
|
|
||||||
|
.vehicule-armor-box
|
||||||
|
min-width: 3.5rem
|
||||||
|
|
||||||
|
// ── Body wrapper (contains tabs + sidebar nav) ─────
|
||||||
|
// min-height ensures both tabs in the sidebar are always visible
|
||||||
|
// (2 tabs × 54px each + 8px padding = 116px)
|
||||||
|
.vehicule-content
|
||||||
|
flex: 1
|
||||||
|
display: flex
|
||||||
|
flex-direction: column
|
||||||
|
overflow: hidden
|
||||||
|
min-height: 320px
|
||||||
|
|
||||||
|
// ── Tab panels ─────────────────────────────────────
|
||||||
|
.vehicule-tab
|
||||||
|
flex: 1
|
||||||
|
overflow-y: auto
|
||||||
|
padding: 0.75rem
|
||||||
|
display: none
|
||||||
|
|
||||||
|
&.active
|
||||||
|
display: block
|
||||||
|
|
||||||
|
// ── Stats grid ─────────────────────────────────────
|
||||||
|
.vehicule-stats-grid
|
||||||
|
display: grid
|
||||||
|
grid-template-columns: 1fr 1fr
|
||||||
|
gap: 4px 12px
|
||||||
|
|
||||||
|
.vehicule-field
|
||||||
|
display: flex
|
||||||
|
flex-direction: row
|
||||||
|
align-items: center
|
||||||
|
gap: 8px
|
||||||
|
padding: 3px 0
|
||||||
|
border-bottom: 1px solid rgba(0,0,0,0.08)
|
||||||
|
|
||||||
|
&:last-child
|
||||||
|
border-bottom: none
|
||||||
|
|
||||||
|
label
|
||||||
|
font-family: "Barlow Condensed", sans-serif
|
||||||
|
font-size: 0.72rem
|
||||||
|
font-weight: 700
|
||||||
|
text-transform: uppercase
|
||||||
|
color: var(--mgt2-color-primary)
|
||||||
|
flex: 0 0 120px
|
||||||
|
white-space: nowrap
|
||||||
|
|
||||||
|
input[type="number"],
|
||||||
|
select
|
||||||
|
flex: 1
|
||||||
|
background: transparent
|
||||||
|
border: 1px solid transparent
|
||||||
|
border-radius: 3px
|
||||||
|
color: var(--mgt2-color-form)
|
||||||
|
font-family: "Barlow Condensed", sans-serif
|
||||||
|
font-size: 0.9rem
|
||||||
|
padding: 2px 4px
|
||||||
|
&:focus
|
||||||
|
outline: none
|
||||||
|
border-color: var(--mgt2-color-primary)
|
||||||
|
background: rgba(255,255,255,0.1)
|
||||||
|
|
||||||
|
input[type="number"]
|
||||||
|
text-align: center
|
||||||
|
width: 4rem
|
||||||
|
|
||||||
|
select
|
||||||
|
cursor: pointer
|
||||||
|
|
||||||
|
|
||||||
|
// ── HTMLField editor min-height in description tab ──────────────────────────
|
||||||
|
.mgt2.vehicule
|
||||||
|
.vehicule-tab[data-tab="description"]
|
||||||
|
.editor,
|
||||||
|
.editor-content,
|
||||||
|
prose-mirror
|
||||||
|
min-height: 300px !important
|
||||||
|
height: auto !important
|
||||||
@@ -13,4 +13,5 @@
|
|||||||
@import 'components/_tabs'
|
@import 'components/_tabs'
|
||||||
@import 'components/_tab-sidebar'
|
@import 'components/_tab-sidebar'
|
||||||
@import 'components/_tables'
|
@import 'components/_tables'
|
||||||
@import 'components/_creature'
|
@import 'components/_creature'
|
||||||
|
@import 'components/_vehicule'
|
||||||
2
styles/mgt2.min.css
vendored
2
styles/mgt2.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
90
system.json
90
system.json
@@ -1,47 +1,47 @@
|
|||||||
{
|
{
|
||||||
"id": "mgt2",
|
"id": "mgt2",
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"title": "MGT2 - Mongoose Traveller (Unofficial)",
|
"title": "MGT2 - Mongoose Traveller (Unofficial)",
|
||||||
"description": "An unofficial implementation of Mongoose Publishing Traveller (VO/VF). Traveller is the property of Mongoose Publishing, and can be purchased at https://www.mongoosepublishing.com",
|
"description": "An unofficial implementation of Mongoose Publishing Traveller (VO/VF). Traveller is the property of Mongoose Publishing, and can be purchased at https://www.mongoosepublishing.com",
|
||||||
"background": "systems/mgt2/assets/screens/rosette-nebula-ngc2239-hoo.webp",
|
"background": "systems/mgt2/assets/screens/rosette-nebula-ngc2239-hoo.webp",
|
||||||
"url": "https://github.com/JDR-Ninja/foundryvtt-mgt2",
|
"url": "https://github.com/JDR-Ninja/foundryvtt-mgt2",
|
||||||
"manifest": "https://github.com/JDR-Ninja/foundryvtt-mgt2/releases/latest/download/system.json",
|
"manifest": "https://github.com/JDR-Ninja/foundryvtt-mgt2/releases/latest/download/system.json",
|
||||||
"readme": "https://raw.githubusercontent.com/JDR-Ninja/foundryvtt-mgt2/main/README.md",
|
"readme": "https://raw.githubusercontent.com/JDR-Ninja/foundryvtt-mgt2/main/README.md",
|
||||||
"download": "https://github.com/JDR-Ninja/foundryvtt-mgt2/releases/download/v0.1.4/mgt2.zip",
|
"download": "https://github.com/JDR-Ninja/foundryvtt-mgt2/releases/download/v0.1.4/mgt2.zip",
|
||||||
"changelog": "https://raw.githubusercontent.com/JDR-Ninja/foundryvtt-mgt2/main/CHANGELOG.md",
|
"changelog": "https://raw.githubusercontent.com/JDR-Ninja/foundryvtt-mgt2/main/CHANGELOG.md",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "JdR Ninja",
|
"name": "JdR Ninja",
|
||||||
"url": "https://www.jdr.ninja/",
|
"url": "https://www.jdr.ninja/",
|
||||||
"discord": "jdr.ninja"
|
"discord": "jdr.ninja"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"esmodules": [
|
"esmodules": [
|
||||||
"mgt2.bundle.js"
|
"mgt2.bundle.js"
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"styles/mgt2.min.css"
|
"styles/mgt2.min.css"
|
||||||
],
|
],
|
||||||
"packs": [],
|
"packs": [],
|
||||||
"languages": [
|
"languages": [
|
||||||
{
|
{
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
"name": "English",
|
"name": "English",
|
||||||
"path": "lang/en.json"
|
"path": "lang/en.json"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"lang": "fr",
|
"lang": "fr",
|
||||||
"name": "Français",
|
"name": "Français",
|
||||||
"path": "lang/fr.json"
|
"path": "lang/fr.json"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "11",
|
"minimum": "11",
|
||||||
"verified": "12.324"
|
"verified": "12.324"
|
||||||
},
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
"distance": 1.5,
|
"distance": 1.5,
|
||||||
"units": "m"
|
"units": "m"
|
||||||
},
|
},
|
||||||
"primaryTokenAttribute": "life"
|
"primaryTokenAttribute": "life"
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
"vehicule",
|
"vehicule",
|
||||||
"creature"
|
"creature"
|
||||||
],
|
],
|
||||||
"htmlFields": ["notes"],
|
"htmlFields": ["notes", "biography"],
|
||||||
"character": {},
|
"character": {},
|
||||||
"vehicule": {},
|
"vehicule": {},
|
||||||
"creature": {}
|
"creature": {}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<form class="{{cssClass}} flexcol" autocomplete="off">
|
<form class="{{cssClass}} flexcol" autocomplete="off">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.config.psionic" data-dtype="Boolean" {{checked system.config.psionic}} />{{ localize 'MGT2.Actor.ShowPsionicTalents' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="psionic" data-dtype="Boolean" {{checked system.config.psionic}} />{{ localize 'MGT2.Actor.ShowPsionicTalents' }}</label>
|
||||||
</div>
|
</div>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>{{ localize 'MGT2.Actor.Initiative' }}</legend>
|
<legend>{{ localize 'MGT2.Actor.Initiative' }}</legend>
|
||||||
|
|||||||
@@ -272,6 +272,22 @@
|
|||||||
<label class="upcase">{{ localize 'MGT2.Actor.Rads' }}</label>
|
<label class="upcase">{{ localize 'MGT2.Actor.Rads' }}</label>
|
||||||
<input class="field" name="system.health.radiations" type="text" value="{{system.health.radiations}}" />
|
<input class="field" name="system.health.radiations" type="text" value="{{system.health.radiations}}" />
|
||||||
</div>
|
</div>
|
||||||
|
<!-- HEALING SECTION -->
|
||||||
|
<div class="header upcase">{{ localize 'MGT2.Healing.Title' }}</div>
|
||||||
|
<div class="healing-buttons" style="display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px;">
|
||||||
|
<button type="button" data-action="heal" data-heal-type="firstaid" class="button sm" title="{{ localize 'MGT2.Healing.FirstAid' }}">
|
||||||
|
<i class="fas fa-bandage"></i> {{ localize 'MGT2.Healing.FirstAid' }}
|
||||||
|
</button>
|
||||||
|
<button type="button" data-action="heal" data-heal-type="surgery" class="button sm" title="{{ localize 'MGT2.Healing.Surgery' }}">
|
||||||
|
<i class="fas fa-flask-vial"></i> {{ localize 'MGT2.Healing.Surgery' }}
|
||||||
|
</button>
|
||||||
|
<button type="button" data-action="heal" data-heal-type="medical" class="button sm" title="{{ localize 'MGT2.Healing.MedicalCare' }}">
|
||||||
|
<i class="fas fa-hospital"></i> {{ localize 'MGT2.Healing.MedicalCare' }}
|
||||||
|
</button>
|
||||||
|
<button type="button" data-action="heal" data-heal-type="natural" class="button sm" title="{{ localize 'MGT2.Healing.NaturalHealing' }}">
|
||||||
|
<i class="fas fa-leaf"></i> {{ localize 'MGT2.Healing.NaturalHealing' }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-row heading color-1">
|
<div class="table-row heading color-1">
|
||||||
<div class="row-item row-item-30 row-item-left upcase">{{ localize 'MGT2.Actor.Wounds' }}</div>
|
<div class="row-item row-item-30 row-item-left upcase">{{ localize 'MGT2.Actor.Wounds' }}</div>
|
||||||
@@ -443,7 +459,7 @@
|
|||||||
<div class="row-item row-item-20 row-item-center">{{weapon.system.damage}}</div>
|
<div class="row-item row-item-20 row-item-center">{{weapon.system.damage}}</div>
|
||||||
<div class="row-item row-item-2 row-item-right flex-fix">{{weapon.weight}}</div>
|
<div class="row-item row-item-2 row-item-right flex-fix">{{weapon.weight}}</div>
|
||||||
<div class="row-item row-item-15 item-controls flex-fix">
|
<div class="row-item row-item-15 item-controls flex-fix">
|
||||||
<a class="item-control item-equip {{weapon.toggleClass}}" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
<a class="item-control item-equip {{weapon.toggleClass}}" data-action="equipItem" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
||||||
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
||||||
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditWeapon' }}"><i class="fas fa-edit"></i></a>
|
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditWeapon' }}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteWeapon' }}"><i class="fas fa-trash"></i></a>
|
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteWeapon' }}"><i class="fas fa-trash"></i></a>
|
||||||
@@ -468,7 +484,7 @@
|
|||||||
<div class="row-item row-item-10 row-item-center">{{armor.system.protection}}</div>
|
<div class="row-item row-item-10 row-item-center">{{armor.system.protection}}</div>
|
||||||
<div class="row-item row-item-2 row-item-right flex-fix">{{armor.weight}}</div>
|
<div class="row-item row-item-2 row-item-right flex-fix">{{armor.weight}}</div>
|
||||||
<div class="row-item row-item-15 item-controls flex-fix">
|
<div class="row-item row-item-15 item-controls flex-fix">
|
||||||
<a class="item-control item-equip {{armor.toggleClass}}" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
<a class="item-control item-equip {{armor.toggleClass}}" data-action="equipItem" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
||||||
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
||||||
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditArmor' }}"><i class="fas fa-edit"></i></a>
|
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditArmor' }}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteArmor' }}"><i class="fas fa-trash"></i></a>
|
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteArmor' }}"><i class="fas fa-trash"></i></a>
|
||||||
@@ -487,7 +503,7 @@
|
|||||||
<div class="row-item row-item-30 row-item-left">{{augment.name}}</div>
|
<div class="row-item row-item-30 row-item-left">{{augment.name}}</div>
|
||||||
<div class="row-item row-item-40 row-item-left">{{augment.system.improvement}}</div>
|
<div class="row-item row-item-40 row-item-left">{{augment.system.improvement}}</div>
|
||||||
<div class="row-item row-item-15 item-controls flex-fix">
|
<div class="row-item row-item-15 item-controls flex-fix">
|
||||||
<a class="item-control item-equip {{augment.toggleClass}}" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
<a class="item-control item-equip {{augment.toggleClass}}" data-action="equipItem" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
||||||
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
||||||
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditAugment' }}"><i class="fas fa-edit"></i></a>
|
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditAugment' }}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteAugment' }}"><i class="fas fa-trash"></i></a>
|
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteAugment' }}"><i class="fas fa-trash"></i></a>
|
||||||
@@ -512,7 +528,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row-item row-item-2 row-item-right flex-fix">{{computer.weight}}</div>
|
<div class="row-item row-item-2 row-item-right flex-fix">{{computer.weight}}</div>
|
||||||
<div class="row-item row-item-15 item-controls flex-fix">
|
<div class="row-item row-item-15 item-controls flex-fix">
|
||||||
<a class="item-control item-equip {{computer.toggleClass}}" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
<a class="item-control item-equip {{computer.toggleClass}}" data-action="equipItem" title="Equip"><i class="fa-solid fa-shield-halved"></i></a>
|
||||||
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreItem' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
||||||
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditComputer' }}"><i class="fas fa-edit"></i></a>
|
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditComputer' }}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteComputer' }}"><i class="fas fa-trash"></i></a>
|
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteComputer' }}"><i class="fas fa-trash"></i></a>
|
||||||
@@ -557,7 +573,7 @@
|
|||||||
<div class="row-item row-item-2 row-item-center">{{equipment.system.quantity}}</div>
|
<div class="row-item row-item-2 row-item-center">{{equipment.system.quantity}}</div>
|
||||||
<div class="row-item row-item-2 row-item-right flex-fix">{{equipment.weight}}</div>
|
<div class="row-item row-item-2 row-item-right flex-fix">{{equipment.weight}}</div>
|
||||||
<div class="row-item row-item-15 item-controls flex-fix">
|
<div class="row-item row-item-15 item-controls flex-fix">
|
||||||
<a class="item-control item-equip {{equipment.toggleClass}}" title="{{ localize 'MGT2.Actor.EquipUnequip' }}"><i class="fa-solid fa-shield-halved"></i></a>
|
<a class="item-control item-equip {{equipment.toggleClass}}" data-action="equipItem" title="{{ localize 'MGT2.Actor.EquipUnequip' }}"><i class="fa-solid fa-shield-halved"></i></a>
|
||||||
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreEquipment' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
<a class="item-control item-storage-in" title="{{ localize 'MGT2.Actor.StoreEquipment' }}"><i class="fa-solid fa-inbox-in"></i></a>
|
||||||
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditEquipment' }}"><i class="fas fa-edit"></i></a>
|
<a class="item-control item-edit" title="{{ localize 'MGT2.Actor.EditEquipment' }}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteEquipment' }}"><i class="fas fa-trash"></i></a>
|
<a class="item-control item-delete" title="{{ localize 'MGT2.Actor.DeleteEquipment' }}"><i class="fas fa-trash"></i></a>
|
||||||
@@ -687,8 +703,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group mt-1">
|
<div class="field-group mt-1">
|
||||||
<label class="upcase">{{ localize 'MGT2.Actor.Notes' }}</label>
|
<label class="upcase">{{ localize 'MGT2.Actor.Notes' }}</label>
|
||||||
<textarea name="system.finance.description" rows="3">{{system.finance.description}}</textarea>
|
{{formInput systemFields.finance.fields.notes enriched=enrichedFinanceNotes value=system.finance.notes name="system.finance.notes" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -720,11 +736,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="tab w100 h100" data-group="sidebar" data-tab="notes">
|
<div class="tab w100 h100" data-group="sidebar" data-tab="notes">
|
||||||
<div class="header upcase">{{ localize 'MGT2.Actor.Notes' }}</div>
|
<div class="header upcase">{{ localize 'MGT2.Actor.Notes' }}</div>
|
||||||
{{editor system.notes target="system.notes" button=true editable=true}}
|
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab w100 h100" data-group="sidebar" data-tab="biography">
|
<div class="tab w100 h100" data-group="sidebar" data-tab="biography">
|
||||||
<div class="header upcase">{{ localize 'MGT2.Actor.Biography' }}</div>
|
<div class="header upcase">{{ localize 'MGT2.Actor.Biography' }}</div>
|
||||||
{{editor system.biography target="system.biography" button=true editable=true}}
|
{{formInput systemFields.biography enriched=enrichedBiography value=system.biography name="system.biography" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
{{#if showTrash}}
|
{{#if showTrash}}
|
||||||
<!-- <div class="tab" data-group="inventory" data-tab="trash">
|
<!-- <div class="tab" data-group="inventory" data-tab="trash">
|
||||||
|
|||||||
@@ -80,19 +80,20 @@
|
|||||||
{{!-- ── TAB CONTENT ── --}}
|
{{!-- ── TAB CONTENT ── --}}
|
||||||
<div class="creature-body">
|
<div class="creature-body">
|
||||||
|
|
||||||
|
{{!-- ── TAB : COMBAT (compétences + attaques + traits) ── --}}
|
||||||
|
<div class="tab" data-group="primary" data-tab="combat">
|
||||||
|
|
||||||
{{!-- ── TAB : COMPÉTENCES ── --}}
|
{{!-- Compétences --}}
|
||||||
<div class="tab" data-group="primary" data-tab="skills">
|
<div class="header upcase">{{ localize 'MGT2.Creature.TabSkills' }}</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-row heading color-1">
|
<div class="table-row heading color-1">
|
||||||
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.SkillName' }}</div>
|
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.SkillName' }}</div>
|
||||||
<div class="row-item row-item-center upcase" style="flex: 1">{{ localize 'MGT2.Creature.SkillLevel' }}</div>
|
<div class="row-item row-item-center upcase" style="flex: 1">{{ localize 'MGT2.Creature.SkillLevel' }}</div>
|
||||||
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.SkillNote' }}</div>
|
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.SkillNote' }}</div>
|
||||||
<div class="row-item row-item-right" style="flex: 0 0 3rem">
|
<div class="row-item row-item-right item-controls" style="flex: 0 0 3rem">
|
||||||
<a data-action="addSkill" data-prop="skills" title="{{ localize 'MGT2.Creature.AddSkill' }}"><i class="fas fa-plus"></i></a>
|
{{#if isEditable}}<a data-action="addSkill" data-prop="skills" title="{{ localize 'MGT2.Creature.AddSkill' }}"><i class="fas fa-plus"></i></a>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#each system.skills as |skill i|}}
|
{{#each system.skills as |skill i|}}
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="row-item row-item-left" style="flex: 3">
|
<div class="row-item row-item-left" style="flex: 3">
|
||||||
@@ -124,29 +125,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#unless system.skills.length}}
|
{{#unless system.skills.length}}
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="row-item row-item-center text-muted" style="flex:1">{{ localize 'MGT2.Creature.NoSkills' }}</div>
|
<div class="row-item row-item-center text-muted" style="flex:1">{{ localize 'MGT2.Creature.NoSkills' }}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- ── TAB : ATTAQUES ── --}}
|
{{!-- Attaques --}}
|
||||||
<div class="tab" data-group="primary" data-tab="attacks">
|
<div class="header upcase">{{ localize 'MGT2.Creature.TabAttacks' }}</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-row heading color-1">
|
<div class="table-row heading color-1">
|
||||||
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.AttackName' }}</div>
|
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.AttackName' }}</div>
|
||||||
<div class="row-item row-item-center upcase" style="flex: 2">{{ localize 'MGT2.Creature.AttackDamage' }}</div>
|
<div class="row-item row-item-center upcase" style="flex: 2">{{ localize 'MGT2.Creature.AttackDamage' }}</div>
|
||||||
|
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.AttackSkill' }}</div>
|
||||||
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Items.Description' }}</div>
|
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Items.Description' }}</div>
|
||||||
<div class="row-item row-item-right" style="flex: 0 0 4rem">
|
<div class="row-item row-item-right item-controls" style="flex: 0 0 4rem">
|
||||||
{{#if isEditable}}
|
{{#if isEditable}}<a data-action="addAttack" data-prop="attacks" title="{{ localize 'MGT2.Creature.AddAttack' }}"><i class="fas fa-plus"></i></a>{{/if}}
|
||||||
<a data-action="addAttack" data-prop="attacks" title="{{ localize 'MGT2.Creature.AddAttack' }}"><i class="fas fa-plus"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#each system.attacks as |atk i|}}
|
{{#each system.attacks as |atk i|}}
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="row-item row-item-left" style="flex: 3">
|
<div class="row-item row-item-left" style="flex: 3">
|
||||||
@@ -163,6 +160,22 @@
|
|||||||
<span class="damage-formula">{{atk.damage}}</span>
|
<span class="damage-formula">{{atk.damage}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row-item row-item-left" style="flex: 3">
|
||||||
|
{{#if ../isEditable}}
|
||||||
|
<select name="system.attacks.{{i}}.skill">
|
||||||
|
<option value="-1">— {{ localize 'MGT2.RollPrompt.NoSkill' }} —</option>
|
||||||
|
{{#each ../system.skills as |sk si|}}
|
||||||
|
<option value="{{si}}" {{#if (eq si ../skill)}}selected{{/if}}>{{sk.name}} ({{showDM sk.level}})</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
{{else}}
|
||||||
|
{{#if (gte atk.skill 0)}}
|
||||||
|
<span>{{lookup (lookup ../system.skills atk.skill) "name"}}</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="text-muted">—</span>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
<div class="row-item row-item-left" style="flex: 3">
|
<div class="row-item row-item-left" style="flex: 3">
|
||||||
{{#if ../isEditable}}
|
{{#if ../isEditable}}
|
||||||
<input type="text" name="system.attacks.{{i}}.description" value="{{atk.description}}" />
|
<input type="text" name="system.attacks.{{i}}.description" value="{{atk.description}}" />
|
||||||
@@ -178,29 +191,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#unless system.attacks.length}}
|
{{#unless system.attacks.length}}
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="row-item row-item-center text-muted" style="flex:1">{{ localize 'MGT2.Creature.NoAttacks' }}</div>
|
<div class="row-item row-item-center text-muted" style="flex:1">{{ localize 'MGT2.Creature.NoAttacks' }}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{!-- ── TAB : TRAITS ── --}}
|
{{!-- Traits --}}
|
||||||
<div class="tab" data-group="primary" data-tab="traits">
|
<div class="header upcase">{{ localize 'MGT2.Creature.TabTraits' }}</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-row heading color-1">
|
<div class="table-row heading color-1">
|
||||||
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.TraitName' }}</div>
|
<div class="row-item row-item-left upcase" style="flex: 3">{{ localize 'MGT2.Creature.TraitName' }}</div>
|
||||||
<div class="row-item row-item-center upcase" style="flex: 1">{{ localize 'MGT2.Creature.TraitValue' }}</div>
|
<div class="row-item row-item-center upcase" style="flex: 1">{{ localize 'MGT2.Creature.TraitValue' }}</div>
|
||||||
<div class="row-item row-item-left upcase" style="flex: 4">{{ localize 'MGT2.Items.Description' }}</div>
|
<div class="row-item row-item-left upcase" style="flex: 4">{{ localize 'MGT2.Items.Description' }}</div>
|
||||||
<div class="row-item row-item-right" style="flex: 0 0 3rem">
|
<div class="row-item row-item-right item-controls" style="flex: 0 0 3rem">
|
||||||
{{#if isEditable}}
|
{{#if isEditable}}<a data-action="addTrait" data-prop="traits" title="{{ localize 'MGT2.Creature.AddTrait' }}"><i class="fas fa-plus"></i></a>{{/if}}
|
||||||
<a data-action="addTrait" data-prop="traits" title="{{ localize 'MGT2.Creature.AddTrait' }}"><i class="fas fa-plus"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#each system.traits as |trait i|}}
|
{{#each system.traits as |trait i|}}
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="row-item row-item-left" style="flex: 3">
|
<div class="row-item row-item-left" style="flex: 3">
|
||||||
@@ -231,34 +239,32 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
||||||
{{#unless system.traits.length}}
|
{{#unless system.traits.length}}
|
||||||
<div class="table-row">
|
<div class="table-row">
|
||||||
<div class="row-item row-item-center text-muted" style="flex:1">{{ localize 'MGT2.Creature.NoTraits' }}</div>
|
<div class="row-item row-item-center text-muted" style="flex:1">{{ localize 'MGT2.Creature.NoTraits' }}</div>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
</div>{{!-- /tab combat --}}
|
||||||
|
|
||||||
{{!-- ── TAB : INFORMATIONS ── --}}
|
{{!-- ── TAB : INFORMATIONS ── --}}
|
||||||
<div class="tab" data-group="primary" data-tab="info">
|
<div class="tab" data-group="primary" data-tab="info">
|
||||||
<div class="creature-info-tab">
|
<div class="creature-info-tab">
|
||||||
<div class="field-group mt-1">
|
<div class="field-group mt-1">
|
||||||
<label class="upcase">{{ localize 'MGT2.Items.Description' }}</label>
|
<label class="upcase">{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.biography" rows="8" class="creature-description">{{system.biography}}</textarea>
|
{{formInput systemFields.biography enriched=enrichedBiography value=system.biography name="system.biography" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group mt-1">
|
<div class="field-group mt-1">
|
||||||
<label class="upcase">{{ localize 'MGT2.Items.Notes' }}</label>
|
<label class="upcase">{{ localize 'MGT2.Items.Notes' }}</label>
|
||||||
<textarea name="system.notes" rows="4" class="creature-description">{{system.notes}}</textarea>
|
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- ── VERTICAL SIDEBAR TABS (outside window, right side) ── --}}
|
{{!-- ── VERTICAL SIDEBAR TABS (outside window, right side) ── --}}
|
||||||
<nav class="sheet-sidebar tabs" data-group="primary">
|
<nav class="sheet-sidebar tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="skills" title="{{ localize 'MGT2.Creature.TabSkills' }}"><i class="fa-solid fa-head-side"></i><span class="tab-label">COMP.</span></a>
|
<a class="item tab-select" data-tab="combat" title="{{ localize 'MGT2.Creature.TabCombat' }}"><i class="fa-solid fa-swords"></i><span class="tab-label">COMBAT</span></a>
|
||||||
<a class="item tab-select" data-tab="attacks" title="{{ localize 'MGT2.Creature.TabAttacks' }}"><i class="fa-solid fa-bolt"></i><span class="tab-label">ATT.</span></a>
|
|
||||||
<a class="item tab-select" data-tab="traits" title="{{ localize 'MGT2.Creature.TabTraits' }}"><i class="fa-solid fa-star"></i><span class="tab-label">TRAITS</span></a>
|
|
||||||
<a class="item tab-select" data-tab="info" title="{{ localize 'MGT2.Creature.TabInfo' }}"><i class="fa-solid fa-circle-info"></i><span class="tab-label">INFO</span></a>
|
<a class="item tab-select" data-tab="info" title="{{ localize 'MGT2.Creature.TabInfo' }}"><i class="fa-solid fa-circle-info"></i><span class="tab-label">INFO</span></a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,124 @@
|
|||||||
<form class="{{cssClass}} flexcol" autocomplete="off" style="align-content: flex-start;align-items: baseline;overflow: hidden;height: 100%;">
|
<div class="{{cssClass}} vehicule-sheet flexcol" style="overflow: hidden; height: 100%;">
|
||||||
|
|
||||||
|
<!-- ── Header ─────────────────────────────────────── -->
|
||||||
<section class="vehicule-header">
|
<section class="vehicule-header">
|
||||||
<div class="vehicule-header-img">
|
<div class="vehicule-header-img">
|
||||||
<img class="profile" src="{{img}}" data-edit="img" title="{{name}}" height="130" width="100" />
|
<img class="profile" src="{{img}}" data-edit="img" title="{{name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="vehicule-header-body">
|
<div class="vehicule-header-body">
|
||||||
<input class="field-name" name="name" type="text" value="{{name}}" />
|
<input class="vehicule-name" name="name" type="text" value="{{name}}" />
|
||||||
<ul class="character-summary">
|
<div class="vehicule-header-stats">
|
||||||
<li class="w5-10"><input name="system.personal.title" type="text" value="{{system.personal.title}}" placeholder="{{ localize 'MGT2.Actor.PlaceholderTITLE' }}" /></li>
|
<div class="vehicule-stat-box vehicule-hull">
|
||||||
<li class="w2-10"><input name="system.personal.species" type="text" value="{{system.personal.species}}" placeholder="{{ localize 'MGT2.Actor.PlaceholderSPECIES' }}" /></li>
|
<label>{{ localize 'MGT2.Vehicule.Hull' }}</label>
|
||||||
<li class="w1-10"><input name="system.personal.age" type="text" value="{{system.personal.age}}" placeholder="{{ localize 'MGT2.Actor.PlaceholderAGE' }}" /></li>
|
<div class="vehicule-stat-value">
|
||||||
<li class="w2-10"><input name="system.personal.wup" type="text" value="{{system.personal.wup}}" placeholder="{{ localize 'MGT2.Actor.PlaceholderUCP' }}" /></li>
|
<input type="number" name="system.life.value" value="{{system.life.value}}" />
|
||||||
</ul>
|
<span>/</span>
|
||||||
|
<input type="number" name="system.life.max" value="{{system.life.max}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="vehicule-armor-group">
|
||||||
|
<div class="vehicule-armor-label">{{ localize 'MGT2.Vehicule.Armor' }}</div>
|
||||||
|
<div class="vehicule-armor-row">
|
||||||
|
<div class="vehicule-stat-box vehicule-armor-box">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.ArmorFront' }}</label>
|
||||||
|
<div class="vehicule-stat-value">
|
||||||
|
<input type="number" name="system.armor.front" value="{{system.armor.front}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="vehicule-stat-box vehicule-armor-box">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.ArmorSides' }}</label>
|
||||||
|
<div class="vehicule-stat-value">
|
||||||
|
<input type="number" name="system.armor.sides" value="{{system.armor.sides}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="vehicule-stat-box vehicule-armor-box">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.ArmorRear' }}</label>
|
||||||
|
<div class="vehicule-stat-value">
|
||||||
|
<input type="number" name="system.armor.rear" value="{{system.armor.rear}}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</form>
|
|
||||||
|
<!-- ── Body: tab content + vertical sidebar nav ──── -->
|
||||||
|
<div class="vehicule-content">
|
||||||
|
|
||||||
|
<!-- Tab: Stats -->
|
||||||
|
<div class="tab vehicule-tab" data-group="primary" data-tab="stats">
|
||||||
|
<div class="vehicule-stats-grid">
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.SpeedCruise' }}</label>
|
||||||
|
<select name="system.speed.cruise">
|
||||||
|
{{selectOptions config.SpeedBands selected=system.speed.cruise localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.SpeedMax' }}</label>
|
||||||
|
<select name="system.speed.maximum">
|
||||||
|
{{selectOptions config.SpeedBands selected=system.speed.maximum localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Agility' }}</label>
|
||||||
|
<input type="number" name="system.agility" value="{{system.agility}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Crew' }}</label>
|
||||||
|
<input type="number" name="system.crew" value="{{system.crew}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Passengers' }}</label>
|
||||||
|
<input type="number" name="system.passengers" value="{{system.passengers}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Cargo' }}</label>
|
||||||
|
<input type="number" name="system.cargo" value="{{system.cargo}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Shipping' }}</label>
|
||||||
|
<input type="number" name="system.shipping" value="{{system.shipping}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Cost' }}</label>
|
||||||
|
<input type="number" name="system.cost" value="{{system.cost}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="vehicule-field">
|
||||||
|
<label>{{ localize 'MGT2.Vehicule.Autopilot' }}</label>
|
||||||
|
<input type="number" name="system.skills.autopilot" value="{{system.skills.autopilot}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tab: Description -->
|
||||||
|
<div class="tab vehicule-tab" data-group="primary" data-tab="description">
|
||||||
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Vertical sidebar nav (positioned absolutely right of window) -->
|
||||||
|
<nav class="sheet-sidebar tabs" data-group="primary">
|
||||||
|
<a class="item tab-select" data-tab="stats" title="{{ localize 'MGT2.Vehicule.TabStats' }}">
|
||||||
|
<i class="fa-solid fa-gauge-high"></i>
|
||||||
|
<span class="tab-label">STATS</span>
|
||||||
|
</a>
|
||||||
|
<a class="item tab-select" data-tab="description" title="{{ localize 'MGT2.Vehicule.TabDescription' }}">
|
||||||
|
<i class="fa-solid fa-circle-info"></i>
|
||||||
|
<span class="tab-label">INFO</span>
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<div class="dice-result">
|
<div class="dice-result">
|
||||||
<div class="dice-formula">{{formula}}</div>
|
<div class="dice-formula">{{formula}}</div>
|
||||||
{{{tooltip}}}
|
{{{tooltip}}}
|
||||||
<h4 class="dice-total {{#if success}}success{{else if failure}}failure{{/if}}">{{total}}</h4>
|
<h4 class="dice-total {{#if success}}success{{else if failure}}failure{{/if}}" {{#if rollBreakdown}}data-tooltip="{{rollBreakdown}}"{{/if}}>{{total}}</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -34,4 +34,10 @@
|
|||||||
{{else if failure}}
|
{{else if failure}}
|
||||||
<div class="mgt2-outcome is-failure"><i class="fa-solid fa-xmark"></i> {{ localize 'MGT2.Chat.Roll.Failure' }}</div>
|
<div class="mgt2-outcome is-failure"><i class="fa-solid fa-xmark"></i> {{ localize 'MGT2.Chat.Roll.Failure' }}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if effectStr}}
|
||||||
|
<div class="mgt2-effect {{#if success}}is-success{{else}}is-failure{{/if}}">
|
||||||
|
{{ localize 'MGT2.Chat.Roll.Effect' }} <span class="mgt2-effect-value">{{effectStr}}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="dice-result">
|
<div class="dice-result">
|
||||||
<div class="dice-formula">{{formula}}</div>
|
<div class="dice-formula">{{formula}}</div>
|
||||||
{{{tooltip}}}
|
{{{tooltip}}}
|
||||||
<h4 class="dice-total {{#if rollSuccess}}success{{else if rollFailure}}failure{{/if}}">{{total}}</h4>
|
<h4 class="dice-total {{#if rollSuccess}}success{{else if rollFailure}}failure{{/if}}" {{#if rollBreakdown}}data-tooltip="{{rollBreakdown}}"{{/if}}>{{total}}</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -40,6 +40,14 @@
|
|||||||
<div class="mgt2-outcome is-failure"><i class="fa-solid fa-xmark"></i> {{ localize 'MGT2.Chat.Roll.Failure' }}</div>
|
<div class="mgt2-outcome is-failure"><i class="fa-solid fa-xmark"></i> {{ localize 'MGT2.Chat.Roll.Failure' }}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if rollEffectStr}}
|
||||||
|
<div class="mgt2-effect {{#if rollSuccess}}is-success{{else}}is-failure{{/if}}">
|
||||||
|
{{ localize 'MGT2.Chat.Roll.Effect' }} <span class="mgt2-effect-value">{{rollEffectStr}}</span>
|
||||||
|
{{#if healingAmount}}<span class="mgt2-healing-amount">({{ localize 'MGT2.Healing.Heals' }} {{healingAmount}})</span>{{/if}}
|
||||||
|
{{#if surgeryDamageAmount}}<span class="mgt2-healing-amount">({{ localize 'MGT2.Healing.SurgeryDamage' }} {{surgeryDamageAmount}})</span>{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if showButtons}}
|
{{#if showButtons}}
|
||||||
<div class="mgt2-buttons">
|
<div class="mgt2-buttons">
|
||||||
{{#if hasDamage}}
|
{{#if hasDamage}}
|
||||||
@@ -48,8 +56,8 @@
|
|||||||
{{#if showRollDamage}}
|
{{#if showRollDamage}}
|
||||||
<button data-action="rollDamage">{{ localize 'MGT2.Chat.Roll.Damages' }}</button>
|
<button data-action="rollDamage">{{ localize 'MGT2.Chat.Roll.Damages' }}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#each cardButtons as |cardButton i|}}
|
{{#each cardButtons as |cardButton|}}
|
||||||
<button data-index="{{i}}" title="{{cardButton.label}}">{{cardButton.label}}</button>
|
<button data-action="{{cardButton.action}}" title="{{cardButton.label}}">{{cardButton.label}}</button>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -6,13 +6,7 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
{{> systems/mgt2/templates/items/parts/sheet-physical-item.html }}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Protection' }}</span>
|
|
||||||
<input type="text" name="system.protection" value="{{system.protection}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
@@ -22,19 +16,28 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
<div class="field-groups">
|
<div class="item-details-grid">
|
||||||
<div class="field-group">
|
{{> systems/mgt2/templates/items/parts/sheet-physical-item-tab.html }}
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Protection' }}</label>
|
||||||
|
<input type="text" name="system.protection" value="{{system.protection}}" data-dtype="String" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Radiations' }}</label>
|
||||||
|
<input type="number" name="system.radiations" value="{{system.radiations}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group">
|
<div class="field-row field-row--check">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.powered" data-dtype="Boolean" {{checked system.powered}} />{{ localize 'MGT2.Items.Powered' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.powered" data-dtype="Boolean" {{checked system.powered}} />{{ localize 'MGT2.Items.Powered' }}</label>
|
||||||
</div>
|
</div>
|
||||||
{{#if hadContainer}}
|
{{#if hadContainer}}
|
||||||
<div class="field-group">
|
<div class="field-row full">
|
||||||
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
||||||
<select name="system.container.id">
|
<select name="system.container.id">
|
||||||
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
||||||
@@ -42,10 +45,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group" style="margin-top:8px;">
|
|
||||||
<label>{{ localize 'MGT2.Items.Radiations' }}</label>
|
|
||||||
<input type="number" name="system.radiations" value="{{system.radiations}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-row heading">
|
<div class="table-row heading">
|
||||||
<div class="row-item row-item-left row-item-30">{{ localize 'MGT2.Items.Options' }}</div>
|
<div class="row-item row-item-left row-item-30">{{ localize 'MGT2.Items.Options' }}</div>
|
||||||
|
|||||||
@@ -6,27 +6,30 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" data-dtype="String" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" data-dtype="String" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Terms' }}</span>
|
|
||||||
<input type="number" name="system.terms" value="{{system.terms}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Rank' }}</span>
|
|
||||||
<input type="number" name="system.rank" value="{{system.rank}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Assignment' }}</span>
|
|
||||||
<input type="text" name="system.assignment" value="{{system.assignment}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
<a class="item tab-select" data-tab="events">{{ localize 'MGT2.Items.EventsMishaps' }}</a>
|
<a class="item tab-select" data-tab="events">{{ localize 'MGT2.Items.EventsMishaps' }}</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content-area">
|
<div class="tab-content-area">
|
||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
|
</div>
|
||||||
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
|
<div class="item-details-grid">
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Terms' }}</label>
|
||||||
|
<input type="number" name="system.terms" value="{{system.terms}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Rank' }}</label>
|
||||||
|
<input type="number" name="system.rank" value="{{system.rank}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row full">
|
||||||
|
<label>{{ localize 'MGT2.Items.Assignment' }}</label>
|
||||||
|
<input type="text" name="system.assignment" value="{{system.assignment}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="events">
|
<div class="tab" data-group="primary" data-tab="events">
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
|
|||||||
@@ -6,13 +6,7 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
{{> systems/mgt2/templates/items/parts/sheet-physical-item.html }}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Processing' }}</span>
|
|
||||||
<input type="number" name="system.processing" value="{{system.processing}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
@@ -22,16 +16,21 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
<div class="field-groups">
|
<div class="item-details-grid">
|
||||||
<div class="field-group">
|
{{> systems/mgt2/templates/items/parts/sheet-physical-item-tab.html }}
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Processing' }}</label>
|
||||||
|
<input type="number" name="system.processing" value="{{system.processing}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
||||||
</div>
|
</div>
|
||||||
{{#if hadContainer}}
|
{{#if hadContainer}}
|
||||||
<div class="field-group">
|
<div class="field-row full">
|
||||||
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
||||||
<select name="system.container.id">
|
<select name="system.container.id">
|
||||||
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
||||||
|
|||||||
@@ -6,32 +6,6 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Relation' }}</span>
|
|
||||||
<select name="system.relation">
|
|
||||||
{{selectOptions config.ContactRelations selected=system.relation localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Attitude' }}</span>
|
|
||||||
<select name="system.attitude">
|
|
||||||
{{selectOptions config.Attitudes selected=system.attitude localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Status' }}</span>
|
|
||||||
<select name="system.status">
|
|
||||||
{{selectOptions config.ContactStatus selected=system.status localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{{#if settings.useGender}}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Gender' }}</span>
|
|
||||||
<input type="text" name="system.gender" value="{{system.gender}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Informations' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Informations' }}</a>
|
||||||
<a class="item tab-select" data-tab="description">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="description">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
@@ -39,46 +13,68 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content-area">
|
<div class="tab-content-area">
|
||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-groups">
|
<div class="item-details-grid">
|
||||||
<div class="field-group">
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Relation' }}</label>
|
||||||
|
<select name="system.relation">
|
||||||
|
{{selectOptions config.ContactRelations selected=system.relation localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Attitude' }}</label>
|
||||||
|
<select name="system.attitude">
|
||||||
|
{{selectOptions config.Attitudes selected=system.attitude localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Status' }}</label>
|
||||||
|
<select name="system.status">
|
||||||
|
{{selectOptions config.ContactStatus selected=system.status localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{#if settings.useGender}}
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Gender' }}</label>
|
||||||
|
<input type="text" name="system.gender" value="{{system.gender}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div class="field-row">
|
||||||
<label>{{ localize 'MGT2.Species' }}</label>
|
<label>{{ localize 'MGT2.Species' }}</label>
|
||||||
<input type="text" name="system.species" value="{{system.species}}" data-dtype="String" />
|
<input type="text" name="system.species" value="{{system.species}}" data-dtype="String" />
|
||||||
</div>
|
</div>
|
||||||
{{#if settings.usePronouns}}
|
{{#if settings.usePronouns}}
|
||||||
<div class="field-group">
|
<div class="field-row">
|
||||||
<label>{{ localize 'MGT2.Pronouns' }}</label>
|
<label>{{ localize 'MGT2.Pronouns' }}</label>
|
||||||
<input type="text" name="system.pronouns" value="{{system.pronouns}}" data-dtype="String" />
|
<input type="text" name="system.pronouns" value="{{system.pronouns}}" data-dtype="String" />
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
<div class="field-row">
|
||||||
<div class="field-group" style="margin-top:8px;">
|
<label>{{ localize 'MGT2.Items.Title' }}</label>
|
||||||
<label>{{ localize 'MGT2.Items.Title' }}</label>
|
<input type="text" name="system.title" value="{{system.title}}" data-dtype="String" />
|
||||||
<input type="text" name="system.title" value="{{system.title}}" data-dtype="String" />
|
</div>
|
||||||
</div>
|
<div class="field-row">
|
||||||
<div class="field-group">
|
<label>{{ localize 'MGT2.Items.Nickname' }}</label>
|
||||||
<label>{{ localize 'MGT2.Items.Nickname' }}</label>
|
<input type="text" name="system.nickname" value="{{system.nickname}}" data-dtype="String" />
|
||||||
<input type="text" name="system.nickname" value="{{system.nickname}}" data-dtype="String" />
|
</div>
|
||||||
</div>
|
<div class="field-row">
|
||||||
<div class="field-groups">
|
|
||||||
<div class="field-group">
|
|
||||||
<label>{{ localize 'MGT2.Items.Homeworld' }}</label>
|
<label>{{ localize 'MGT2.Items.Homeworld' }}</label>
|
||||||
<input type="text" name="system.homeworld" value="{{system.homeworld}}" data-dtype="String" />
|
<input type="text" name="system.homeworld" value="{{system.homeworld}}" data-dtype="String" />
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group">
|
<div class="field-row">
|
||||||
<label>{{ localize 'MGT2.Items.Location' }}</label>
|
<label>{{ localize 'MGT2.Items.Location' }}</label>
|
||||||
<input type="text" name="system.location" value="{{system.location}}" data-dtype="String" />
|
<input type="text" name="system.location" value="{{system.location}}" data-dtype="String" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="field-row full">
|
||||||
<div class="field-group">
|
<label>{{ localize 'MGT2.Items.Occupation' }}</label>
|
||||||
<label>{{ localize 'MGT2.Items.Occupation' }}</label>
|
<input type="text" name="system.occupation" value="{{system.occupation}}" data-dtype="String" />
|
||||||
<input type="text" name="system.occupation" value="{{system.occupation}}" data-dtype="String" />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="description">
|
<div class="tab" data-group="primary" data-tab="description">
|
||||||
{{editor system.description.value target="system.description" button=true editable=true}}
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="notes">
|
<div class="tab" data-group="primary" data-tab="notes">
|
||||||
{{editor system.notes target="system.notes" button=true editable=true}}
|
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -7,22 +7,6 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" data-dtype="String" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" data-dtype="String" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Weight' }} ({{unitlabels.weight}})</span>
|
|
||||||
<input type="number" value="{{weight}}" readonly style="opacity:0.7;" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill-checkbox">
|
|
||||||
<input type="checkbox" name="system.onHand" id="onhand-{{item.id}}" data-dtype="Boolean" {{checked system.onHand}} />
|
|
||||||
<label for="onhand-{{item.id}}">{{ localize 'MGT2.Items.OnHand' }}</label>
|
|
||||||
</div>
|
|
||||||
{{#if isGM}}
|
|
||||||
<div class="item-stat-pill-checkbox">
|
|
||||||
<input type="checkbox" name="system.locked" id="locked-{{item.id}}" data-dtype="Boolean" {{checked system.locked}} />
|
|
||||||
<label for="locked-{{item.id}}">{{ localize 'MGT2.Items.Locked' }}</label>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
@@ -34,20 +18,40 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
<div class="field-group">
|
<div class="item-details-grid">
|
||||||
<label>{{ localize 'MGT2.Items.Location' }}</label>
|
<div class="field-row">
|
||||||
<input type="text" name="system.location" value="{{system.location}}" data-dtype="String" />
|
<label>{{ localize 'MGT2.Items.Weight' }} ({{unitlabels.weight}})</label>
|
||||||
|
<input type="number" value="{{weight}}" readonly style="opacity:0.7;" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Location' }}</label>
|
||||||
|
<input type="text" name="system.location" value="{{system.location}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
|
<label class="mgt2-checkbox">
|
||||||
|
<input type="checkbox" name="system.onHand" id="onhand-{{item.id}}" data-dtype="Boolean" {{checked system.onHand}} />
|
||||||
|
{{ localize 'MGT2.Items.OnHand' }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{{#if isGM}}
|
||||||
|
<div class="field-row field-row--check">
|
||||||
|
<label class="mgt2-checkbox">
|
||||||
|
<input type="checkbox" name="system.locked" id="locked-{{item.id}}" data-dtype="Boolean" {{checked system.locked}} />
|
||||||
|
{{ localize 'MGT2.Items.Locked' }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{#if isGM}}
|
{{#if isGM}}
|
||||||
<div class="tab" data-group="primary" data-tab="tab3">
|
<div class="tab" data-group="primary" data-tab="tab3">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.LockedDescription' }}</label>
|
<label>{{ localize 'MGT2.Items.LockedDescription' }}</label>
|
||||||
<textarea name="system.lockedDescription" rows="6">{{system.lockedDescription}}</textarea>
|
{{formInput systemFields.lockedDescription enriched=enrichedLockedDescription value=system.lockedDescription name="system.lockedDescription" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -12,32 +12,40 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<div class="item-stat-pill">
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Type' }}</span>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
<select name="system.subType" style="font-size:0.75rem;">
|
</nav>
|
||||||
{{selectOptions config.DiseaseSubType selected=system.subType localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Difficulty' }}</span>
|
|
||||||
<select name="system.difficulty" style="font-size:0.75rem;">
|
|
||||||
{{selectOptions config.Difficulty selected=system.difficulty localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Damage' }}</span>
|
|
||||||
<input type="text" name="system.damage" value="{{system.damage}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Interval' }}</span>
|
|
||||||
<input type="text" name="system.interval" value="{{system.interval}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tab-content-area">
|
<div class="tab-content-area">
|
||||||
<div class="field-group">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<div class="field-group">
|
||||||
<textarea name="system.description" rows="8">{{system.description}}</textarea>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
|
<div class="item-details-grid">
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Type' }}</label>
|
||||||
|
<select name="system.subType">
|
||||||
|
{{selectOptions config.DiseaseSubType selected=system.subType localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Difficulty' }}</label>
|
||||||
|
<select name="system.difficulty">
|
||||||
|
{{selectOptions config.Difficulty selected=system.difficulty localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Damage' }}</label>
|
||||||
|
<input type="text" name="system.damage" value="{{system.damage}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Interval' }}</label>
|
||||||
|
<input type="text" name="system.interval" value="{{system.interval}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -14,15 +14,7 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Type' }}</span>
|
|
||||||
<select name="system.subType" style="font-size:0.75rem;">
|
|
||||||
{{selectOptions config.EquipmentSubType selected=system.subType localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{{> systems/mgt2/templates/items/parts/sheet-physical-item.html }}
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
@@ -32,16 +24,23 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
<div class="field-groups">
|
<div class="item-details-grid">
|
||||||
<div class="field-group">
|
<div class="field-row">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />Equipped</label>
|
<label>{{ localize 'MGT2.Items.Type' }}</label>
|
||||||
|
<select name="system.subType">
|
||||||
|
{{selectOptions config.EquipmentSubType selected=system.subType localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{> systems/mgt2/templates/items/parts/sheet-physical-item-tab.html }}
|
||||||
|
<div class="field-row field-row--check">
|
||||||
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
||||||
</div>
|
</div>
|
||||||
{{#if hadContainer}}
|
{{#if hadContainer}}
|
||||||
<div class="field-group">
|
<div class="field-row full">
|
||||||
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
||||||
<select name="system.container.id">
|
<select name="system.container.id">
|
||||||
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
||||||
|
|||||||
@@ -10,15 +10,7 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Type' }}</span>
|
|
||||||
<select name="system.subType" style="font-size:0.75rem;">
|
|
||||||
{{selectOptions config.ItemSubType selected=system.subType localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{{> systems/mgt2/templates/items/parts/sheet-physical-item.html }}
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
@@ -27,34 +19,41 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
{{#if hadContainer}}
|
<div class="item-details-grid">
|
||||||
<div class="field-groups">
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Type' }}</label>
|
||||||
|
<select name="system.subType">
|
||||||
|
{{selectOptions config.ItemSubType selected=system.subType localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{> systems/mgt2/templates/items/parts/sheet-physical-item-tab.html }}
|
||||||
|
{{#if hadContainer}}
|
||||||
|
<div class="field-row full">
|
||||||
|
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
||||||
|
<select name="system.container.id">
|
||||||
|
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
{{#if (eq system.subType "software")}}
|
{{#if (eq system.subType "software")}}
|
||||||
<div class="field-group">
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Bandwidth' }}</label>
|
||||||
|
<input type="number" name="system.software.bandwidth" value="{{system.software.bandwidth}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
{{#if hadContainer}}
|
||||||
|
<div class="field-row full">
|
||||||
<label>{{ localize 'MGT2.Items.Computer' }}</label>
|
<label>{{ localize 'MGT2.Items.Computer' }}</label>
|
||||||
<select name="system.software.computerId">
|
<select name="system.software.computerId">
|
||||||
{{selectOptions computers selected=system.software.computerId valueAttr="_id" labelAttr="name"}}
|
{{selectOptions computers selected=system.software.computerId valueAttr="_id" labelAttr="name"}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="field-group">
|
{{/if}}
|
||||||
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
|
||||||
<select name="system.container.id">
|
|
||||||
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
|
||||||
{{#if (eq system.subType "software")}}
|
|
||||||
<div class="field-group" style="margin-top:8px;">
|
|
||||||
<label>{{ localize 'MGT2.Items.Bandwidth' }}</label>
|
|
||||||
<input type="number" name="system.software.bandwidth" value="{{system.software.bandwidth}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
24
templates/items/parts/sheet-physical-item-tab.html
Normal file
24
templates/items/parts/sheet-physical-item-tab.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Quantity' }}</label>
|
||||||
|
<input type="number" name="system.quantity" value="{{system.quantity}}" data-dtype="Number" integer="true" positive="true" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Weight' }} ({{unitlabels.weight}})</label>
|
||||||
|
<input type="number" name="weight" value="{{weight}}" data-dtype="Number" step="0.5" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
|
<label class="mgt2-checkbox">
|
||||||
|
<input type="checkbox" name="system.weightless" data-dtype="Boolean" {{checked system.weightless}} />
|
||||||
|
{{ localize 'MGT2.Items.Weightless' }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Cost' }}</label>
|
||||||
|
<input type="number" name="system.cost" value="{{system.cost}}" data-dtype="Number" step="1" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.TL' }}</label>
|
||||||
|
<select name="system.tl">
|
||||||
|
{{selectOptions config.TL selected=system.tl localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
@@ -15,11 +15,11 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
{{editor system.descriptionLong target="system.descriptionLong" button=true editable=true}}
|
{{formInput systemFields.descriptionLong enriched=enrichedDescriptionLong value=system.descriptionLong name="system.descriptionLong" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab3">
|
<div class="tab" data-group="primary" data-tab="tab3">
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="{{cssClass}} flexrow itemsheet">
|
<div class="{{cssClass}} itemsheet">
|
||||||
<div class="item-type-bar">
|
<div class="item-type-bar">
|
||||||
{{#if (eq system.subType "skill")}}
|
{{#if (eq system.subType "skill")}}
|
||||||
<span class="item-type-label"><i class="fas fa-star"></i> {{localize 'MGT2.TalentSubType.skill'}}</span>
|
<span class="item-type-label"><i class="fas fa-star"></i> {{localize 'MGT2.TalentSubType.skill'}}</span>
|
||||||
@@ -10,68 +10,75 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Type' }}</span>
|
|
||||||
<select name="system.subType" style="font-size:0.75rem;">
|
|
||||||
{{selectOptions config.TalentSubType selected=system.subType localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{{#if (eq system.subType "skill")}}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Level' }}</span>
|
|
||||||
<input type="number" name="system.level" value="{{system.level}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Speciality' }}</span>
|
|
||||||
<input type="text" name="system.skill.speciality" value="{{system.skill.speciality}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
{{else if (eq system.subType "psionic")}}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Level' }}</span>
|
|
||||||
<input type="number" name="system.level" value="{{system.level}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.PSICost' }}</span>
|
|
||||||
<input type="number" name="system.psionic.cost" value="{{system.psionic.cost}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Reach' }}</span>
|
|
||||||
<select name="system.psionic.reach">
|
|
||||||
<option></option>
|
|
||||||
{{selectOptions config.PsionicReach selected=system.psionic.reach localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="config">{{ localize 'MGT2.Items.Configuration' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
|
<a class="item tab-select" data-tab="tab3">{{ localize 'MGT2.Items.Configuration' }}</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content-area">
|
<div class="tab-content-area">
|
||||||
|
|
||||||
|
{{!-- Tab 1 : Description --}}
|
||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
{{#if (eq system.subType "psionic")}}
|
<div class="field-group">
|
||||||
<div class="field-groups" style="margin-bottom:8px;">
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<div class="field-group">
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- Tab 2 : Détails --}}
|
||||||
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
|
<div class="item-details-grid">
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Type' }}</label>
|
||||||
|
<select name="system.subType">
|
||||||
|
{{selectOptions config.TalentSubType selected=system.subType localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Level' }}</label>
|
||||||
|
<input type="number" name="system.level" value="{{system.level}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
{{#if (eq system.subType "skill")}}
|
||||||
|
<div class="field-row full">
|
||||||
|
<label>{{ localize 'MGT2.Items.Speciality' }}</label>
|
||||||
|
<input type="text" name="system.skill.speciality" value="{{system.skill.speciality}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
|
<label class="mgt2-checkbox">
|
||||||
|
<input type="checkbox" name="system.skill.reduceEncumbrance" data-dtype="Boolean" {{checked system.skill.reduceEncumbrance}} />
|
||||||
|
{{ localize 'MGT2.Items.ReduceEncumbrance' }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{{else if (eq system.subType "psionic")}}
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.PSICost' }}</label>
|
||||||
|
<input type="number" name="system.psionic.cost" value="{{system.psionic.cost}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Reach' }}</label>
|
||||||
|
<select name="system.psionic.reach">
|
||||||
|
<option value=""></option>
|
||||||
|
{{selectOptions config.PsionicReach selected=system.psionic.reach localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row full">
|
||||||
<label>{{ localize 'MGT2.Items.Duration' }}</label>
|
<label>{{ localize 'MGT2.Items.Duration' }}</label>
|
||||||
<div style="display:flex;gap:4px;">
|
<div class="range-inputs">
|
||||||
<input type="text" name="system.psionic.duration" value="{{system.psionic.duration}}" data-dtype="String" />
|
<input type="text" name="system.psionic.duration" value="{{system.psionic.duration}}" data-dtype="String" />
|
||||||
<select name="system.psionic.durationUnit">
|
<select name="system.psionic.durationUnit">
|
||||||
{{selectOptions config.Durations selected=system.psionic.durationUnit localize=true}}
|
{{selectOptions config.Durations selected=system.psionic.durationUnit localize=true}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="config">
|
|
||||||
{{#if (eq system.subType "skill")}}
|
{{!-- Tab 3 : Configuration (jet de dé) --}}
|
||||||
<div class="field-group">
|
<div class="tab" data-group="primary" data-tab="tab3">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.skill.reduceEncumbrance" data-dtype="Boolean" {{checked system.skill.reduceEncumbrance}} />{{ localize 'MGT2.Items.ReduceEncumbrance' }}</label>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{> systems/mgt2/templates/items/parts/sheet-configuration.html }}
|
{{> systems/mgt2/templates/items/parts/sheet-configuration.html }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,28 +6,7 @@
|
|||||||
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
<img class="item-header-img" src="{{item.img}}" data-edit="img" data-tooltip="{{item.name}}" />
|
||||||
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
<input class="item-header-name" name="name" type="text" value="{{item.name}}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="item-stats-bar">
|
|
||||||
{{> systems/mgt2/templates/items/parts/sheet-physical-item.html }}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Damage' }}</span>
|
|
||||||
<input type="text" name="system.damage" value="{{system.damage}}" data-dtype="String" />
|
|
||||||
</div>
|
|
||||||
{{#unless system.range.isMelee}}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Range' }}</span>
|
|
||||||
<div style="display:flex;gap:3px;align-items:center;">
|
|
||||||
<input type="text" name="system.range.value" value="{{system.range.value}}" data-dtype="String" style="width:3rem;" />
|
|
||||||
<select name="system.range.unit" style="width:5rem;">
|
|
||||||
{{selectOptions config.MetricRange selected=system.range.unit localize=true}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/unless}}
|
|
||||||
<div class="item-stat-pill">
|
|
||||||
<span class="stat-label">{{ localize 'MGT2.Items.Magazine' }}</span>
|
|
||||||
<input type="number" name="system.magazine" value="{{system.magazine}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav class="horizontal-tabs tabs" data-group="primary">
|
<nav class="horizontal-tabs tabs" data-group="primary">
|
||||||
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
<a class="item tab-select" data-tab="tab1">{{ localize 'MGT2.Items.Description' }}</a>
|
||||||
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
<a class="item tab-select" data-tab="tab2">{{ localize 'MGT2.Items.Details' }}</a>
|
||||||
@@ -37,19 +16,61 @@
|
|||||||
<div class="tab" data-group="primary" data-tab="tab1">
|
<div class="tab" data-group="primary" data-tab="tab1">
|
||||||
<div class="field-group">
|
<div class="field-group">
|
||||||
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
<label>{{ localize 'MGT2.Items.Description' }}</label>
|
||||||
<textarea name="system.description" rows="6">{{system.description}}</textarea>
|
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab" data-group="primary" data-tab="tab2">
|
<div class="tab" data-group="primary" data-tab="tab2">
|
||||||
<div class="field-groups">
|
<div class="item-details-grid">
|
||||||
<div class="field-group">
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Quantity' }}</label>
|
||||||
|
<input type="number" name="system.quantity" value="{{system.quantity}}" data-dtype="Number" integer="true" positive="true" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.TL' }}</label>
|
||||||
|
<select name="system.tl">{{selectOptions config.TL selected=system.tl localize=true}}</select>
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Weight' }} ({{unitlabels.weight}})</label>
|
||||||
|
<input type="number" name="weight" value="{{weight}}" data-dtype="Number" step="0.5" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Cost' }}</label>
|
||||||
|
<input type="number" name="system.cost" value="{{system.cost}}" data-dtype="Number" step="1" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Damage' }}</label>
|
||||||
|
<input type="text" name="system.damage" value="{{system.damage}}" data-dtype="String" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Magazine' }}</label>
|
||||||
|
<input type="number" name="system.magazine" value="{{system.magazine}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
{{#unless system.range.isMelee}}
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.Range' }}</label>
|
||||||
|
<div class="range-inputs">
|
||||||
|
<input type="text" name="system.range.value" value="{{system.range.value}}" data-dtype="String" />
|
||||||
|
<select name="system.range.unit">
|
||||||
|
{{selectOptions config.MetricRange selected=system.range.unit localize=true}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
<div class="field-row">
|
||||||
|
<label>{{ localize 'MGT2.Items.MagazineCost' }}</label>
|
||||||
|
<input type="number" name="system.magazineCost" value="{{system.magazineCost}}" data-dtype="Number" class="short" />
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.weightless" data-dtype="Boolean" {{checked system.weightless}} />{{ localize 'MGT2.Items.Weightless' }}</label>
|
||||||
|
</div>
|
||||||
|
<div class="field-row field-row--check">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.range.isMelee" data-dtype="Boolean" {{checked system.range.isMelee}} />{{ localize 'MGT2.Items.IsMelee' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.range.isMelee" data-dtype="Boolean" {{checked system.range.isMelee}} />{{ localize 'MGT2.Items.IsMelee' }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group">
|
<div class="field-row field-row--check">
|
||||||
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="system.equipped" data-dtype="Boolean" {{checked system.equipped}} />{{ localize 'MGT2.Items.Equipped' }}</label>
|
||||||
</div>
|
</div>
|
||||||
{{#if hadContainer}}
|
{{#if hadContainer}}
|
||||||
<div class="field-group">
|
<div class="field-row full">
|
||||||
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
<label>{{ localize 'MGT2.Items.Storage' }}</label>
|
||||||
<select name="system.container.id">
|
<select name="system.container.id">
|
||||||
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
{{selectOptions containers selected=system.container.id valueAttr="_id" labelAttr="name"}}
|
||||||
@@ -57,10 +78,6 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-group" style="margin-top:8px;">
|
|
||||||
<label>{{ localize 'MGT2.Items.MagazineCost' }}</label>
|
|
||||||
<input type="number" name="system.magazineCost" value="{{system.magazineCost}}" data-dtype="Number" />
|
|
||||||
</div>
|
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<div class="table-row heading">
|
<div class="table-row heading">
|
||||||
<div class="row-item row-item-left">{{ localize 'MGT2.Items.Trait' }}</div>
|
<div class="row-item row-item-left">{{ localize 'MGT2.Items.Trait' }}</div>
|
||||||
|
|||||||
@@ -1,4 +1,32 @@
|
|||||||
<form class="{{cssClass}} flexcol" autocomplete="off" style="padding: 0 6px;">
|
<form class="{{cssClass}} flexcol" autocomplete="off" style="padding: 0 6px;">
|
||||||
|
|
||||||
|
{{!-- Hidden fields for healing --}}
|
||||||
|
{{#if showHeal}}
|
||||||
|
<input type="hidden" name="healType" value="{{healType}}" />
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- ── Mode CRÉATURE : sélecteur de compétence de la créature ── --}}
|
||||||
|
{{#if isCreature}}
|
||||||
|
|
||||||
|
{{#if showSkillSelector}}
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ localize 'MGT2.RollPrompt.CreatureSkill' }}</label>
|
||||||
|
<select name="creatureSkillIndex">
|
||||||
|
<option value="-1">— {{ localize 'MGT2.RollPrompt.NoSkill' }} —</option>
|
||||||
|
{{#each creatureSkills}}
|
||||||
|
<option value="{{@index}}" {{#if (eq @index ../selectedSkillIndex)}}selected{{/if}}>{{name}} ({{showDM level}})</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="form-group roll-prompt-info">
|
||||||
|
<span class="roll-prompt-skill-name">{{skillName}}</span>
|
||||||
|
<span class="roll-prompt-skill-level">{{showDM skillLevel}}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{!-- ── Mode PERSONNAGE : caractéristique + compétence + états ── --}}
|
||||||
|
{{else}}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{ localize 'MGT2.RollPrompt.CharacteristicDM' }}</label>
|
<label>{{ localize 'MGT2.RollPrompt.CharacteristicDM' }}</label>
|
||||||
<select name="characteristic">
|
<select name="characteristic">
|
||||||
@@ -25,14 +53,34 @@
|
|||||||
<label class="mgt2-checkbox"><input type="checkbox" name="fatigue" data-dtype="Boolean" {{checked fatigue}} />{{ localize 'MGT2.RollPrompt.FatigueDM' }}</label>
|
<label class="mgt2-checkbox"><input type="checkbox" name="fatigue" data-dtype="Boolean" {{checked fatigue}} />{{ localize 'MGT2.RollPrompt.FatigueDM' }}</label>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{ localize 'MGT2.RollPrompt.CustomDM' }}</label>
|
<label>{{ localize 'MGT2.RollPrompt.CustomDM' }}</label>
|
||||||
<input type="text" name="customDM" maxlength="15" />
|
<select name="customDM">
|
||||||
|
<option value="-8">−8</option>
|
||||||
|
<option value="-7">−7</option>
|
||||||
|
<option value="-6">−6</option>
|
||||||
|
<option value="-5">−5</option>
|
||||||
|
<option value="-4">−4</option>
|
||||||
|
<option value="-3">−3</option>
|
||||||
|
<option value="-2">−2</option>
|
||||||
|
<option value="-1">−1</option>
|
||||||
|
<option value="0" selected>0</option>
|
||||||
|
<option value="1">+1</option>
|
||||||
|
<option value="2">+2</option>
|
||||||
|
<option value="3">+3</option>
|
||||||
|
<option value="4">+4</option>
|
||||||
|
<option value="5">+5</option>
|
||||||
|
<option value="6">+6</option>
|
||||||
|
<option value="7">+7</option>
|
||||||
|
<option value="8">+8</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{ localize 'MGT2.RollPrompt.Difficulty' }}</label>
|
<label>{{ localize 'MGT2.RollPrompt.Difficulty' }}</label>
|
||||||
<select name="difficulty">
|
<select name="difficulty">
|
||||||
<option></option>
|
<option value="">—</option>
|
||||||
{{selectOptions config.Difficulty selected = difficulty localize = true}}
|
{{selectOptions config.Difficulty selected = difficulty localize = true}}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user