import { SoSCardDeck } from "./sos-card-deck.js"; import { SoSUtility } from "./sos-utility.js"; import { SoSFlipDialog } from "./sos-flip-dialog.js"; /* -------------------------------------------- */ /** * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. * @extends {Actor} */ export class SoSActor extends Actor { /* -------------------------------------------- */ /** * Override the create() function to provide additional SoS functionality. * * This overrided create() function adds initial items * Namely: Basic skills, money, * * @param {Object} data Barebones actor data which this function adds onto. * @param {Object} options (Unused) Additional options which customize the creation workflow. * */ static async create(data, options) { // Case of compendium global import if (data instanceof Array) { return super.create(data, options); } // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic if (data.items) { let actor = super.create(data, options); return actor; } data.items = []; let compendiumName = "foundryvtt-shadows-over-sol.skills"; if ( compendiumName ) { let skills = await SoSUtility.loadCompendium(compendiumName); data.items = data.items.concat( skills ); } compendiumName = "foundryvtt-shadows-over-sol.consequences"; if ( compendiumName ) { let consequences = await SoSUtility.loadCompendium(compendiumName) data.items = data.items.concat(consequences); } return super.create(data, options); } /* -------------------------------------------- */ async prepareData() { super.prepareData(); if ( !this.cardDeck ) { this.cardDeck = new SoSCardDeck(); this.cardDeck.initCardDeck( this, this.data.data.internals.deck ); } this.controlScores(); } /* -------------------------------------------- */ getEdgesCard( ) { let edgesCard = duplicate(this.cardDeck.data.cardEdge); for (let edge of edgesCard) { edge.path = `systems/foundryvtt-shadows-over-sol/img/cards/${edge.cardName}.webp` } return edgesCard; } /* -------------------------------------------- */ resetDeckFull( ) { this.cardDeck.shuffleDeck(); this.cardDeck.drawEdge( this.data.data.scores.edge.value ); this.saveDeck(); } /* -------------------------------------------- */ drawNewEdge( ) { this.cardDeck.drawEdge( 1 ); this.saveDeck(); } /* -------------------------------------------- */ resetDeck() { } /* -------------------------------------------- */ saveDeck( ) { let deck = { deck: duplicate(this.cardDeck.data.deck), discard: duplicate(this.cardDeck.data.discard), cardEdge: duplicate(this.cardDeck.data.cardEdge) } this.update( { 'data.internals.deck': deck }); } /* -------------------------------------------- */ getDefense( ) { return this.data.data.scores.defense; } /* -------------------------------------------- */ computeDefense() { return { value: Math.ceil((this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value) / 2), critical: this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value } } /* -------------------------------------------- */ getEdge( ) { return this.data.data.scores.edge.value; } /* -------------------------------------------- */ getEncumbrance( ) { return this.data.data.scores.encumbrance.value; } /* -------------------------------------------- */ computeEdge( ) { return Math.ceil( (this.data.data.stats.intelligence.value + this.data.data.stats.charisma.value) / 2) + this.data.data.scores.edge.bonus; } /* -------------------------------------------- */ getShock( ) { return this.data.data.scores.shock.value; } computeShock() { return Math.ceil( this.data.data.stats.endurance.value + this.data.data.stats.determination.value + this.data.data.scores.dr.value); } /* -------------------------------------------- */ getWound( ) { return this.data.data.scores.wound.value; } computeWound() { return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2); } /* -------------------------------------------- */ async controlScores() { // Defense check let defenseData = this.getDefense(); let newDefenseData = this.computeDefense(); if ( defenseData.value != newDefenseData.value || defenseData.critical != newDefenseData.critical) { await this.update( {'data.scores.defense': newDefenseData}); } // Edge check if ( this.getEdge() != this.computeEdge() ) { await this.update( {'data.scores.edge.value': this.computeEdge()}); } // Encumbrance if ( this.getEncumbrance() != this.data.data.stats.strength.value ) { await this.update( {'data.scores.encumbrance.value': this.data.data.stats.strength.value }); } // Shock if ( this.getShock() != this.computeShock() ) { await this.update( {'data.scores.shock.value': this.computeShock() }); } // Wounds if ( this.getWound() != this.computeWound() ) { await this.update( {'data.scores.wound.value': this.computeWound() }); } } /* -------------------------------------------- */ async rollStat( statKey ) { let flipData = { mode: 'stat', stat: duplicate(this.data.data.stats[statKey]), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20) } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/dialog-flip.html', flipData); new SoSFlipDialog(flipData, html).render(true); //console.log("STAT", this); //let result = this.cardDeck.doFlipStat( duplicate(this.data.data.stat[statKey]) ); } /* -------------------------------------------- */ async rollSkill( skill ) { let flipData = { mode: 'skill', statList: duplicate(this.data.data.stats), skill: duplicate(skill), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20) } flipData.statList['nostat'] = { label: "No stat (ie defaulting skills)", value: 0, cardsuit: "none" } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/dialog-flip.html', flipData); new SoSFlipDialog(flipData, html).render(true); } }