From 9904c3dcd3f63bd540da4c3d76ec1519ace6f0b0 Mon Sep 17 00:00:00 2001 From: walcutt Date: Fri, 20 Dec 2024 11:18:13 -0500 Subject: [PATCH] Added basic cards implementation --- hench.mjs | 14 ++++ module/cards/hench-card.mjs | 29 ++++++++ module/cards/hench-cards.mjs | 135 +++++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 module/cards/hench-card.mjs create mode 100644 module/cards/hench-cards.mjs diff --git a/hench.mjs b/hench.mjs index 026016e..bcfc764 100644 --- a/hench.mjs +++ b/hench.mjs @@ -1,3 +1,5 @@ +import { HenchCard, HenchCardDataModel } from "./module/cards/hench-card.mjs"; +import { HenchCards, HenchCardsDataModel } from "./module/cards/hench-cards.mjs"; import { BossDataModel, HenchDataModel } from "./module/data-models.mjs"; import { HenchActorSheet } from "./module/sheets/hench-actor-sheet.mjs"; @@ -40,6 +42,18 @@ Hooks.once("init", () => { boss: BossDataModel, }; + CONFIG.Card.dataModels = { + base: HenchCardDataModel, + }; + CONFIG.Card.documentClass = HenchCard; + + CONFIG.Cards.dataModels = { + base: HenchCardsDataModel, + }; + CONFIG.Cards.documentClass = HenchCards; + + console.log(CONFIG); + Actors.unregisterSheet('core', ActorSheet); Actors.registerSheet('hench', HenchActorSheet, { makeDefault: true, diff --git a/module/cards/hench-card.mjs b/module/cards/hench-card.mjs new file mode 100644 index 0000000..a5ce6c3 --- /dev/null +++ b/module/cards/hench-card.mjs @@ -0,0 +1,29 @@ +const { HTMLField, SchemaField, NumberField, StringField, BooleanField, FilePathField, ArrayField } = foundry.data.fields; + +export const CARD_ZONES = { + DECK: 'DECK', + DISCARD: 'DISCARD', + SPREAD: 'SPREAD', + HELD: 'HELD', +}; + +// Data Model +export class HenchCardDataModel extends foundry.abstract.TypeDataModel { + static defineSchema() { + return { + cue: new StringField({required: true, blank: true, initial: ""}), + zone: new StringField({required: true, blank: false, initial: CARD_ZONES.DECK, options: CARD_ZONES}), + }; + } +} + +// Document Class +export class HenchCard extends Card { + get numericalValue() { + if(this.value < 7) { + return this.value; + } + + return 0; + } +} \ No newline at end of file diff --git a/module/cards/hench-cards.mjs b/module/cards/hench-cards.mjs new file mode 100644 index 0000000..315b9a6 --- /dev/null +++ b/module/cards/hench-cards.mjs @@ -0,0 +1,135 @@ +import { CARD_ZONES } from "./hench-card.mjs"; + +const { StringField } = foundry.data.fields; + +// Data Model +export class HenchCardsDataModel extends foundry.abstract.TypeDataModel { + static defineSchema() { + return {}; + } +} + +// Document Class +export class HenchCards extends Cards { + // Getters + get allCards() { + return this.cards.contents; + } + + get deck() { + return this.cardsInZone(CARD_ZONES.DECK); + } + + get discard() { + return this.allCards.filter( + c => c.system.zone === CARD_ZONES.DISCARD + ); + } + + get spread() { + return this.allCards.filter( + c => c.system.zone === CARD_ZONES.SPREAD + ); + } + + get held() { + return this.allCards.filter( + c => c.system.zone === CARD_ZONES.HELD + ); + } + + cardsInZone(zone) { + return this.allCards.filter( + c => c.system.zone === zone + ).sort((a, b) => a.sort - b.sort); + } + + // Mutations + + async updateCards(mutation) { + await this.update({ + cards: mutation, + }); + } + + // After moving cards, re-assign sorting to minimal required values + async realignSorting() { + await this.realignSubstackSorting(CARD_ZONES.DECK); + await this.realignSubstackSorting(CARD_ZONES.SPREAD); + await this.realignSubstackSorting(CARD_ZONES.HELD); + await this.realignSubstackSorting(CARD_ZONES.DISCARD); + } + + async realignSubstackSorting(zone) { + const cards = this.cardsInZone(zone); + + const sortedCards = cards.sort((a, b) => a.sort - b.sort); + + const mutation = sortedCards.map( + (c, i) => ({ + _id: c._id, + sort: i + }) + ); + + await this.updateCards(mutation); + } + + // Randomize sorting of cards, only in deck. + async shuffleDeck() { + const cards = this.cardsInZone(CARD_ZONES.DECK); + + const shuffleMutation = cards.map( + c => ({ + _id: c._id, + sort: Math.floor(Math.random() * cards.length) + }) + ); + + await this.updateCards(shuffleMutation); + + await this.realignSorting(); + } + + // Send all cards back to the deck, and shuffle. + async resetDeck() { + await this.sendCards(this.discard, CARD_ZONES.DECK); + await this.sendCards(this.held, CARD_ZONES.DECK); + await this.sendCards(this.spread, CARD_ZONES.DECK); + + await this.shuffleDeck(); + } + + async sendCards(cards, zone, dest = CONST.CARD_DRAW_MODES.BOTTOM) { + const existingZone = this.cardsInZone(zone); + + const mutation = cards.map( + (c, i) => { + let destIndex; + + switch(dest) { + case CONST.CARD_DRAW_MODES.BOTTOM: + case CONST.CARD_DRAW_MODES.LAST: + destIndex = existingZone.length + i; + break; + case CONST.CARD_DRAW_MODES.TOP: + case CONST.CARD_DRAW_MODES.FIRST: + destIndex = (-1 * cards.length) + i; + break; + default: // Random + destIndex = Math.floor(Math.random() * existingZone.length); + } + + return { + _id: c._id, + ['system.zone']: zone, + sort: destIndex + }; + } + ); + + await this.updateCards(mutation); + + await this.realignSorting(); + } +} \ No newline at end of file