Mise àjour vers 9.6.0
Validation JSON / validate (push) Successful in 13s

This commit is contained in:
2026-05-18 07:23:40 +02:00
parent 52939af8c8
commit 38d88c2f19
204 changed files with 4123 additions and 3343 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
} }
], ],
"url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr", "url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr",
"version": "9.4.3", "version": "9.6.0",
"esmodules": [ "esmodules": [
"wh4_fr.js", "wh4_fr.js",
"modules/babele-register.js", "modules/babele-register.js",
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
return args.item?.system?.isProjectiles && args.data.targets[0]?.actor?.sizeNum < 3 return args.item?.system?.isRanged && args.data.targets[0]?.actor?.sizeNum < 3
+1
View File
@@ -0,0 +1 @@
this.item.system.encumbrance.value = Math.max(0, this.item.system.encumbrance.value - 1)
+18
View File
@@ -0,0 +1,18 @@
let melee = ["Compendium.wfrp4e-core.items.Item.4MJJCiOKPkBByYwW", "Compendium.wfrp4e-core.items.Item.RWJrupj9seau0w31", "Compendium.wfrp4e-core.items.Item.jt0DmVK9IiF6Sd2h"];
let ranged = ["Compendium.wfrp4e-core.items.Item.5eDd6iFeR9G6cCfz", "Compendium.wfrp4e-core.items.Item.jrYW2OyDHd1Md2my", "Compendium.wfrp4e-core.items.Item.cygaI9gq4BQJvbB5"];
if (args.equipped)
{
if (this.item.system.isMelee)
{
this.actor.addEffectItems(melee, this.effect);
}
else
{
this.actor.addEffectItems(ranged, this.effect);
}
}
else
{
this.effect.deleteCreatedItems();
}
+5
View File
@@ -0,0 +1,5 @@
let property = this.effect.getFlag("wfrp4e", "property");
if (property && !this.item.system.flaws.value.find(i => i.name == property));
{
this.item.system.flaws.value.push({name : property});
}
+17 -14
View File
@@ -1,28 +1,31 @@
if (!this.item.name.includes("(") || this.item.system.tests.value.includes("Terrain") || this.item.system.tests.value.toLowerCase().includes("(any)")) { if (!this.item.name.includes("(") || this.item.system.tests.value.includes("Terrain") || this.item.system.tests.value.toLowerCase().includes("(any)"))
{
let tests = this.item.system.tests.value let tests = this.item.system.tests.value
let name = this.item.name let name = this.item.name
// If name already specifies, make sure Tests value reflects that // Si le nom précise déjà un terrain, on met à jour la valeur de tests
if (name.includes("(") && !name.toLowerCase().includes("(any)")) { if (name.includes("(") && !name.toLowerCase().includes("(any)"))
{
let terrain = name.split("(")[1].split(")")[0] let terrain = name.split("(")[1].split(")")[0]
tests = tests.replace("the Terrain", terrain) tests = tests.replace("the Terrain", terrain)
} }
else // If no sense specified, provide dialog choice else // Sinon, on propose un choix par dialogue
{ {
let choice = await ItemDialog.create(ItemDialog.objectToArray({ let choice = await ItemDialog.create(ItemDialog.objectToArray({
coastal: "Littoral", coastal : "Littoral",
deserts: "Déserts", deserts : "Déserts",
marshes: "Marécages", marshes : "Marécages",
rocky: "Rocailleux", rocky : "Rocailleux",
tundra: "Toundra", tundra : "Toundra",
woodlands: "Régions boisées" woodlands : "Régions boisées"
}, this.item.img), 1, "Choisissez un Terrain"); }, this.item.img), 1, "Choisissez un Terrain");
if (choice[0]) { if (choice[0])
{
name = `${name.split("(")[0].trim()} (${choice[0].name})` name = `${name.split("(")[0].trim()} (${choice[0].name})`
tests = tests.replace("Terrain", choice[0].name + " Terrain") tests = tests.replace("the Terrain", choice[0].name + " Terrain")
} }
} }
this.effect.updateSource({ name }) this.effect.updateSource({name})
this.item.updateSource({ name, "system.tests.value": tests }) this.item.updateSource({name, "system.tests.value" : tests})
} }
+21
View File
@@ -0,0 +1,21 @@
let damage = await new Roll("1d10").roll();
damage.toMessage(this.script.getChatData());
this.actor.applyDamage(damage.total, {
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL,
createMessage: this.script.getChatData()
});
const test = await this.actor.setupSkill(
game.i18n.localize("NAME.Endurance"),
{
fields: {difficulty: "average"},
skipTargets: true,
appendTitle: `${this.effect.name}`,
},
);
await test.roll();
if (test.failed)
{
this.actor.addCondition("stunned");
}
+1 -1
View File
@@ -1,4 +1,4 @@
if (args.opposedTest.result.hitloc.value == this.item.system.location.key && args.totalWoundLoss > 0) if (args.loc == this.item.system.location.key && args.totalWoundLoss > 0)
{ {
args.actor.addCondition("bleeding", 2); args.actor.addCondition("bleeding", 2);
} }
+1
View File
@@ -0,0 +1 @@
if (!this.item.system.properties.qualities.pummel) this.item.system.qualities.value.push({name : 'pummel'});if (!this.item.system.properties.qualities.hack) this.item.system.qualities.value.push({name : 'hack'})
+1
View File
@@ -0,0 +1 @@
return game.messages.get(args.context.dispel)?.system.test.spell.system.magicMissile.value;
+1 -1
View File
@@ -1 +1 @@
args.prefillModifiers.difficulty = "hard" args.fields.difficulty = "hard"
+6
View File
@@ -0,0 +1,6 @@
let damage = await new Roll("1d10 + 1").roll();
damage.toMessage(this.script.getChatData());
this.actor.applyDamage(damage.total, {
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_AP,
createMessage: this.script.getChatData()
});
+10
View File
@@ -0,0 +1,10 @@
if (args.type == "effect" && args.options.action == "delete" && ["prone"].some(i => args.document.statuses.has(i)))
{
this.script.notification("Impossible de retirer " + args.document.name);
let resist = await this.effect.resistEffect();
if (resist)
{
this.effect.delete();
}
return resist;
}
+1 -1
View File
@@ -5,5 +5,5 @@ let SL = Math.floor(args.test.target / 10) - Math.floor(args.test.result.roll /
let ones = Number(args.test.result.roll.toString().split("").pop()) let ones = Number(args.test.result.roll.toString().split("").pop())
if (ones > SL) if (ones > SL)
args.Test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`) args.test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`)
} }
+7
View File
@@ -0,0 +1,7 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Pray"), {appendTitle: ` - ${this.effect.name}`});
await test.roll();
if (test.succeeded)
{
this.actor.removeCondition("blinded", 1 + parseInt(test.result.SL));
}
+1
View File
@@ -0,0 +1 @@
args.options.terror
+6
View File
@@ -0,0 +1,6 @@
let roll = await new Roll("2d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {
value: roll.total,
units: "days"
}});
+6
View File
@@ -0,0 +1,6 @@
let roll = await new Roll("2d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {
value: roll.total,
units: "rounds"
}});
+1
View File
@@ -0,0 +1 @@
this.actor.modifyWounds(-1);
+21
View File
@@ -0,0 +1,21 @@
let damage = await new Roll("1d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
damage.toMessage(this.script.getChatData());
this.actor.applyDamage(damage.total, {
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL,
createMessage: this.script.getChatData()
});
const test = await this.actor.setupSkill(
game.i18n.localize("NAME.Endurance"),
{
fields: {difficulty: "difficult"},
skipTargets: true,
appendTitle: `${this.effect.name}`,
},
);
await test.roll();
if (test.failed)
{
this.actor.addCondition("stunned");
}
+1 -1
View File
@@ -5,5 +5,5 @@ let SL = Math.floor(args.test.target / 10) - Math.floor(args.test.result.roll /
let ones = Number(args.test.result.roll.toString().split("").pop()) let ones = Number(args.test.result.roll.toString().split("").pop())
if (ones > SL) if (ones > SL)
args.Test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`) args.test.result.other.push(`<span class="hide-option"><b>${this.effect.name}</b>: ${ones + args.test.successBonus + args.test.slBonus} DR</span>`)
} }
+27
View File
@@ -0,0 +1,27 @@
let roll = await new Roll("1d10").roll();
roll.toMessage(this.script.getChatData());
if (roll.total == 1)
{
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: The weapon counts as a @Corruption[minor]{minor source of Corruption}.</p>`});
}
else if (roll.total <= 5)
{
let quirks = await fromUuid("Compendium.wfrp4e-archives2.tables.RollTable.LbNZOF6Ov7xKHS5Z");
if (quirks)
{
let quirkRoll = await new Roll("1d100 + 40").roll();
quirkRoll.toMessage(this.script.getChatData());
let quirkResult = (await quirks.roll({roll: quirkRoll})).results[0].text;
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: ${quirkResult.replace("<p>", "")}</p>`});
}
else
{
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: Generate an additional Quirk or Curse by rolling on the @UUID[Compendium.wfrp4e-archives2.tables.RollTable.LbNZOF6Ov7xKHS5Z]{Quirks and Curses} Table and adding +40 to the result.</p>`});
}
}
else
{
this.item.updateSource({"system.description.value" : this.item.system.description.value += `<p><strong>${this.effect.name}</strong>: People who recognise the weapon are subject to @UUID[Compendium.wfrp4e-core.items.Item.0VpT5yubw4UL7j6f]{Animosity} towards the bearer.</p>`});
}
+2 -2
View File
@@ -11,8 +11,8 @@ if (args.test.result.castOutcome == "failure")
this.script.notification(`Lost ${value} Wounds`) this.script.notification(`Lost ${value} Wounds`)
this.actor.modifyWounds(-1 * value) this.actor.modifyWounds(-1 * value)
await this.item.system.toggleEquip(); await this.item.system.toggleEquip();
args.Test.addSL(value); args.test.addSL(value);
args.Test.preData.other.push(`<strong>${this.effect.name}</strong>: +${value} SL`) args.test.preData.other.push(`<strong>${this.effect.name}</strong>: +${value} SL`)
} }
}) })
} }
+7
View File
@@ -0,0 +1,7 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`})
await test.roll();
if (test.failed && this.actor.type == "character")
{
this.actor.update({"system.status.corruption.value" : parseInt(this.actor.status.corruption.value) + 1})
this.script.message("Gagné un point de Corruption", {whisper : ChatMessage.getWhisperRecipients("GM")})
}
+1 -1
View File
@@ -13,7 +13,7 @@ const test = await this.actor.setupSkill(game.i18n.localize("NAME.Résistance"),
await test.roll(); await test.roll();
if (test.failed) { if (test.failed) {
await this.actor.addEffectItems(bloodyFluxUUID, this.effet); await this.actor.addEffectItems(bloodyFluxUUID, this.effect);
} else { } else {
const SL = test.result.SL; const SL = test.result.SL;
const heal = 1 + SL; const heal = 1 + SL;
+4
View File
@@ -0,0 +1,4 @@
this.actor.addCondition("blinded");
let roll = await new Roll("1d10").roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {value: roll.total, units: "hours"}});
+5
View File
@@ -0,0 +1,5 @@
if (args.sourceTest.options.doubleDamage)
{
args.modifiers.other.push({label: this.effect.name, value: args.totalWoundLoss});
args.totalWoundLoss *= 2;
}
+10
View File
@@ -0,0 +1,10 @@
let test = args.test
if (test && test.spell?.system.magicMissile.value)
{
let roll = await new Roll("1d100").roll();
roll.toMessage(this.script.getChatData());
if (roll.total <= 30)
{
this.script.message(`<strong>${this.item.name}</strong> : Le sort échoue !`)
}
}
+9
View File
@@ -0,0 +1,9 @@
if (args.test.skill?.name == game.i18n.localize("NAME.Pray") || args.test.prayer)
{
if (parseInt(args.test.result.SL) > 0)
{
args.test.result.SL = "+0";
args.test.result.description = game.i18n.localize("ROLL.MarginalSuccess");
args.test.result.other.push(`<strong>${this.effect.name}</strong>: Maximum +0 SL`)
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
let halve; let halve;
if (args.opposedTest.attackerTest.item?.type != "spell") if (args.sourceItem?.type != "spell")
{ {
halve = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : "Diviser les dégâts par deux ? (Divise tous les dégâts sauf le feu, le froid et la magie)"}) halve = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : "Diviser les dégâts par deux ? (Divise tous les dégâts sauf le feu, le froid et la magie)"})
} }
+14
View File
@@ -0,0 +1,14 @@
let properties = {
fine : "Fine",
durable : "Durable",
lightweight : "Lightweight",
practical : "Practical"
};
let choice = await ItemDialog.create(ItemDialog.objectToArray(properties), 1, {title: this.effect.name, text: "Select Property"});
if (choice[0])
{
this.effect.updateSource({"flags.wfrp4e.property" : choice[0].id, name : this.effect.setSpecifier(choice[0].name)});
}
+26
View File
@@ -0,0 +1,26 @@
let colors = {
fire : "#b22222",
heavens : "#87ceeb",
metal : "#ee9b3a",
shadow : "#808080",
life : "#008000",
beasts : "#a52a2a",
light : "#f0ffff",
death : "#800080",
necromancy : "#800080",
daemonology : "#8b0000"
};
let spell = this.actor.itemTypes.spell.find(i => Object.keys(colors).includes(i.system.lore.value[0]));
let color;
if (spell)
{
color = colors[spell.system.lore.value[0]];
}
else
{
color = Object.values(colors)[Math.ceil(CONFIG.Dice.randomUniform() * 10)];
}
this.effect.updateSource({changes: this.effect.changes.concat({key: "token.light.color", type: "override", value: color})});
+15
View File
@@ -0,0 +1,15 @@
let qualities = {
fast : "Rapide",
hack : "Tranchant",
impale : "Empalant",
penetrating : "Pénétrant",
precise : "Précis"
}
let choice = await ItemDialog.create(ItemDialog.objectToArray(qualities, this.item.img), 1, {text: "Choisissez une qualité", title: this.effect.name});
if (choice[0])
{
this.script.message(choice[0].name);
this.effect.setFlag("wfrp4e", "quality", choice[0].id);
}
+1
View File
@@ -0,0 +1 @@
if (args.totalWoundLoss > 0) args.actor.addCondition('ablaze')
+2 -2
View File
@@ -2,7 +2,7 @@ let lore = this.effect.name.split("(")[1].split(")")[0].toLowerCase();
// If channelling corresponding lore // If channelling corresponding lore
if (args.type == "channelling" && args.spell.system.lore.value == lore) if (args.type == "channelling" && args.spell.system.lore.value == lore)
args.prefillModifiers.slBonus += 2 args.fields.slBonus += 2
// If channelling or casting different lore // If channelling or casting different lore
else if (args.spell.system.lore.value != lore && args.spell.system.lore.value != "petty") else if (args.spell.system.lore.value != lore && args.spell.system.lore.value != "petty")
args.prefillModifiers.slBonus -= 1 args.fields.slBonus -= 1
+6
View File
@@ -0,0 +1,6 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields : {difficulty : "hard"}, context : {failure: "Gain Broken"}});
await test.roll();
if (test.failed)
{
this.actor.addCondition("broken");
}
+5 -2
View File
@@ -1,5 +1,8 @@
if (args.opposedTest.attackerTest.weapon?.system.properties?.qualities.hack && !args.hackReminder) if (args.sourceItem?.system.properties?.qualities.hack && !args.hackReminder)
{ {
args.hackReminder = true; args.hackReminder = true;
args.opposedTest.result.other.push(`<strong>${this.effect.name}</strong>: Hack causes ${this.item.Advances} extra damage`) if (args.opposedTest)
{
args.opposedTest.result.other.push(`<strong>${this.effect.name}</strong> : Tranchant inflige ${this.item.Advances} dégâts supplémentaires`)
}
} }
+7 -4
View File
@@ -1,11 +1,14 @@
if (args.totalWoundLoss > 0) { if (args.totalWoundLoss > 0) {
if (args.opposedTest)
{
args.opposedTest.result.other.push( args.opposedTest.result.other.push(
`@Corruption[minor]{Moderate Exposure to Corruption}` `@Corruption[minor]{Exposition modérée à la Corruption}`
) )
}
this.script.message(`<strong>${this.effect.name}</strong>: this.script.message(`<strong>${this.effect.name}</strong>:
@Corruption[moderate]{Moderate Exposure to Corruption} <br/> @Corruption[moderate]{Exposition modérée à la Corruption} <br/>
<strong>${args.actor.prototypeToken.name}</strong> must take an <strong>${args.actor.prototypeToken.name}</strong> doit effectuer un
<strong>Corruption (Moderate) Test</strong>`, <strong>Test de Corruption (Modéré)</strong>`,
{whisper: ChatMessage.getWhisperRecipients("GM")} {whisper: ChatMessage.getWhisperRecipients("GM")}
) )
} }
+2 -2
View File
@@ -1,6 +1,6 @@
if ((args.opposedTest.attackerTest.item && args.opposedTest.attackerTest.item.isMelee) || (args.opposedTest.attackerTest.item && !args.opposedTest.attackerTest.item.name.includes("Projectiles"))) if ((args.sourceItem && args.sourceItem.isMelee) || (args.sourceItem && !args.sourceItem.name.includes("Projectiles")))
{ {
let choice = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : `<p>Apply damage with <strong>${this.effect.name}</strong> to attacker?`}) let choice = await foundry.applications.api.DialogV2.confirm({window : {title : this.effect.name}, content : `<p>Appliquer les dégâts avec <strong>${this.effect.name}</strong> à l'attaquant ?`})
if (choice) if (choice)
{ {
+1 -1
View File
@@ -1,2 +1,2 @@
args.prefillModifiers.modifier += 10 args.fields.modifier += 10
+12
View File
@@ -0,0 +1,12 @@
let properties = {
ugly : "Ugly",
shoddy : "Shoddy",
unreliable : "Unreliable"
};
let choice = await ItemDialog.create(ItemDialog.objectToArray(properties), 1, {title: this.effect.name, text: "Select Property"});
if (choice[0])
{
this.effect.updateSource({"flags.wfrp4e.property" : choice[0].id, name : this.effect.setSpecifier(choice[0].name)});
}
+4
View File
@@ -0,0 +1,4 @@
let skills = this.actor.itemTypes.skill.filter(s => (this.effect.getFlag("wfrp4e", "skills") || []).includes(s.name));
skills.forEach(s => {
s.system.modifier.value -= 10;
})
+1 -1
View File
@@ -1,4 +1,4 @@
if (args.opposedTest.result.hitloc.value == this.item.system.location.key && args.totalWoundLoss > 0) if (args.loc == this.item.system.location.key && args.totalWoundLoss > 0)
{ {
args.actor.addCondition("bleeding", 2); args.actor.addCondition("bleeding", 2);
this.script.notification("Etat Hémorragique ajouté") this.script.notification("Etat Hémorragique ajouté")
+4 -3
View File
@@ -1,8 +1,9 @@
if (args.opposedTest.result.hitloc.value == "body") if (args.loc == "body")
{ {
if ((await new Roll("1d2").roll()).total == 1) if ((await new Roll("1d2").roll()).total == 1)
{ {
args.opposedTest.result.hitloc.value = "head" args.loc = "head"
this.script.message(`Localisation du coup changé pour la tête`) args.AP = foundry.utils.deepClone(args.actor.status.armour[args.loc]);
this.script.message(`Localisation du coup changée pour la tête`)
} }
} }
+5
View File
@@ -0,0 +1,5 @@
let locs = Object.keys(this.actor.system.status.armour);
let location = locs[Math.floor(CONFIG.Dice.randomUniform() * (locs.length))];
game.wfrp4e.tables.formatChatRoll(`crit${location}`, {criticalLocation: location, showRoll: true});
+3
View File
@@ -0,0 +1,3 @@
let roll = await new Roll("1d10").roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {value: roll.total, units: "hours"}});
+2
View File
@@ -0,0 +1,2 @@
let skill = this.actor.itemTypes.skill.find(s => s.name === game.i18n.localize("NAME.Pray"));
skill.system.modifier.value -= 10;
+27
View File
@@ -0,0 +1,27 @@
this.actor.addCondition("ablaze");
let colors = {
fire : "#b22222",
heavens : "#87ceeb",
metal : "#ee9b3a",
shadow : "#808080",
life : "#008000",
beasts : "#a52a2a",
light : "#f0ffff",
death : "#800080",
necromancy : "#800080",
daemonology : "#8b0000"
};
let spell = this.actor.itemTypes.spell.find(i => Object.keys(colors).includes(i.system.lore.value[0]));
let color;
if (spell)
{
color = colors[spell.system.lore.value[0]];
}
else
{
color = Object.values(colors)[Math.ceil(CONFIG.Dice.randomUniform() * 10)];
}
this.effect.updateSource({changes: this.effect.changes.concat({key: "token.light.color", type: "override", value: color})});
+1 -1
View File
@@ -1,4 +1,4 @@
if (args.opposedTest.result.hitloc.value == "body" && args.totalWoundLoss > 0) if (args.loc == "body" && args.totalWoundLoss > 0)
{ {
args.actor.addCondition("bleeding", 2) args.actor.addCondition("bleeding", 2)
this.script.notification("Etat Hémmoragique appliqué : 2 niveaux de saignement") this.script.notification("Etat Hémmoragique appliqué : 2 niveaux de saignement")
+5
View File
@@ -0,0 +1,5 @@
if (args.type == "effect" && args.options.action == "delete" && ["blinded"].some(i => args.document.statuses.has(i)))
{
this.script.notification("Impossible de retirer " + args.document.name);
return false;
}
+1 -1
View File
@@ -25,7 +25,7 @@ if (god)
if (blessings.length) if (blessings.length)
{ {
this.script.scriptNotification("Ajout de " + blessings.map(i => i.name).join(", ")) this.script.scriptNotification("Ajout de " + blessings.map(i => i.name).join(", "))
await this.actor.addEffectItems(blessings.map(i => i.uuid), this.effet) await this.actor.addEffectItems(blessings.map(i => i.uuid), this.effect)
} }
else else
{ {
+1
View File
@@ -0,0 +1 @@
this.actor.addCondition("deafened");
+1
View File
@@ -0,0 +1 @@
game.wfrp4e.tables.formatChatRoll(`mutatephys`, {showRoll: true});
+5
View File
@@ -0,0 +1,5 @@
if (args.totalWoundLoss > 0)
{
args.modifiers.other.push({label : this.effect.name, value : args.totalWoundLoss + 4})
args.totalWoundLoss = (args.totalWoundLoss * 2) + 4
}
+9
View File
@@ -0,0 +1,9 @@
await this.actor.addCondition("blinded");
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {appendTitle: ` - ${this.effect.name}`, skipTargets: true});
await test.roll();
if (test.failed)
{
await this.actor.addCondition("blinded");
}
+3
View File
@@ -0,0 +1,3 @@
if (!this.item.system.properties.qualities.fast) this.item.system.qualities.value.push({name : 'fast'});
if (!this.item.system.properties.qualities.precise) this.item.system.qualities.value.push({name : 'precise'})
if (!this.item.system.properties.qualities.penetrating) this.item.system.qualities.value.push({name : 'penetrating'})
+1 -1
View File
@@ -1 +1 @@
return !args.item?.system.isProjectiles return !args.item?.system.isRanged
+16
View File
@@ -0,0 +1,16 @@
scatter = await game.wfrp4e.tables.rollTable("scatter");
this.script.message(scatter.result);
let distance = await new Roll("1d10").roll();
distance.toMessage(this.script.getChatData({flavor: "Distance (yds.)"}));
let damage = await new Roll("1d10").roll();
damage.toMessage(this.script.getChatData({flavor: "Dégâts"}));
this.actor.applyDamage(damage.total, {
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_AP,
createMessage: this.script.getChatData()
});
this.actor.addCondition("prone");
+33
View File
@@ -0,0 +1,33 @@
let ingredients = this.actor.itemTypes.trapping.filter(i => i.system.trappingType.value == "ingredient");
if (ingredients.length == 0)
{
return this.script.notification("Aucun ingrédient !");
}
this.script.notification("Affecté : " + ingredients.map(i => i.name).join(", "));
for(let i of ingredients)
{
await i.update({
name: i.setSpecifier("Souillé"),
effects: [{
name: "Souillé",
img: i.img,
system: {
transferData :{
documentType: "Item"
},
scriptData: [
{
label: "Influence Maléfique",
script: "args.fields.malignantInfluence = true;",
trigger: "dialog",
options: {
activateScript: "return true;"
}
}
]
}
}]
});
}
+1
View File
@@ -0,0 +1 @@
this.actor.addCondition("surprised");
+6
View File
@@ -0,0 +1,6 @@
let modifier = 0
if (this.effect.name.includes("Moderate"))
modifier = -20
else
modifier = -10
args.fields.modifier += modifier
+1
View File
@@ -0,0 +1 @@
this.actor.addEffectItems("Compendium.wfrp4e-core.items.Item.MVI0lXcg6vvtooAF", this.effect);
+9
View File
@@ -0,0 +1,9 @@
let roll = await new Roll("1d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
roll.toMessage(this.script.getChatData());
let skills = await ItemDialog.create(this.actor.itemTypes.skill, "unlimited", {text: "Select penalized Skills", title: this.effect.name})
let names = skills?.map(i => i.name) || [];
this.effect.updateSource({name: this.effect.setSpecifier(names.join(", ")), "flags.wfrp4e.skills" : names, duration: {
value: roll.total,
units: "hours"
}});
+1 -1
View File
@@ -1,4 +1,4 @@
if (args.opposedTest.result.hitloc.value == this.item.system.location.key && args.totalWoundLoss > 0) if (args.loc == this.item.system.location.key && args.totalWoundLoss > 0)
{ {
args.actor.addCondition("bleeding", 1); args.actor.addCondition("bleeding", 1);
} }
+3
View File
@@ -0,0 +1,3 @@
let roll = await new Roll("1d10").roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({"duration" : {value: roll.total, units: "rounds"}})
+1 -1
View File
@@ -1 +1 @@
return args.item?.isProjectiles return args.item?.isRanged
+6
View File
@@ -0,0 +1,6 @@
let roll = await new Roll("1d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {
value: roll.total,
units: "rounds"
}});
+1
View File
@@ -0,0 +1 @@
args.fields.slBonus += 3;
+7
View File
@@ -0,0 +1,7 @@
let test = await this.actor.setupCharacteristic("wp", {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields : {difficulty : "average"}, context : {failure: "1 point de Corruption gagné"}})
await test.roll();
if (test.failed && this.actor.type == "character")
{
this.actor.update({"system.status.corruption.value" : parseInt(this.actor.status.corruption.value) + 1})
this.script.message("Gagné un point de Corruption", {whisper : ChatMessage.getWhisperRecipients("GM")})
}
+3
View File
@@ -0,0 +1,3 @@
let roll = await new Roll("1d5").roll();
roll.toMessage(this.script.getChatData());
this.actor.addCondition("ablaze", roll.total);
+1
View File
@@ -0,0 +1 @@
if (!this.item.system.properties.qualities.precise) this.item.system.qualities.value.push({name : 'precise'})
+2
View File
@@ -0,0 +1,2 @@
this.actor.update({"system.status.corruption.value" : parseInt(this.actor.system.status.corruption.value) + 1});
this.script.notification("Corruption ajoutée");
+6
View File
@@ -0,0 +1,6 @@
let roll = await new Roll("1d10").roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {
value: roll.total,
units: "rounds"
}});
+1 -1
View File
@@ -1 +1 @@
return this.sourceActor.uuid === this.actor.uuid || !args.item?.system?.isProjectiles; return this.sourceActor.uuid === this.actor.uuid || !args.item?.system?.isRanged;
+4
View File
@@ -0,0 +1,4 @@
if (args.test.result.critical)
{
args.test.result.other.push(`<strong>${this.effect.name}</strong>: Can reverse Critical Wound roll`)
}
+1 -1
View File
@@ -1 +1 @@
args.prefillModifiers.modifier -= 10 * this.effect.system.condition.value args.fields.modifier -= 10 * this.effect.system.condition.value
+5
View File
@@ -0,0 +1,5 @@
let property = this.effect.getFlag("wfrp4e", "property");
if (property && !this.item.system.qualities.value.find(i => i.name == property));
{
this.item.system.qualities.value.push({name : property});
}
+7
View File
@@ -0,0 +1,7 @@
let skills = this.actor.itemTypes.skill.filter(i => i.name == "Language (Magick)" || i.name.includes("Channelling"))
for(let skill of skills)
{
await skill.update({"system.modifier.value" : -1 * skill.system.total.value})
}
this.script.notification("Modificateurs ajoutés aux compétences : " + skills.map(i => i.name).join(", "), "info", true);
+7
View File
@@ -0,0 +1,7 @@
let locs = Object.values(this.actor.system.status.armour).map(i => i.label).filter(i => i);
let location = locs[Math.floor(CONFIG.Dice.randomUniform() * (locs.length))];
this.script.notification(location);
this.effect.updateSource({name: this.effect.setSpecifier(location)});
+2 -2
View File
@@ -2,7 +2,7 @@ let lore = this.effect.name.split("(")[1].split(")")[0].toLowerCase();
// If channelling corresponding lore // If channelling corresponding lore
if (args.type == "channelling" && args.spell.system.lore.value == lore) if (args.type == "channelling" && args.spell.system.lore.value == lore)
args.prefillModifiers.slBonus += 1 args.fields.slBonus += 1
// If channelling or casting different lore // If channelling or casting different lore
else if (args.spell.system.lore.value != lore && args.spell.system.lore.value != "petty") else if (args.spell.system.lore.value != lore && args.spell.system.lore.value != "petty")
args.prefillModifiers.slBonus -= 1 args.fields.slBonus -= 1
+1 -1
View File
@@ -1,4 +1,4 @@
if (args.opposedTest.result.hitloc.value == "body" && args.totalWoundLoss > 0) if (args.loc == "body" && args.totalWoundLoss > 0)
{ {
args.actor.addCondition("bleeding", 2) args.actor.addCondition("bleeding", 2)
this.script.message("Gain de 2 états Hémorragique") this.script.message("Gain de 2 états Hémorragique")
+1 -1
View File
@@ -1 +1 @@
return args.weapon?.system.isProjectiles return args.weapon?.system.isRanged
+1 -1
View File
@@ -1,4 +1,4 @@
if (this.item.system.protects[args.opposedTest.result.hitloc.value]) if (this.item.system.protects[args.loc])
{ {
args.weaponProperties.qualities.penetrating = false; args.weaponProperties.qualities.penetrating = false;
} }
+1
View File
@@ -0,0 +1 @@
this.actor.modifyAdvantage(1)
+9
View File
@@ -0,0 +1,9 @@
if (args.totalWoundLoss > 0 && this.item.protects[args.loc])
{
let roll = await new Roll("1d10").roll();
roll.toMessage(this.script.getChatData())
if (roll.total == 10)
{
args.abort = this.effect.name
}
}
+1 -1
View File
@@ -1 +1 @@
args.prefillModifiers.modifier -= 20 args.fields.modifier -= 20
+1
View File
@@ -0,0 +1 @@
args.test.result.other.push(`<strong>${this.effect.name}</strong>: @Fear[1,${this.actor.prototypeToken.name}]`)
+28
View File
@@ -0,0 +1,28 @@
let damage = await new Roll("2d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
damage.toMessage(this.script.getChatData());
this.actor.applyDamage(damage.total, {
damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL,
createMessage: this.script.getChatData()
});
const test = await this.actor.setupSkill(
game.i18n.localize("NAME.Endurance"),
{
fields: {difficulty: "hard"},
skipTargets: true,
appendTitle: `${this.effect.name}`,
},
);
await test.roll();
if (test.failed)
{
if (parseInt(test.result.SL) <= -4)
{
this.actor.addCondition("unconscious");
}
else
{
this.actor.addCondition("stunned");
}
}
+2
View File
@@ -0,0 +1,2 @@
await this.actor.addCondition("prone");
await this.actor.addCondition("blinded", 1 + this.actor.system.status.sin?.value || 0)
+1 -1
View File
@@ -1 +1 @@
return !args.weapon?.system.properties.qualities.hack || args.weapon?.system?.isProjectiles return !args.weapon?.system.properties.qualities.hack || args.weapon?.system?.isRanged
+6
View File
@@ -0,0 +1,6 @@
if (args.type == "cast")
{
args.abort = true;
this.script.notification("Impossible de lancer des sorts !");
}
return true;
+9
View File
@@ -0,0 +1,9 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {fields: {difficulty : "average"}, appendTitle : " - Wounded"})
await test.roll();
if (test.failed)
{
fromUuid("Compendium.wfrp4e-core.items.kKccDTGzWzSXCBOb").then(disease => {
this.actor.createEmbeddedDocuments("Item", [disease.toObject()])
this.script.scriptNotification("Gained " + disease.name)
})
}
+6
View File
@@ -0,0 +1,6 @@
let roll = await new Roll("1d10 + @sin", {sin: this.actor.system.status.sin.value || 0}).roll();
roll.toMessage(this.script.getChatData());
this.effect.updateSource({duration: {
value: roll.total,
units: "days"
}});
+22 -48
View File
@@ -10,10 +10,10 @@ let characteristics = {
"wp" : 10, "wp" : 10,
"fel" : 10 "fel" : 10
} }
let skills = ["Charme", "Focalisation", "Entertain (Prophecy)", "Intuition"] let skills = ["Charme", "Focalisation", "Entertain (Prophétie)", "Intuition"]
let skillAdvancements = [0, 0, 20, 10] let skillAdvancements = [0, 0, 20, 10]
let talents = ["Détection dartefact", "Menaçant", "Sixième Sens"] let talents = ["Détection d'artefact", "Menaçant", "Sixième Sens"]
let traits = ["Condamné", "Spellcaster (Lore of Life)", "Protection"] let traits = ["Condamné", "Lanceur de sorts (Voie de la vie)", "Protection"]
let trappings = [] let trappings = []
let items = []; let items = [];
let spells = ["Forêt d'épines"]; let spells = ["Forêt d'épines"];
@@ -27,14 +27,14 @@ for (let ch in characteristics)
for (let index = 0; index < skills.length; index++) for (let index = 0; index < skills.length; index++)
{ {
let Compétence = skills[index] let skill = skills[index]
let skillItem; let skillItem;
skillItem = updateObj.items.find(i => i.name == Compétence && i.type == "Compétence") skillItem = updateObj.items.find(i => i.name == skill && i.type == "skill")
if (skillItem) if (skillItem)
skillItem.system.advances.value += skillAdvancements[index] skillItem.system.advances.value += skillAdvancements[index]
else else
{ {
skillItem = await game.wfrp4e.utility.findSkill(Compétence) skillItem = await game.wfrp4e.utility.findSkill(skill)
skillItem = skillItem.toObject(); skillItem = skillItem.toObject();
skillItem.system.advances.value = skillAdvancements[index]; skillItem.system.advances.value = skillAdvancements[index];
items.push(skillItem); items.push(skillItem);
@@ -50,7 +50,7 @@ for (let talent of talents)
} }
else else
{ {
ui.notifications.warn(`Could not find ${talent}`, {permanent : true}) ui.notifications.warn(`Introuvable : ${talent}`, {permanent : true})
} }
} }
@@ -59,48 +59,22 @@ for (let trait of traits)
{ {
let traitMatches = trait.matchAll(traitRegex).next().value let traitMatches = trait.matchAll(traitRegex).next().value
let traitName = traitMatches[1] let traitName = traitMatches[1]
let traitVal = traitMatches[2] || traitMatches[4] // could be match 2 or 4 depending on if there'}`).trim() let traitVal = traitMatches[2] || traitMatches[4] // could be match 2 or 4 depending on if there's a specialization
let traitSpec = traitMatches[3]
let traitItem;
try {
traitItem = await WFRP_Utility.findItem(traitName, "trait")
} }
else catch { }
traitItem.system.specification.value = traitSpec if (!traitItem) {
ui.notifications.warn(`Introuvable : ${trait}`, {permanent : true})
}
traitItem = traitItem.toObject()
items.push(traitItem) if (Number.isNumeric(traitVal))
}
for (let trapping of trappings)
{
let trappingItem = await game.wfrp4e.utility.findItem(trapping)
if (trappingItem)
{ {
trappingItem = trappingItem.toObject() traitItem.system.specification.value = traitName.includes('Arme','Cornes','Queue','Tentacules','Morsure') ? traitVal - parseInt(characteristicValues[3]/10) : traitVal;
trappingItem.system.equipped.value = true;
items.push(trappingItem);
}
else
{
ui.notifications.warn(`Could not find ${trapping}`, {permanent : true})
}
}
for (let spell of spells)
{
let spellItem = await game.wfrp4e.utility.findItem(spell)
if (spellItem)
{
spellItem = spellItem.toObject()
items.push(spellItem);
}
else
{
ui.notifications.warn(`Could not find ${spell}`, {permanent : true})
}
}
updateObj.name = updateObj.name +='Arme','Cornes','Tail','Tentacules','Morsure') ? traitVal - parseInt(characteristicValues[3]/10) : traitVal;
traitItem.name = (traitItem.name + ` ${traitSpec ? "("+ traitSpec + ")" : ""}`).trim() traitItem.name = (traitItem.name + ` ${traitSpec ? "("+ traitSpec + ")" : ""}`).trim()
} }
else else
@@ -123,7 +97,7 @@ for (let trapping of trappings)
} }
else else
{ {
ui.notifications.warn(`Could not find ${trapping}`, {permanent : true}) ui.notifications.warn(`Introuvable : ${trapping}`, {permanent : true})
} }
} }
@@ -138,7 +112,7 @@ for (let spell of spells)
} }
else else
{ {
ui.notifications.warn(`Could not find ${spell}`, {permanent : true}) ui.notifications.warn(`Introuvable : ${spell}`, {permanent : true})
} }
} }
+3
View File
@@ -0,0 +1,3 @@
if (!this.item.system.properties.qualities.pummel) this.item.system.qualities.value.push({name : 'pummel'});
if (!this.item.system.properties.qualities.impale) this.item.system.qualities.value.push({name : 'impale'})
if (!this.item.system.properties.qualities.penetrating) this.item.system.qualities.value.push({name : 'penetrating'})
+1
View File
@@ -0,0 +1 @@
if (this.item.attackType == "ranged") args.initiative += "+10"
+12
View File
@@ -0,0 +1,12 @@
if (args.equipped)
{
this.script.notification("Frénésie !")
let frenzy = (await fromUuid("Compendium.wfrp4e-core.items.Item.yRhhOlt18COq4e1q.ActiveEffect.ydTMvbmqv6BZ4u6d")).toObject();
frenzy.statuses = ["frenzy"];
frenzy.disabled = false;
ActiveEffect.implementation.create(frenzy, {parent: this.actor});
}
else
{
this.actor.effects.find(e => e.statuses.has("frenzy"))?.delete();
}
+1
View File
@@ -0,0 +1 @@
this.actor.addCondition("broken", 1 + this.actor.system.status.sin?.value || 0)
+1 -1
View File
@@ -1,4 +1,4 @@
if (args.opposedTest.result.hitloc.value == this.item.system.location.key) if (args.loc == this.item.system.location.key)
{ {
args.actor.addCondition("bleeding", 1); args.actor.addCondition("bleeding", 1);
this.script.notification("Etat Hémorragique ajouté") this.script.notification("Etat Hémorragique ajouté")

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