import { PegasusUtility } from "./pegasus-utility.js"; import { PegasusActor } from "./pegasus-actor.js"; import { PegasusActorSheet } from "./pegasus-actor-sheet.js"; import { PegasusItemSheet } from "./pegasus-item-sheet.js"; export class PegasusActorCreate { /* -------------------------------------------- */ async start() { this.actor = await Actor.create({ name: "New Actor", type: "character" }); this.actor.sheet.render(true) this.actor.computeValue = true // To force value computation const racesPack = await PegasusUtility.loadCompendium("fvtt-pegasus-rpg.race") this.races = racesPack.map(i => i.toObject()) const rolesPack = await PegasusUtility.loadCompendium("fvtt-pegasus-rpg.role") this.roles = rolesPack.map(i => i.toObject()) const perksPack = await PegasusUtility.loadCompendium("fvtt-pegasus-rpg.perks") this.perks = perksPack.map(i => i.toObject()) const specPack = await PegasusUtility.loadCompendium("fvtt-pegasus-rpg.specialisations") this.specs = specPack.map(i => i.toObject()) const virtuePack = await PegasusUtility.loadCompendium("fvtt-pegasus-rpg.virtues") this.virtues = virtuePack.map(i => i.toObject()) const vicePack = await PegasusUtility.loadCompendium("fvtt-pegasus-rpg.vices") this.vices = vicePack.map(i => i.toObject()) this.showRaces() } /* -------------------------------------------- */ createFormData(step) { let formData = { name: this.actor.name, img: this.actor.img, step: step, races: this.races, roles: this.roles, nboptionnal: this.raceOptionnalAbilities?.nboptionnal ?? 0, optionnalabilities: this.raceOptionnalAbilities?.optionnalabilities ?? [], } if (this.raceSelectableStats) { formData.numberstats = this.raceSelectableStats.numberstats; formData.statsonlyonce = this.raceSelectableStats.statsonlyonce; formData.stats = this.raceSelectableStats.stats; } return formData; } /* -------------------------------------------- */ getSpecFromRoleStat(role) { let specList = [] for (let stat of role.system.statincreasechoice) { if (stat.flag) { specList = specList.concat(this.specs.filter(spec => spec.system.statistic.toLowerCase() == stat.name.toLowerCase())) } } return specList } /* -------------------------------------------- */ getPerksFromRole(role) { let perks = this.perks.filter(perk => perk.system.category.toLowerCase() == role.system.perksrole.toLowerCase()) return perks } /* -------------------------------------------- */ async processChatEvent(event) { const step = $(event.currentTarget).data("step-name"); const itemId = $(event.currentTarget).data("item-id"); if (step == "select-race") { let race = this.races.find(item => item._id == itemId); this.currentRace = race; this.actor.applyRace(race); PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); if (race.system.nboptionnal > 0 && race.system.optionnalabilities.length > 0) { this.manageOptionnalAbilities(race); } else { if (race.system.selectablestats) { this.manageSelectableStats(race); } else if (race.system.perksgained) { this.manageRacePerks(race); } else { this.showRoles() } } } if (step == 'select-race-optionnal') { let ability = this.raceOptionnalAbilities.optionnalabilities.find(item => item._id == itemId); let update = [] this.actor.applyAbility(ability, update); this.actor.update(update) this.actor.createEmbeddedDocuments('Item', [ability]); PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); this.raceOptionnalAbilities.optionnalabilities = this.raceOptionnalAbilities.optionnalabilities.filter(item => item._id != itemId); this.raceOptionnalAbilities.nboptionnal -= 1; this.processOptionnalAbilitiesStep(); } if (step == 'select-race-stats') { let statKey = $(event.currentTarget).data("stat-key"); this.actor.modStat(statKey, 1); this.raceSelectableStats.stats[statKey].used = true; this.raceSelectableStats.numberstats -= 1; PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); this.processSelectableStats(); } if (step == 'select-race-perks') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let perk = this.racePerks.find(item => item._id == itemId); this.actor.createEmbeddedDocuments('Item', [perk]); this.racePerks = this.racePerks.filter(item => item._id != itemId); this.nbRacePerks -= 1; if (this.nbRacePerks == 0 || this.racePerks.length == 0) { this.showRoles() } else { this.manageRacePerks() } } if (step == 'select-role') { let role = this.roles.find(item => item._id == itemId); PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); this.actor.applyRole(role); this.currentRole = role; this.nbRoleStat = 2; this.roleStats = duplicate(role.system.statincreasechoice) this.showRoleStartSpec(); } if (step == 'select-role-start-spec') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let spec = this.roleSpecStart.find(item => item._id == itemId); this.actor.addIncSpec(spec, 1); this.nbRoleSpecStart--; this.roleSpecStart = this.roleSpecStart.filter(item => item._id != itemId);//Remove selected spec if (this.nbRoleSpecStart == 0) { this.showRoleStat(); } else { this.showRoleStartSpec(); } } if (step == 'select-role-stat') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let statKey = $(event.currentTarget).data("stat-key"); this.actor.valueStat(statKey, 1); for (let stat of this.roleStats) { if (stat.name.toLowerCase() == statKey.toLowerCase()) { stat.flag = false } } this.nbRoleStat--; if (this.nbRoleStat == 0 || this.roleStats.length == 0) { this.roleSpec = this.getSpecFromRoleStat(this.currentRole) this.nbDT2 = 1; this.nbDT1 = 2; this.showRoleSpecialisations() } else { this.showRoleStat(); } } if (step == 'select-role-spec') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let spec = this.roleSpec.find(item => item._id == itemId); if (this.nbDT2 > 0) { this.actor.addIncSpec(spec, 2) this.nbDT2--; } else { this.actor.addIncSpec(spec, 1) this.nbDT1--; } this.roleSpec = this.roleSpec.filter(item => item._id != itemId);//Remove selected spec if (this.nbDT1 == 0 || this.roleSpec.length == 0) { this.rolePerks = this.getPerksFromRole(this.currentRole) // duplicate(this.currentRole.data.perks) this.nbPerks = 2; this.showRolePerks() } else { this.showRoleSpecialisations() } } if (step == 'select-role-perk') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let perk = this.rolePerks.find(item => item._id == itemId); this.actor.addIncPerk(perk, 1) let excludedPerks = this.actor.items.filter(it => it.type == "perk" && !it.system.upgradable) this.rolePerks = [] for (let perk of this.rolePerks) { if (!excludedPerks.find(it => it.name == perk.name)) { this.rolePerks.push(perk) } } this.rolePerks.sort(function (a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) this.nbPerks--; if (this.nbPerks == 0 || this.rolePerks.length == 0) { this.nbGlobalSpec = 5 if (this.forceVirtue) { this.showVirtue() } else { this.showGlobalSpec() } } else { this.showRolePerks() } } if (step == 'select-global-spec') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let spec = this.specs.find(item => item._id == itemId); this.actor.addIncSpec(spec, 1) this.nbGlobalSpec--; if (this.nbGlobalSpec == 0) { this.nbGlobalStat = 5 if (this.forceVirtue) { this.showVirtue() } else { this.showGlobalStat() } } else { this.showGlobalSpec() } } if (step == 'select-global-stat') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)) let statKey = $(event.currentTarget).data("stat-key") this.actor.valueStat(statKey, 1) this.nbGlobalStat-- if (this.nbGlobalStat == 0) { this.nbGlobalPerk = 1 if (this.forceVirtue) { this.showVirtue() } else { this.showGlobalPerk() } } else { this.showGlobalStat() } } if (step == 'select-global-perk') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)) let perk = this.perks.find(item => item._id == itemId); this.actor.addIncPerk(perk, 1) this.nbGlobalPerk--; if (this.nbGlobalPerk == 0) { this.nbGlobalStatus = 1 if (this.forceVirtue) { this.showVirtue() } else { this.showGlobalStatus() } } else { this.showGlobalPerk() } } if (step == 'select-global-status') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)) let statusKey = $(event.currentTarget).data("status-key") this.actor.addStatusBonus(statusKey, 1) this.nbGlobalStatus--; if (this.nbGlobalStatus == 0) { this.nbBonusSelection = 1 if (this.forceVirtue) { this.showVirtue() } else { this.showBonusSelection() } } else { this.showGlobalStatus() } } if (step == 'select-bonus-selection') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)) let nextStep = $(event.currentTarget).data("bonus-key") this.forceVirtue = true if (nextStep == "bonus-statistic") { this.nbGlobalStat = 2 this.showGlobalStat() } if (nextStep == "bonus-specialisation") { this.nbGlobalSpec = 4 this.showGlobalSpec() } if (nextStep == "bonus-perk") { this.nbGlobalPerk = 2 this.showGlobalPerk() } if (nextStep == "bonus-status") { this.nbGlobalStatus = 5 this.showGlobalStatus() } if (nextStep == "bonus-roleability") { this.actor.increaseRoleAbility() } if (nextStep == "bonus-ppp5") { this.actor.addPPP(5) } if (nextStep == "bonus-wealthy") { ChatMessage.create({ content: "NOT AUTOMATED! Your character starts with x2 Starting Funds" }) this.showVirtue() } if (nextStep == "bonus-heirloom") { ChatMessage.create({ content: "NOT AUTOMATED! Your character starts with an item of choice (GM Must approve). This item provides a Level 1 Bonus Dice to a Stat of choice" }) this.showVirtue() } if (nextStep == "bonus-vehicle") { ChatMessage.create({ content: "NOT AUTOMATED! Your character starts with a Vehicle of Choice (GM Must approve)." }) this.showVirtue() } if (nextStep == "bonus-mount") { ChatMessage.create({ content: "NOT AUTOMATED! Your character starts with a Mount of Choice (GM Must approve)." }) this.showVirtue() } if (nextStep == "bonus-sidekick") { ChatMessage.create({ content: "NOT AUTOMATED! Your character starts with a Sidekick of Choice (GM Must approve)." }) this.showVirtue() } if (nextStep == "bonus-ambidextrious") { this.actor.setHandInformation("Ambidextrious") this.showVirtue() } } if (step == 'select-global-virtue') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let virtue = this.virtues.find(item => item._id == itemId); await this.actor.createEmbeddedDocuments('Item', [virtue]) this.showVice() } if (step == 'select-global-vice') { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)); let vice = this.vices.find(item => item._id == itemId); await this.actor.createEmbeddedDocuments('Item', [vice]); if(this.forceEnd) { this.showCharacterEnd() } else { this.showViceQuestion() } } if (step == "select-vice-question") { PegasusUtility.removeChatMessageId(PegasusUtility.findChatMessageId(event.currentTarget)) let nextStep = $(event.currentTarget).data("question-key") this.forceEnd = true if (nextStep == "vice-next-step") { this.showCharacterEnd() } if (nextStep == "vice-5-cdp") { this.actor.addCDP(5) this.showVice() } if (nextStep == "vice-vertue") { this.showVirtue() } } } /* -------------------------------------------- */ async openItemView(event) { let step = $(event.currentTarget).data("step"); let itemId = $(event.currentTarget).data("item-id"); let itemData if (step == 'select-race') { itemData = this.races.find(item => item._id == itemId); } if (step == 'select-race-optionnal') { itemData = this.raceOptionnalAbilities.optionnalabilities.find(item => item._id == itemId); } if (step == 'select-race-perks') { itemData = this.perks.find(item => item._id == itemId); } if (step == 'select-race-perks') { itemData = this.racePerks.find(item => item._id == itemId); } if (step == 'select-role') { itemData = this.roles.find(item => item._id == itemId); } if (step == 'select-role-start-spec') { itemData = this.roleSpecStart.find(item => item._id == itemId); } if (step == 'select-role-spec') { itemData = this.roleSpec.find(item => item._id == itemId); } if (step == 'select-role-perk') { itemData = this.rolePerks.find(item => item._id == itemId); } if (step == 'select-global-spec') { itemData = this.specs.find(item => item._id == itemId); } if (itemData) { let item = await Item.create(itemData, { temporary: true }); new PegasusItemSheet(item).render(true); } } /* -------------------------------------------- */ manageSelectableStats(race) { this.raceSelectableStats = { "race": race, "statsonlyonce": race.data.statsonlyonce, "numberstats": race.data.numberstats, "stats": duplicate(this.actor.data.data.statistics) } this.processSelectableStats() } /* -------------------------------------------- */ async renderChatMessage(formData) { let chatData = { user: game.user.id, alias: this.actor.name, rollMode: game.settings.get("core", "rollMode"), whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')), content: await renderTemplate('systems/fvtt-pegasus-rpg/templates/chat-create-actor.html', formData) }; //console.log("Apply damage chat", chatData ); await ChatMessage.create(chatData); } /* --------------- -------------------- --------- */ manageRacePerks(race) { if (!this.currentRace.data.perksgained) { this.showRoles() return; } if (!this.racePerks) { // First init if (this.currentRace.data.perksall) { this.racePerks = duplicate(this.perks) } else { this.racePerks = duplicate(this.currentRace.data.perks) } this.nbRacePerks = this.currentRace.data.perksnumber; } let formData = this.createFormData("select-race-perks") formData.raceperks = this.racePerks; formData.nbraceperks = this.nbRacePerks; this.renderChatMessage(formData) } /* --------------- -------------------- --------- */ async processSelectableStats() { // End of race options choice if (this.raceSelectableStats.numberstats == 0) { this.manageRacePerks(); return; } let formData = this.createFormData("select-race-stats") let chatData = { user: game.user.id, alias: this.actor.name, rollMode: game.settings.get("core", "rollMode"), whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients('GM')), content: await renderTemplate('systems/fvtt-pegasus-rpg/templates/chat-create-actor.html', formData) }; //console.log("Apply damage chat", chatData ); await ChatMessage.create(chatData); } /* --------------- ----------------------------- */ manageOptionnalAbilities(race) { this.raceOptionnalAbilities = { "nboptionnal": race.data.nboptionnal, "optionnalabilities": duplicate(race.data.optionnalabilities), } this.processOptionnalAbilitiesStep() } /* -------------------------------------------- */ async processOptionnalAbilitiesStep() { // End of race options choice if (this.raceOptionnalAbilities.nboptionnal == 0) { if (this.raceSelectableStats) { this.manageSelectableStats(this.currentrace); } else if (this.currentRace.system.perksgained) { this.manageRacePerks(this.currentRace); } else { this.showRoles() } } else { let formData = this.createFormData("select-race-optionnal") this.renderChatMessage(formData) } } /* -------------------------------------------- */ async showRaces() { let formData = this.createFormData("select-race") this.renderChatMessage(formData) } /* -------------------------------------------- */ async showRoles() { let formData = this.createFormData("select-role") this.renderChatMessage(formData) } /* ------------------------------- ------------- */ async showRoleStartSpec() { if (!this.roleSpecStart) { this.roleSpecStart = this.specs.filter(spec => spec.system.statistic.toUpperCase() == this.currentRole.system.statincrease1.toUpperCase() || spec.system.statistic.toUpperCase() == this.currentRole.system.statincrease2.toUpperCase()) //console.log("SPEC FOUND", this.roleSpecStart) //this.roleSpecStart = duplicate(this.currentRole.data.specialisationsplus1) this.nbRoleSpecStart = 2; } let formData = this.createFormData("select-role-start-spec") formData.rolestartspec = this.roleSpecStart formData.rolestartspec.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) formData.nbrolespecstart = this.nbRoleSpecStart; this.renderChatMessage(formData) } /* ------------------------------- ------------- */ async showRoleStat() { let formData = this.createFormData("select-role-stat") formData.rolestats = [] for (let stat of this.roleStats) { if (stat.flag) { formData.rolestats.push(duplicate(this.actor.system.statistics[stat.name.toLowerCase()])) } } //console.log("STAT", this.roleStats, formData) this.renderChatMessage(formData) } /* -------------------------------------------- */ async showRoleSpecialisations() { let formData = this.createFormData("select-role-spec") formData.rolespec = duplicate(this.roleSpec) formData.rolespec.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) formData.dt = 1 if (this.nbDT2 > 0) { formData.dt = 2 } this.renderChatMessage(formData) } /* -------------------------------------------- */ async showRolePerks() { let formData = this.createFormData("select-role-perk") formData.roleperks = duplicate(this.rolePerks) formData.roleperks.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) formData.nbperks = this.nbPerks this.renderChatMessage(formData) } /* -------------------------------------------- */ async showGlobalSpec() { let formData = this.createFormData("select-global-spec") let excludedSpecs = this.actor.items.filter(it => it.type == "specialisation" && it.system.level >= 4) formData.specs = [] for (let spec of this.specs) { let isOK = true for (let excluded of excludedSpecs) { if (excluded.name == spec.name) { isOK = false break } } if (isOK) { formData.specs.push(spec) } } formData.specs.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) this.renderChatMessage(formData) } /* -------------------------------------------- */ async showGlobalStat() { let formData = this.createFormData("select-global-stat") formData.stats = {} for (let key in this.actor.system.statistics) { let stat = this.actor.system.statistics[key] if (stat.level < 5) { formData.stats[key] = duplicate(stat) } } this.renderChatMessage(formData) } /* -------------------------------------------- */ async showGlobalPerk() { let formData = this.createFormData("select-global-perk") let excludedPerks = this.actor.items.filter(it => it.type == "perk" && !it.system.upgradable) formData.perks = [] for (let perk of this.perks) { let isOK = true for (let excluded of excludedPerks) { if (excluded.name == perk.name) { isOK = false break } } if (isOK) { formData.perks.push(perk) } } formData.perks.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) this.renderChatMessage(formData) } /* -------------------------------------------- */ async showGlobalStatus() { let formData = this.createFormData("select-global-status") formData.status = duplicate(this.actor.system.secondary) formData.status["nrg"] = duplicate(this.actor.system.nrg) this.renderChatMessage(formData) } /* -------------------------------------------- */ async showBonusSelection() { let formData = this.createFormData("select-bonus-selection") formData.bonuses = { "bonus-statistic": { name: "Increase 2 Stats" }, "bonus-specialisation": { name: "Increase 4 Specialisations" }, "bonus-perk": { name: "Choose/Upgrade 2 Perks" }, "bonus-status": { name: "Upgrade 5 status" }, "bonus-roleability": { name: "Role Ability +1" }, "bonus-ppp5": { name: "Gain +5 PPP" }, "bonus-wealthy": { name: "Wealthy (money x 2)" }, "bonus-heirloom": { name: "Family Heirloom (Special Item)" }, "bonus-vehicle": { name: "Starting Vehicle" }, "bonus-sidekick": { name: "Starting Sidekick" }, "bonus-ambidextrious": { name: "Ambidextrious" } } this.renderChatMessage(formData) } /* -------------------------------------------- */ async showVirtue() { let formData = this.createFormData("select-global-virtue") let virtues = this.actor.items.filter(it => it.type == "virtue") formData.virtues = [] for ( let virtue1 of this.virtues) { // Filter existing virtues let isOK = true for(let virtue2 of virtues) { if (virtue1.name == virtue2.name) { isOK = false break } } if (isOK) { formData.virtues.push(virtue1) } } formData.virtues.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) this.renderChatMessage(formData) } /* -------------------------------------------- */ async showVice() { let formData = this.createFormData("select-global-vice") let virtues = this.actor.items.filter(it => it.type == "virtue") let vices = this.actor.items.filter(it => it.type == "vice") formData.vices = [] for (let vice of this.vices) { let isOK = true for ( let virtue of virtues) { for (let nonVice of virtue.system.unavailablevice) { if(nonVice.name == vice.name) { isOK = false break } } } for ( let vice2 of vices) { if(vice2.name == vice.name) { isOK = false break } } if (isOK) { formData.vices.push( vice) } } formData.vices.sort(function compare(a, b) { if (a.name < b.name) { return -1 } else { return 1 } }) this.renderChatMessage(formData) } /* -------------------------------------------- */ showViceQuestion() { let formData = this.createFormData("select-vice-question") formData.questions = { "vice-next-step": { name: "Go to next step" }, "vice-5-cdp": { name: "Gain +5 CDP and choose a Vice" }, "vice-vertue": { name: "Choose a Virtue and a Vice" } } this.renderChatMessage(formData) } /* -------------------------------------------- */ async showCharacterEnd() { await this.actor.computeNRGHealth() this.actor.computeValue = false // To force value computation let formData = this.createFormData("character-end") this.renderChatMessage(formData) } }