Gestion de l'astrologie

This commit is contained in:
2022-12-23 23:24:09 +01:00
parent 7a8cf9f8fd
commit bcb377db7a
24 changed files with 521 additions and 91 deletions

View File

@ -136,6 +136,7 @@ export class BoLActorSheet extends ActorSheet {
formData.treasure = this.actor.treasure
formData.boleffects = this.actor.boleffects
formData.alchemyrecipe = this.actor.alchemyrecipe
formData.horoscopes = this.actor.horoscopes
formData.vehicles = this.actor.vehicles
formData.fightoptions = this.actor.fightoptions
formData.ammos = this.actor.ammos
@ -156,6 +157,8 @@ export class BoLActorSheet extends ActorSheet {
formData.notes = await TextEditor.enrichHTML(this.object.system.details.notes, {async: true})
formData.isSorcerer = this.actor.isSorcerer()
formData.isAlchemist = this.actor.isAlchemist()
formData.isAstrologer = this.actor.isAstrologer()
formData.isMysteries = formData.isSorcerer || formData.isAlchemist || formData.isAstrologer
formData.isPriest = this.actor.isPriest()
formData.isGM = game.user.isGM
@ -244,7 +247,16 @@ export class BoLActorSheet extends ActorSheet {
case "careerxp":
this.actor.incCareerXP( li.data("item-id"))
break;
case "horoscope-minor":
BoLRoll.horoscopeCheck(this.actor, event, "minor")
break
case "horoscope-major":
BoLRoll.horoscopeCheck(this.actor, event, "major")
break
case "horoscope-major-group":
BoLRoll.horoscopeCheck(this.actor, event, "majorgroup")
break
default: break;
}
}

View File

@ -25,7 +25,7 @@ export class BoLActor extends Actor {
/* -------------------------------------------- */
getCharType() {
if (this.type === 'character') {
return 'player'
return "player"
}
return this.system.chartype
}
@ -249,6 +249,9 @@ export class BoLActor extends Actor {
get boleffects() {
return this.items.filter(i => i.type === "feature" && i.system.subtype === "boleffect")
}
get horoscopes() {
return this.items.filter(i => i.type === "feature" && i.system.subtype === "horoscope")
}
get boons() {
return duplicate(this.items.filter(i => i.type === "feature" && i.system.subtype === "boon") || []);
}
@ -354,6 +357,11 @@ export class BoLActor extends Actor {
return true
return false
}
isAstrologer() {
if (this.careers.find(item => item.system.properties.astrologer == true))
return true
return false
}
isPriest() {
if (this.careers.find(item => item.system.properties.priest == true))
return true
@ -424,6 +432,74 @@ export class BoLActor extends Actor {
this.updateEmbeddedDocuments('Item', [{ _id: alchemy.id, 'system.properties.pccurrent': 0 }])
}
}
/*-------------------------------------------- */
spentAstrologyPoints(points) {
let astrology = duplicate(this.system.resources.astrologypoints)
astrology.value -= points
astrology.value = Math.max(astrology.value,0)
this.update( { 'system.resources.astrologypoints': astrology} )
}
/*-------------------------------------------- */
getHoroscopesBonus() {
let astro = this.items.filter(it => it.type == "feature" && it.system.subtype == "horoscope" && !it.system.properties.ishoroscopemajor
&& it.system.properties.horoscopeanswer == "favorable")
return astro
}
/*-------------------------------------------- */
getHoroscopesMalus() {
let astro = this.items.filter(it => it.type == "feature" && it.system.subtype == "horoscope" && !it.system.properties.ishoroscopemajor
&& it.system.properties.horoscopeanswer == "unfavorable")
return astro
}
/*-------------------------------------------- */
manageHoroscope(rollData) {
//Spent points
this.spentAstrologyPoints(rollData.astrologyPointsCost)
if ( rollData.horoscopeType == "minor") {
let horoscope = { name: "SITUATION A SPECIFIER", type :"feature",
img: "icons/magic/perception/eye-ringed-glow-angry-large-red.webp",
system :{subtype: "horoscope", properties: {
ishoroscopemajor: false,
horoscopeanswer: (rollData.isSuccess) ? "favorable": "unfavorable",
rank: rollData.careerBonus
}
}
}
this.createEmbeddedDocuments('Item', [horoscope])
}
if ( rollData.horoscopeType == "major" ) {
if ( rollData.isSuccess) {
this.subHeroPoints(1)
} else {
this.addHeroPoints(1)
}
}
if ( rollData.horoscopeType == "majorgroup" ) {
let rID = randomID(16)
let horoscopes = duplicate(game.settings.get("bol", "horoscope-group"))
horoscopes[rID] = {
name: game.i18n.localize("BOL.ui.groupHoroscope") + this.name,
maxDice: rollData.careerBonus,
availableDice: rollData.careerBonus,
type: (rollData.isSuccess) ? "bonus": "malus"
}
}
}
/*-------------------------------------------- */
removeHoroscopeMinor( rollData) {
let toDel = []
for(let horo of rollData.selectedHoroscope) {
toDel.push( horo._id )
}
if (toDel.length > 0) {
this.deleteEmbeddedDocuments('Item', toDel)
}
}
/*-------------------------------------------- */
async spendAlchemyPoint(alchemyId, pcCost) {
@ -441,7 +517,14 @@ export class BoLActor extends Actor {
}
}
}
/*-------------------------------------------- */
getAstrologerBonus() {
let astrologer = this.careers.find(item => item.system.properties.astrologer == true)
if (astrologer) {
return astrologer.system.rank
}
return 0;
}
/*-------------------------------------------- */
getAlchemistBonus() {
let sorcerer = this.careers.find(item => item.system.properties.alchemist == true)
@ -536,6 +619,11 @@ export class BoLActor extends Actor {
"label": "BOL.featureSubtypes.effects",
"ranked": false,
"items": this.boleffects
},
"horoscopes": {
"label": "BOL.featureSubtypes.horoscope",
"ranked": false,
"items": this.horoscopes
}
}
}
@ -707,6 +795,12 @@ export class BoLActor extends Actor {
newHeroP = (newHeroP < 0) ? 0 : newHeroP;
await this.update({ 'system.resources.hero.value': newHeroP });
}
/*-------------------------------------------- */
async addHeroPoints(nb) {
let newHeroP = this.system.resources.hero.value + nb;
newHeroP = (newHeroP < 0) ? 0 : newHeroP;
await this.update({ 'system.resources.hero.value': newHeroP });
}
/*-------------------------------------------- */
async sufferDamage(damage) {

View File

@ -18,20 +18,20 @@ export class BoLRoll {
/* -------------------------------------------- */
static updateApplicableEffects(rollData) {
let appEffects = []
for( let effect of rollData.bolEffects) {
if(effect.system.properties.identifier =="always") {
appEffects.push(effect)
for (let effect of rollData.bolEffects) {
if (effect.system.properties.identifier == "always") {
appEffects.push(effect)
} else if (effect.system.properties.identifier.includes(rollData.attribute.key)) {
appEffects.push(effect)
} else if ( rollData.aptitude && effect.system.properties.identifier.includes(rollData.aptitude.key)) {
appEffects.push(effect)
appEffects.push(effect)
} else if (rollData.aptitude && effect.system.properties.identifier.includes(rollData.aptitude.key)) {
appEffects.push(effect)
}
}
return appEffects
}
/* -------------------------------------------- */
static getCommonRollData(actor, mode, attribute, aptitude = undefined ) {
static getCommonRollData(actor, mode, attribute, aptitude = undefined) {
let rollData = {
mode: mode,
@ -42,8 +42,13 @@ export class BoLRoll {
attrValue: attribute.value,
aptValue: 0,
careerBonus: 0,
horoscopeBonus: 0,
horoscopeMalus: 0,
selectedHoroscope: [],
armorAgiMalus: actor.getArmorAgiMalus(),
armorInitMalus: actor.getArmorInitMalus(),
horoscopeBonusList: actor.getHoroscopesBonus(),
horoscopeMalusList: actor.getHoroscopesMalus(),
adv: "0",
mod: 0,
modRanged: 0,
@ -62,7 +67,7 @@ export class BoLRoll {
static attributeCheck(actor, key) {
let attribute = eval(`actor.system.attributes.${key}`)
let rollData = this.getCommonRollData(actor, "attribute", attribute)
rollData.description = game.i18n.localize('BOL.ui.attributeCheck') + " - " + game.i18n.localize(attribute.label)
rollData.label = (attribute.label) ? game.i18n.localize(attribute.label) : null
@ -83,11 +88,11 @@ export class BoLRoll {
rollData.label = (aptitude.label) ? game.i18n.localize(aptitude.label) : null
rollData.description = game.i18n.localize('BOL.ui.aptitudeCheck') + " - " + game.i18n.localize(aptitude.label)
return this.displayRollDialog( rollData)
return this.displayRollDialog(rollData)
}
/* -------------------------------------------- */
static async detectDistance( weapon, target ) {
static async detectDistance(weapon, target) {
let visible, dist
if (weapon.system.properties.ranged || weapon.system.properties.throwing) {
console.log("target", target, weapon)
@ -95,19 +100,19 @@ export class BoLRoll {
dist = Number(canvas.grid.measureDistances([{ ray: new Ray(_token.center, target.center) }], { gridSpaces: false })).toFixed(2)
let range = Number(weapon.system.properties.range)
let rangeMsg = "BOL.chat.rangeout"
if ( dist <= range) {
if (dist <= range) {
rangeMsg = "BOL.chat.range0"
} else if (dist < range*2) {
} else if (dist < range * 2) {
rangeMsg = "BOL.chat.range1"
} else if (dist < range*3) {
} else if (dist < range * 3) {
rangeMsg = "BOL.chat.range2"
} else if (dist < range*4) {
} else if (dist < range * 4) {
rangeMsg = "BOL.chat.range3"
} else if (dist < range*5) {
} else if (dist < range * 5) {
rangeMsg = "BOL.chat.range4"
} else if (dist < range*6) {
} else if (dist < range * 6) {
rangeMsg = "BOL.chat.range5"
} else if (dist < range*7) {
} else if (dist < range * 7) {
rangeMsg = "BOL.chat.range6"
}
ChatMessage.create({
@ -121,7 +126,7 @@ export class BoLRoll {
rangeMsg: rangeMsg
})
})
}
}
}
/* -------------------------------------------- */
@ -136,7 +141,7 @@ export class BoLRoll {
let rollData = this.getCommonRollData(actor, "weapon", attribute, aptitude)
// Compute distance
this.detectDistance( weapon, target)
this.detectDistance(weapon, target)
// Manage specific case
let fightOption = actor.getActiveFightOption()
@ -144,14 +149,14 @@ export class BoLRoll {
ui.notifications.warn(`{{actor.name}} est en Défense Totale ! Il ne peut pas attaquer ce round.`)
return
}
// Update the roll structure
rollData.weapon = weapon
rollData.weapon = weapon
rollData.isRanged = weaponData.properties.ranged || weaponData.properties.throwing
rollData.targetId = target?.id
rollData.fightOption = fightOption
rollData.defenderId = target?.actor.id
rollData.label = (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName')
rollData.defenderId = target?.actor.id
rollData.label = (weapon.name) ? weapon.name : game.i18n.localize('BOL.ui.noWeaponName')
rollData.description = game.i18n.localize('BOL.ui.weaponAttack') + " : " + weapon.name
return this.displayRollDialog(rollData)
@ -194,23 +199,38 @@ export class BoLRoll {
rollData.label = alchemy.name
rollData.description = game.i18n.localize('BOL.ui.makeAlchemy') + "+" + alchemy.name
console.log("ALCHEMY!", alchemyDef);
return this.displayRollDialog(alchemyDef);
console.log("ALCHEMY!", rollData);
return this.displayRollDialog(rollData);
}
/* -------------------------------------------- */
static spellCheckWithSpell( actor, spell ) {
static horoscopeCheck(actor, event, horoscopeType) {
let rollData = this.getCommonRollData(actor, "horoscope", actor.system.attributes.mind)
rollData.careerBonus = actor.getAstrologerBonus()
rollData.horoscopeType = horoscopeType
rollData.horoscopeTypeLabel = "BOL.ui."+horoscopeType
rollData.astrologyPointsCost = (horoscopeType == "minor") ? 1 : 2
rollData.label = game.i18n.localize('BOL.ui.makeHoroscope')
rollData.description = game.i18n.localize('BOL.ui.makeHoroscope') + " " + game.i18n.localize(rollData.horoscopeTypeLabel)
console.log("HOROSCOPE!", rollData);
return this.displayRollDialog(rollData);
}
/* -------------------------------------------- */
static spellCheckWithSpell(actor, spell) {
let rollData = this.getCommonRollData(actor, "spell", actor.system.attributes.mind)
rollData.spell = spell
rollData.ppCurrent = Number(actor.system.resources.power.value),
rollData.careerBonus = actor.getSorcererBonus(),
rollData.ppCostArmor = actor.getPPCostArmor(),
rollData.ppCost = Number(spell.system.properties.ppcost),
rollData.mod = Number(spell.system.properties.difficulty),
rollData.label = spell.name,
rollData.description = game.i18n.localize('BOL.ui.focusSpell') + " : " + spell.name
rollData.careerBonus = actor.getSorcererBonus(),
rollData.ppCostArmor = actor.getPPCostArmor(),
rollData.ppCost = Number(spell.system.properties.ppcost),
rollData.mod = Number(spell.system.properties.difficulty),
rollData.label = spell.name,
rollData.description = game.i18n.localize('BOL.ui.focusSpell') + " : " + spell.name
//console.log("SPELL!", spellDef)
return this.displayRollDialog(rollData)
}
@ -228,7 +248,7 @@ export class BoLRoll {
return
}
spell = duplicate(spell)
return this.spellCheckWithSpell( actor, spell)
return this.spellCheckWithSpell(actor, spell)
}
/* -------------------------------------------- */
@ -245,15 +265,18 @@ export class BoLRoll {
if (effect.system.properties.modifier == "1B") {
this.rollData.bmDice++;
} else if (effect.system.properties.modifier == "1B") {
this.rollData.bmDice+=2;
this.rollData.bmDice += 2;
} else if (effect.system.properties.modifier == "1M") {
this.rollData.bmDice--;
} else if (effect.system.properties.modifier == "2M") {
this.rollData.bmDice-=2;
} else if (effect.system.properties.modifier == "2M") {
this.rollData.bmDice -= 2;
} else {
effectModifier += Number(effect.system.properties.modifier)
}
}
this.rollData.bmDice += this.rollData.horoscopeBonus
this.rollData.bmDice -= this.rollData.horoscopeMalus
// Keep track of the final effect modifier
this.rollData.effectModifier = effectModifier
@ -267,7 +290,7 @@ export class BoLRoll {
$('#roll-nbdice').val("2 + " + String(Math.abs(this.rollData.bmDice)) + letter)
}
let rollbase = this.rollData.attrValue + "+" + this.rollData.aptValue
if ( this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier ) {
if (this.rollData.weapon && this.rollData.weapon.system.properties.onlymodifier) {
rollbase = ""
}
$('#roll-modifier').val(rollbase + "+" + this.rollData.careerBonus + "+" + this.rollData.mod + "+" +
@ -276,7 +299,7 @@ export class BoLRoll {
// Rebuild lits of applicable effects
let selectEffects = ""
for(let effect of this.rollData.bolApplicableEffects) {
for (let effect of this.rollData.bolApplicableEffects) {
selectEffects += `<option value="${effect.id}" selected>${effect.name}</option>`
}
$('#applicable-effects').html(selectEffects)
@ -339,7 +362,7 @@ export class BoLRoll {
html.find('#optcond').change((event) => { // Dynamic change of PP cost of spell
let pp = BoLUtility.computeSpellCost(this.rollData.spell, event.currentTarget.selectedOptions.length)
this.rollData.ppCost = pp
this.updatePPCost( this.rollData)
this.updatePPCost(this.rollData)
})
html.find('#mod').change((event) => {
@ -401,6 +424,23 @@ export class BoLRoll {
this.rollData.mDice = Number(event.currentTarget.value)
this.updateTotalDice()
})
html.find('#horoscope-bonus-applied').change((event) => {
if (event.currentTarget.value != undefined) {
this.rollData.selectedHoroscope.push( duplicate(this.rollData.horoscopeBonusList[Number(event.currentTarget.value)]) )
}
let horoscopes = $('#horoscope-bonus-applied').val()
this.rollData.horoscopeBonus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
html.find('#horoscope-malus-applied').change((event) => {
if (event.currentTarget.value != undefined) {
this.rollData.selectedHoroscope.push( duplicate(this.rollData.horoscopeMalusList[Number(event.currentTarget.value)]) )
}
let horoscopes = $('#horoscope-malus-applied').val()
this.rollData.horoscopeMalus = (!horoscopes || horoscopes.length == 0) ? 0 : horoscopes.length
this.updateTotalDice()
})
}
/* -------------------------------------------- */
@ -408,7 +448,7 @@ export class BoLRoll {
if (rollData.mode == "weapon") {
rollData.weaponModifier = rollData.weapon.system.properties.attackModifiers ?? 0
rollData.attackBonusDice = rollData.weapon.system.properties.attackBonusDice
if ( rollData.attackBonusDice) {
if (rollData.attackBonusDice) {
rollData.adv = "1B"
rollData.bDice = 1
}
@ -435,7 +475,7 @@ export class BoLRoll {
let actor = BoLUtility.getActorFromRollData(rollData)
let defender
if ( rollData.targetId) {
if (rollData.targetId) {
let token = game.scenes.current.tokens.get(rollData.targetId)
defender = token.actor
}
@ -498,14 +538,14 @@ export class BoLRoll {
//console.log("ROLLMALUS", rollData)
rollData.registerInit = (rollData.aptitude && rollData.aptitude.key == 'init') ? $('#register-init').is(":checked") : false;
const isMalus = (rollData.bmDice < 0)
const isMalus = (rollData.bmDice < 0)
//rollData.nbDice += (rollData.attackBonusDice) ? 1 : 0
let rollbase = rollData.attrValue + rollData.aptValue
if ( rollData.weapon && rollData.weapon.system.properties.onlymodifier ) {
if (rollData.weapon && rollData.weapon.system.properties.onlymodifier) {
rollbase = 0
}
}
const modifiers = rollbase + rollData.careerBonus + rollData.mod + rollData.weaponModifier - rollData.defence - rollData.modArmorMalus + rollData.shieldMalus + rollData.attackModifier + rollData.appliedArmorMalus + rollData.effectModifier
const formula = (isMalus) ? rollData.nbDice + "d6kl2 + " + modifiers : rollData.nbDice + "d6kh2 + " + modifiers
rollData.formula = formula
@ -535,10 +575,10 @@ export class BoLDefaultRoll {
this.rollData.isFumble = false;
}
if (this.rollData.optionsId) {
BoLUtility.cleanupButtons( this.rollData.optionsId)
BoLUtility.cleanupButtons(this.rollData.optionsId)
}
if (this.rollData.applyId) {
BoLUtility.cleanupButtons( this.rollData.applyId)
BoLUtility.cleanupButtons(this.rollData.applyId)
}
this.rollData.optionsId = randomID(16)
this.rollData.applyId = randomID(16)
@ -560,15 +600,15 @@ export class BoLDefaultRoll {
this.rollData.isLegendary = false
this.rollData.isFumble = (diceTotal === 2)
this.rollData.isFailure = !this.rollData.isSuccess
//this.rollData.isRealCritical = true
//this.rollData.isFumble = true
let actor = BoLUtility.getActorFromRollData(this.rollData)
if (this.rollData.reroll == undefined) {
this.rollData.reroll = actor.heroReroll()
}
if (this.rollData.registerInit) {
actor.registerInit(this.rollData)
this.rollData.initiativeRank = actor.getInitiativeRank(this.rollData)
@ -579,9 +619,15 @@ export class BoLDefaultRoll {
if (this.rollData.mode == "alchemy") { // PP cost management
actor.resetAlchemyStatus(this.rollData.alchemy._id)
}
if ( this.rollData.mode == "bougette" && this.rollData.isFailure) {
if (this.rollData.mode == "bougette" && this.rollData.isFailure) {
actor.decBougette()
}
if (this.rollData.mode == "horoscope") { // PP cost management
actor.manageHoroscope(this.rollData)
}
if (this.rollData.selectedHoroscope.length > 0) { // PP cost management
actor.removeHoroscopeMinor(this.rollData)
}
await this.sendChatMessage()
}
@ -589,7 +635,7 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */
async sendChatMessage() {
let actor = BoLUtility.getActorFromRollData(this.rollData)
this._buildChatMessage(this.rollData).then( async msgFlavor => {
this._buildChatMessage(this.rollData).then(async msgFlavor => {
let msg = await this.rollData.roll.toMessage({
user: game.user.id,
rollMode: game.settings.get("core", "rollMode"),
@ -627,7 +673,7 @@ export class BoLDefaultRoll {
this.rollData.reroll = false
this.sendChatMessage()
}
/* -------------------------------------------- */
setSuccess(flag) {
this.rollData.isSuccess = flag
@ -651,7 +697,7 @@ export class BoLDefaultRoll {
/* -------------------------------------------- */
getDamageAttributeValue(attrDamage, actorId = undefined) {
let actor = BoLUtility.getActorFromRollData(this.rollData)
return actor.getDamageAttributeValue( attrDamage )
return actor.getDamageAttributeValue(attrDamage)
}
/* -------------------------------------------- */

View File

@ -53,6 +53,13 @@ export class BoLUtility {
type: String,
onChange: lang => window.location.reload()
})
game.settings.register("bol", "horoscope-group", {
name: "horoscope-group",
scope: "world",
config: false,
default: {},
type: Object
})
this.rollArmor = game.settings.get("bol", "rollArmor") // Roll armor or not
this.useBougette = game.settings.get("bol", "useBougette") // Use optionnal bougette rules

View File

@ -270,6 +270,7 @@ BOL.featureSubtypes = {
"godsfaith" : "BOL.featureSubtypes.gods",
"fightoption" : "BOL.featureSubtypes.fightOption",
"boleffect": "BOL.featureSubtypes.effect",
"horoscope": "BOL.featureSubtypes.horoscope",
}
BOL.fightOptionTypes = {
@ -326,6 +327,11 @@ BOL.creatureSize = {
"colossal": "BOL.size.colossal"
}
BOL.horoscopeAnswer = {
"favorable": "BOL.ui.horoscopefavorable",
"unfavorable": "BOL.ui.horoscopeunfavorable",
}
BOL.bolEffectModifier = {
"-8": "-8",
"-6": "-6",

View File

@ -41,11 +41,14 @@ export const preloadHandlebarsTemplates = async function () {
"systems/bol/templates/item/parts/properties/feature/race-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/fightoption-properties.hbs",
"systems/bol/templates/item/parts/properties/item/weapon-vehicle-properties.hbs",
"systems/bol/templates/item/parts/properties/feature/horoscope-properties.hbs",
// DIALOGS
"systems/bol/templates/chat/rolls/attack-damage-card.hbs",
"systems/bol/templates/chat/rolls/spell-roll-card.hbs",
"systems/bol/templates/chat/rolls/alchemy-roll-card.hbs",
"systems/bol/templates/chat/rolls/selected-horoscope-roll-card.hbs",
"systems/bol/templates/chat/rolls/horoscope-roll-card.hbs",
"systems/bol/templates/dialogs/aptitude-roll-part.hbs",
"systems/bol/templates/dialogs/attribute-roll-part.hbs",
"systems/bol/templates/dialogs/mod-roll-part.hbs",
@ -56,6 +59,7 @@ export const preloadHandlebarsTemplates = async function () {
"systems/bol/templates/dialogs/flaws-roll-part.hbs",
"systems/bol/templates/dialogs/total-roll-part.hbs",
"systems/bol/templates/dialogs/fightoptions-roll-part.hbs",
"systems/bol/templates/dialogs/horoscope-roll-part.hbs"
];
// Load the template parts