Latest updates
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 420 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 102 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
+56
-2
@@ -13,7 +13,7 @@
|
|||||||
--font-primary: "TimesNewRoman";
|
--font-primary: "TimesNewRoman";
|
||||||
--font-secondary: "TimesNewRoman";
|
--font-secondary: "TimesNewRoman";
|
||||||
--font-title: "EagleLake";
|
--font-title: "EagleLake";
|
||||||
--logo-standard: url("../assets/ui/pentagram_logo.webp");
|
--logo-standard: url("../assets/ui/rose_des_vents_01.webp");
|
||||||
--title-color: #dea60b;
|
--title-color: #dea60b;
|
||||||
--background-box: #e0dcdc;
|
--background-box: #e0dcdc;
|
||||||
--color-success: #0f7a0f;
|
--color-success: #0f7a0f;
|
||||||
@@ -2936,6 +2936,58 @@ i.fvtt-hamalron {
|
|||||||
color: #f39c12;
|
color: #f39c12;
|
||||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary {
|
||||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
|
||||||
|
border: 2px solid #667eea;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-summary-title {
|
||||||
|
text-align: center;
|
||||||
|
color: #667eea;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-summary-title i {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-cards-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-cards-grid .tarot-card-summary-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
padding: 0.35rem;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-cards-grid .tarot-card-summary-item:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-cards-grid .tarot-card-summary-item img {
|
||||||
|
width: 35px;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
.fvtt-hamalron.chat-tarot-summary .tarot-cards-grid .tarot-card-summary-item .card-name {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
@keyframes pulse-banner {
|
@keyframes pulse-banner {
|
||||||
0%,
|
0%,
|
||||||
100% {
|
100% {
|
||||||
@@ -2952,7 +3004,9 @@ i.fvtt-hamalron {
|
|||||||
.application.dialog.fvtt-hamalron button {
|
.application.dialog.fvtt-hamalron button {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--color-dark-6);
|
background-color: var(--color-dark-6);
|
||||||
color: var(--color-light-1);
|
color: #ffffff;
|
||||||
|
font-weight: 500;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
.application.dialog.fvtt-hamalron input,
|
.application.dialog.fvtt-hamalron input,
|
||||||
.application.dialog.fvtt-hamalron select {
|
.application.dialog.fvtt-hamalron select {
|
||||||
|
|||||||
+15
-5
@@ -604,7 +604,7 @@
|
|||||||
},
|
},
|
||||||
"Roll": {
|
"Roll": {
|
||||||
"cancel": "Annuler",
|
"cancel": "Annuler",
|
||||||
"roll": "Lancer",
|
"roll": "Lancer l'épreuve",
|
||||||
"rollCompetence": "Jet de compétence",
|
"rollCompetence": "Jet de compétence",
|
||||||
"skill": "Compétence"
|
"skill": "Compétence"
|
||||||
},
|
},
|
||||||
@@ -678,10 +678,10 @@
|
|||||||
"CollectHandsConfirm": "Récupérer toutes les mains ?",
|
"CollectHandsConfirm": "Récupérer toutes les mains ?",
|
||||||
"CollectHandsWarning": "Cela récupérera toutes les cartes de tarot de tous les personnages joueurs et les réintégrera dans le deck. Les doublons seront supprimés pour garantir un deck de 78 cartes.",
|
"CollectHandsWarning": "Cela récupérera toutes les cartes de tarot de tous les personnages joueurs et les réintégrera dans le deck. Les doublons seront supprimés pour garantir un deck de 78 cartes.",
|
||||||
"HandsCollected": "{collected} cartes récupérées. Deck réinitialisé avec {deckSize} cartes uniques.",
|
"HandsCollected": "{collected} cartes récupérées. Deck réinitialisé avec {deckSize} cartes uniques.",
|
||||||
"DistributeCards": "Distribuer 8 cartes",
|
"DistributeCards": "Main de départ",
|
||||||
"DistributeConfirm": "Distribuer les cartes ?",
|
"DistributeConfirm": "Distribuer la main de départ ?",
|
||||||
"DistributeWarning": "Cela distribuera 8 cartes du deck à chaque joueur connecté.",
|
"DistributeWarning": "Cela distribuera 8 cartes du deck à chaque joueur connecté (le Mat est exclu de la distribution initiale).",
|
||||||
"CardsDistributed": "{cards} cartes distribuées à {players} joueur(s).",
|
"CardsDistributed": "{cards} cartes distribuées à {players} joueur(s). Le Mat a été remis dans le deck et le paquet a été remélangé.",
|
||||||
"NotEnoughCards": "Pas assez de cartes dans le deck (minimum 8 requises).",
|
"NotEnoughCards": "Pas assez de cartes dans le deck (minimum 8 requises).",
|
||||||
"DeckEmpty": "Le jeu est vide",
|
"DeckEmpty": "Le jeu est vide",
|
||||||
"DeckEmptyWarning": "Le jeu est vide. Veuillez réinitialiser le jeu pour continuer.",
|
"DeckEmptyWarning": "Le jeu est vide. Veuillez réinitialiser le jeu pour continuer.",
|
||||||
@@ -692,6 +692,16 @@
|
|||||||
"DrawOne": "Tirer 1 carte",
|
"DrawOne": "Tirer 1 carte",
|
||||||
"DrawTension": "Tirage sous tension",
|
"DrawTension": "Tirage sous tension",
|
||||||
"DrawThree": "Tirer 3 cartes",
|
"DrawThree": "Tirer 3 cartes",
|
||||||
|
"DrawThreeTrumps": "Tirer 3 atouts",
|
||||||
|
"DrawEightNumbered": "Tirer 8 cartes numérotées",
|
||||||
|
"DrawOneTrump": "Tirer 1 atout",
|
||||||
|
"EightNumberedCardsDrawn": "8 Cartes Numérotées Tirées",
|
||||||
|
"ThreeTrumpsDrawn": "3 atouts tirés et remélangés dans le deck",
|
||||||
|
"EightNumberedDrawn": "8 cartes numérotées tirées et remélangées dans le deck",
|
||||||
|
"OneTrumpDrawn": "1 atout tiré et remélangé dans le deck",
|
||||||
|
"NotEnoughTrumps": "Pas assez d'atouts dans le deck (minimum 3 requis)",
|
||||||
|
"NotEnoughNumbered": "Pas assez de cartes numérotées dans le deck (minimum 8 requises)",
|
||||||
|
"NoTrumpsAvailable": "Aucun atout disponible dans le deck",
|
||||||
"GMOnly": "Seul le MJ peut accéder au gestionnaire de jeu de tarot",
|
"GMOnly": "Seul le MJ peut accéder au gestionnaire de jeu de tarot",
|
||||||
"NoCardsFound": "Aucune carte de tarot trouvée dans le monde. Veuillez d'abord créer des objets tarot.",
|
"NoCardsFound": "Aucune carte de tarot trouvée dans le monde. Veuillez d'abord créer des objets tarot.",
|
||||||
"NoDiscard": "La défausse est vide",
|
"NoDiscard": "La défausse est vide",
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
collectHands: HamalronTarotDeckManager.#onCollectHands,
|
collectHands: HamalronTarotDeckManager.#onCollectHands,
|
||||||
distributeCards: HamalronTarotDeckManager.#onDistributeCards,
|
distributeCards: HamalronTarotDeckManager.#onDistributeCards,
|
||||||
drawTension: HamalronTarotDeckManager.#onDrawTension,
|
drawTension: HamalronTarotDeckManager.#onDrawTension,
|
||||||
|
drawThreeTrumps: HamalronTarotDeckManager.#onDrawThreeTrumps,
|
||||||
|
drawEightNumbered: HamalronTarotDeckManager.#onDrawEightNumbered,
|
||||||
|
drawOneTrump: HamalronTarotDeckManager.#onDrawOneTrump,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +319,8 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Distribute 8 cards to all connected players
|
* Distribute 8 cards to all connected players (starting hand)
|
||||||
|
* Excludes the Mat from distribution, then returns it to the deck and reshuffles
|
||||||
* @param {Event} event
|
* @param {Event} event
|
||||||
* @param {HTMLElement} target
|
* @param {HTMLElement} target
|
||||||
*/
|
*/
|
||||||
@@ -337,6 +341,7 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
|
|
||||||
let distributedCount = 0
|
let distributedCount = 0
|
||||||
let playersCount = 0
|
let playersCount = 0
|
||||||
|
let matCard = null
|
||||||
|
|
||||||
// Récupérer tous les utilisateurs connectés (sauf le GM)
|
// Récupérer tous les utilisateurs connectés (sauf le GM)
|
||||||
const connectedPlayers = game.users.filter(u => u.active && !u.isGM)
|
const connectedPlayers = game.users.filter(u => u.active && !u.isGM)
|
||||||
@@ -349,10 +354,22 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (playerCharacter) {
|
if (playerCharacter) {
|
||||||
// Tirer 8 cartes pour ce personnage
|
// Tirer 8 cartes pour ce personnage (en ignorant le Mat)
|
||||||
const cardsToDistribute = []
|
const cardsToDistribute = []
|
||||||
for (let i = 0; i < 8 && this.deck.length > 0; i++) {
|
let attempts = 0
|
||||||
|
const maxAttempts = this.deck.length + 10 // Safety limit
|
||||||
|
|
||||||
|
while (cardsToDistribute.length < 8 && this.deck.length > 0 && attempts < maxAttempts) {
|
||||||
const card = this.deck.shift()
|
const card = this.deck.shift()
|
||||||
|
attempts++
|
||||||
|
|
||||||
|
// Si c'est le Mat, le mettre de côté
|
||||||
|
if (card.valeur === "lemat") {
|
||||||
|
matCard = card
|
||||||
|
console.log("Le Mat trouvé et mis de côté pour être remis dans le deck après distribution")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
cardsToDistribute.push(card)
|
cardsToDistribute.push(card)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,14 +379,6 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
if (originalItem) {
|
if (originalItem) {
|
||||||
await playerCharacter.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
await playerCharacter.createEmbeddedDocuments("Item", [originalItem.toObject()])
|
||||||
distributedCount++
|
distributedCount++
|
||||||
|
|
||||||
// Cas spécial : Le Mat
|
|
||||||
if (card.valeur === "lemat") {
|
|
||||||
console.log(`Le Mat distributed to ${playerCharacter.name}! Executing special rules...`)
|
|
||||||
// Import de TirageTarot pour accéder à la fonction helper
|
|
||||||
const { default: HamalronTirageTarot } = await import("../documents/tirage-tarot.mjs")
|
|
||||||
await HamalronTirageTarot.handleLeMatEffect(playerCharacter, this)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,6 +386,16 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remettre le Mat dans le deck si il a été trouvé
|
||||||
|
if (matCard) {
|
||||||
|
this.deck.push(matCard)
|
||||||
|
console.log("Le Mat a été remis dans le deck")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remélanger le deck restant
|
||||||
|
this.shuffleDeck()
|
||||||
|
console.log("Le deck restant a été remélangé")
|
||||||
|
|
||||||
this.saveDeckState()
|
this.saveDeckState()
|
||||||
|
|
||||||
ui.notifications.info(
|
ui.notifications.info(
|
||||||
@@ -389,6 +408,105 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
this.render()
|
this.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw 3 trumps (atouts only)
|
||||||
|
* Cards are returned to deck and reshuffled after draw
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onDrawThreeTrumps(event, target) {
|
||||||
|
const trumpCards = this.deck.filter(card => card.type === "atout")
|
||||||
|
|
||||||
|
if (trumpCards.length < 3) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NotEnoughTrumps"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tirer 3 atouts au hasard
|
||||||
|
const drawnCards = []
|
||||||
|
const availableTrumps = [...trumpCards]
|
||||||
|
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * availableTrumps.length)
|
||||||
|
const card = availableTrumps.splice(randomIndex, 1)[0]
|
||||||
|
drawnCards.push(card)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Envoyer au chat
|
||||||
|
await this.sendCardsToChat(drawnCards)
|
||||||
|
|
||||||
|
// Remélanger le deck (les cartes restent dedans)
|
||||||
|
this.shuffleDeck()
|
||||||
|
this.saveDeckState()
|
||||||
|
this.render()
|
||||||
|
|
||||||
|
ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.ThreeTrumpsDrawn"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw 8 numbered cards (cards 1-10 from the 4 symbols)
|
||||||
|
* Cards are returned to deck and reshuffled after draw
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onDrawEightNumbered(event, target) {
|
||||||
|
const numberedCards = this.deck.filter(card => card.type === "numéro")
|
||||||
|
|
||||||
|
if (numberedCards.length < 8) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NotEnoughNumbered"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tirer 8 cartes numérotées au hasard
|
||||||
|
const drawnCards = []
|
||||||
|
const availableNumbered = [...numberedCards]
|
||||||
|
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
const randomIndex = Math.floor(Math.random() * availableNumbered.length)
|
||||||
|
const card = availableNumbered.splice(randomIndex, 1)[0]
|
||||||
|
drawnCards.push(card)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Envoyer un résumé au chat
|
||||||
|
await this.sendNumberedCardsSummaryToChat(drawnCards)
|
||||||
|
|
||||||
|
// Remélanger le deck (les cartes restent dedans)
|
||||||
|
this.shuffleDeck()
|
||||||
|
this.saveDeckState()
|
||||||
|
this.render()
|
||||||
|
|
||||||
|
ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.EightNumberedDrawn"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw 1 trump (atout only)
|
||||||
|
* Card is returned to deck and reshuffled after draw
|
||||||
|
* @param {Event} event
|
||||||
|
* @param {HTMLElement} target
|
||||||
|
*/
|
||||||
|
static async #onDrawOneTrump(event, target) {
|
||||||
|
const trumpCards = this.deck.filter(card => card.type === "atout")
|
||||||
|
|
||||||
|
if (trumpCards.length === 0) {
|
||||||
|
ui.notifications.warn(game.i18n.localize("HAMALRON.TarotDeck.NoTrumpsAvailable"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tirer 1 atout au hasard
|
||||||
|
const randomIndex = Math.floor(Math.random() * trumpCards.length)
|
||||||
|
const card = trumpCards[randomIndex]
|
||||||
|
|
||||||
|
// Envoyer au chat
|
||||||
|
await this.sendCardsToChat([card])
|
||||||
|
|
||||||
|
// Remélanger le deck (la carte reste dedans)
|
||||||
|
this.shuffleDeck()
|
||||||
|
this.saveDeckState()
|
||||||
|
this.render()
|
||||||
|
|
||||||
|
ui.notifications.info(game.i18n.localize("HAMALRON.TarotDeck.OneTrumpDrawn"))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shuffle discard pile back into deck
|
* Shuffle discard pile back into deck
|
||||||
* @param {Event} event
|
* @param {Event} event
|
||||||
@@ -437,7 +555,7 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
|
|
||||||
const content = `
|
const content = `
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>{{localize "HAMALRON.Label.difficulty"}}</label>
|
<label>${game.i18n.localize("HAMALRON.Label.difficulty")}</label>
|
||||||
<select id="tension-difficulty" style="width: 100%;">
|
<select id="tension-difficulty" style="width: 100%;">
|
||||||
${selectOptions}
|
${selectOptions}
|
||||||
</select>
|
</select>
|
||||||
@@ -524,6 +642,44 @@ export default class HamalronTarotDeckManager extends HandlebarsApplicationMixin
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send numbered cards summary to chat
|
||||||
|
* @param {Array} cards - Array of numbered cards
|
||||||
|
*/
|
||||||
|
async sendNumberedCardsSummaryToChat(cards) {
|
||||||
|
const speaker = ChatMessage.getSpeaker({ alias: "Maître du Jeu" })
|
||||||
|
|
||||||
|
// Créer la liste des cartes
|
||||||
|
const cardsList = cards.map(card => {
|
||||||
|
const symboleLabel = game.i18n.localize(`HAMALRON.Tarot.FIELDS.symbole.${card.symbole}`)
|
||||||
|
const valeurLabel = game.i18n.localize(`HAMALRON.Tarot.FIELDS.valeur.${card.valeur}`)
|
||||||
|
return `
|
||||||
|
<div class="tarot-card-summary-item">
|
||||||
|
<img src="${card.img}" alt="${card.name}" title="${card.name}" />
|
||||||
|
<span class="card-name">${valeurLabel} de ${symboleLabel}</span>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}).join('')
|
||||||
|
|
||||||
|
const content = `
|
||||||
|
<div class="fvtt-hamalron chat-tarot-summary">
|
||||||
|
<h3 class="tarot-summary-title">
|
||||||
|
<i class="fas fa-hashtag"></i>
|
||||||
|
${game.i18n.localize("HAMALRON.TarotDeck.EightNumberedCardsDrawn")}
|
||||||
|
</h3>
|
||||||
|
<div class="tarot-cards-grid">
|
||||||
|
${cardsList}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
await ChatMessage.create({
|
||||||
|
speaker: speaker,
|
||||||
|
content: content,
|
||||||
|
type: CONST.CHAT_MESSAGE_TYPES.OTHER,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the Tarot Deck Manager application
|
* Open the Tarot Deck Manager application
|
||||||
* @returns {HamalronTarotDeckManager}
|
* @returns {HamalronTarotDeckManager}
|
||||||
|
|||||||
@@ -76,12 +76,16 @@ export default class HamalronTirageTarot {
|
|||||||
|
|
||||||
// Marquer les cartes de succès
|
// Marquer les cartes de succès
|
||||||
if (options.tarotCards && actor.system.cartesSucces) {
|
if (options.tarotCards && actor.system.cartesSucces) {
|
||||||
|
const competenceSymbole = options.rollItem.system.carteSymbole
|
||||||
options.tarotCards = options.tarotCards.map(card => {
|
options.tarotCards = options.tarotCards.map(card => {
|
||||||
const isSuccessCard = card.system.type !== "atout" && Object.keys(actor.system.cartesSucces).some(symbole => {
|
// Pour qu'une carte soit une carte de succès :
|
||||||
const successCardData = actor.system.cartesSucces[symbole]
|
// 1. Elle ne doit pas être un atout
|
||||||
return card.system.symbole === symbole &&
|
// 2. Son symbole doit correspondre à celui de la compétence
|
||||||
card.system.valeur === successCardData.value.toString()
|
// 3. Sa valeur doit correspondre à celle d'une carte de succès pour ce symbole
|
||||||
})
|
const isSuccessCard = card.system.type !== "atout" &&
|
||||||
|
card.system.symbole === competenceSymbole &&
|
||||||
|
actor.system.cartesSucces[competenceSymbole] &&
|
||||||
|
card.system.valeur === actor.system.cartesSucces[competenceSymbole].value.toString()
|
||||||
// Créer un objet simple avec toutes les propriétés nécessaires
|
// Créer un objet simple avec toutes les propriétés nécessaires
|
||||||
return {
|
return {
|
||||||
id: card.id,
|
id: card.id,
|
||||||
@@ -339,12 +343,15 @@ export default class HamalronTirageTarot {
|
|||||||
cardSymboleMatch = selectedCard.system.symbole === options.rollItem.system.carteSymbole
|
cardSymboleMatch = selectedCard.system.symbole === options.rollItem.system.carteSymbole
|
||||||
|
|
||||||
// Vérifier si c'est une carte de succès (les atouts ne peuvent jamais être des cartes de succès)
|
// Vérifier si c'est une carte de succès (les atouts ne peuvent jamais être des cartes de succès)
|
||||||
|
// Pour qu'une carte soit une carte de succès :
|
||||||
|
// 1. Elle ne doit pas être un atout
|
||||||
|
// 2. Son symbole doit correspondre à celui de la compétence
|
||||||
|
// 3. Sa valeur doit correspondre à celle d'une carte de succès pour ce symbole
|
||||||
if (actor.system.cartesSucces && selectedCard.system.type !== "atout") {
|
if (actor.system.cartesSucces && selectedCard.system.type !== "atout") {
|
||||||
isAutomaticSuccess = Object.keys(actor.system.cartesSucces).some(symbole => {
|
const competenceSymbole = options.rollItem.system.carteSymbole
|
||||||
const successCardData = actor.system.cartesSucces[symbole]
|
isAutomaticSuccess = selectedCard.system.symbole === competenceSymbole &&
|
||||||
return selectedCard.system.symbole === symbole &&
|
actor.system.cartesSucces[competenceSymbole] &&
|
||||||
selectedCard.system.valeur === successCardData.value.toString()
|
selectedCard.system.valeur === actor.system.cartesSucces[competenceSymbole].value.toString()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export default class HamalronPersonnage extends foundry.abstract.TypeDataModel {
|
|||||||
hair: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
hair: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
home: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
home: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
weight: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
weight: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
|
origineSociale: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||||
})
|
})
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
MANIFEST-000016
|
MANIFEST-000036
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
2026/01/02-10:10:10.253712 7f93ebfff6c0 Recovering log #15
|
2026/04/23-21:08:40.433784 7f9ca63fd6c0 Recovering log #34
|
||||||
2026/01/02-10:10:10.307712 7f93ebfff6c0 Delete type=0 #15
|
2026/04/23-21:08:40.485675 7f9ca63fd6c0 Delete type=3 #32
|
||||||
2026/01/02-10:10:10.307764 7f93ebfff6c0 Delete type=3 #14
|
2026/04/23-21:08:40.485751 7f9ca63fd6c0 Delete type=0 #34
|
||||||
2026/01/02-20:13:00.317288 7f93e9ffb6c0 Level-0 table #19: started
|
2026/04/24-08:02:08.256846 7f9ca53fb6c0 Level-0 table #39: started
|
||||||
2026/01/02-20:13:00.317383 7f93e9ffb6c0 Level-0 table #19: 0 bytes OK
|
2026/04/24-08:02:08.256902 7f9ca53fb6c0 Level-0 table #39: 0 bytes OK
|
||||||
2026/01/02-20:13:00.324182 7f93e9ffb6c0 Delete type=0 #17
|
2026/04/24-08:02:08.263739 7f9ca53fb6c0 Delete type=0 #37
|
||||||
2026/01/02-20:13:00.343771 7f93e9ffb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
|
2026/04/24-08:02:08.263920 7f9ca53fb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
2025/12/28-22:58:25.963740 7f4a83fff6c0 Recovering log #12
|
2026/01/05-22:50:34.529979 7f93eaffd6c0 Recovering log #30
|
||||||
2025/12/28-22:58:25.975413 7f4a83fff6c0 Delete type=3 #10
|
2026/01/05-22:50:34.539962 7f93eaffd6c0 Delete type=3 #28
|
||||||
2025/12/28-22:58:25.975552 7f4a83fff6c0 Delete type=0 #12
|
2026/01/05-22:50:34.540010 7f93eaffd6c0 Delete type=0 #30
|
||||||
|
2026/01/05-22:53:30.707035 7f93e9ffb6c0 Level-0 table #35: started
|
||||||
|
2026/01/05-22:53:30.707107 7f93e9ffb6c0 Level-0 table #35: 0 bytes OK
|
||||||
|
2026/01/05-22:53:30.713792 7f93e9ffb6c0 Delete type=0 #33
|
||||||
|
2026/01/05-22:53:30.735909 7f93e9ffb6c0 Manual compaction at level-0 from 'undefined' @ 72057594037927935 : 1 .. 'undefined' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -713,6 +713,69 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Style pour le résumé des cartes numérotées
|
||||||
|
&.chat-tarot-summary {
|
||||||
|
background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
|
||||||
|
border: 2px solid #667eea;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.tarot-summary-title {
|
||||||
|
text-align: center;
|
||||||
|
color: #667eea;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tarot-cards-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
.tarot-card-summary-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
padding: 0.35rem;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
transition:
|
||||||
|
transform 0.2s,
|
||||||
|
box-shadow 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 35px;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 0.2rem;
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-name {
|
||||||
|
font-size: 0.65rem;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pulse-banner {
|
@keyframes pulse-banner {
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
--font-primary: "TimesNewRoman";
|
--font-primary: "TimesNewRoman";
|
||||||
--font-secondary: "TimesNewRoman";
|
--font-secondary: "TimesNewRoman";
|
||||||
--font-title: "EagleLake";
|
--font-title: "EagleLake";
|
||||||
--logo-standard: url("../assets/ui/pentagram_logo.webp");
|
--logo-standard: url("../assets/ui/rose_des_vents_01.webp");
|
||||||
--title-color: #dea60b;
|
--title-color: #dea60b;
|
||||||
--background-box: #e0dcdc;
|
--background-box: #e0dcdc;
|
||||||
--color-success: rgb(15, 122, 15);
|
--color-success: rgb(15, 122, 15);
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,9 @@
|
|||||||
button {
|
button {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
background-color: var(--color-dark-6);
|
background-color: var(--color-dark-6);
|
||||||
color: var(--color-light-1);
|
color: #ffffff;
|
||||||
|
font-weight: 500;
|
||||||
|
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
|
|||||||
+3
-3
@@ -6,7 +6,7 @@
|
|||||||
"download": "#{DOWNLOAD}#",
|
"download": "#{DOWNLOAD}#",
|
||||||
"url": "https://www.uberwald.me/gitea/public/fvtt-hamalron",
|
"url": "https://www.uberwald.me/gitea/public/fvtt-hamalron",
|
||||||
"license": "LICENSE",
|
"license": "LICENSE",
|
||||||
"version": "13.0.0",
|
"version": "14.0.0",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Uberwald",
|
"name": "Uberwald",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
} },
|
} },
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "13",
|
"minimum": "13",
|
||||||
"verified": "13"
|
"verified": "14"
|
||||||
},
|
},
|
||||||
"esmodules": ["fvtt-hamalron.mjs"],
|
"esmodules": ["fvtt-hamalron.mjs"],
|
||||||
"styles": ["css/fvtt-hamalron.css"],
|
"styles": ["css/fvtt-hamalron.css"],
|
||||||
@@ -65,5 +65,5 @@
|
|||||||
},
|
},
|
||||||
"primaryTokenAttribute": "hp",
|
"primaryTokenAttribute": "hp",
|
||||||
"socket": true,
|
"socket": true,
|
||||||
"background": "systems/fvtt-hamalron/assets/ui/hamalron_background_01.webp"
|
"background": "systems/fvtt-hamalron/assets/ui/illu_alknonost_01.webp"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,6 +68,12 @@
|
|||||||
rootId=partId
|
rootId=partId
|
||||||
disabled=isPlayMode
|
disabled=isPlayMode
|
||||||
}}
|
}}
|
||||||
|
{{formField
|
||||||
|
systemFields.biodata.fields.origineSociale
|
||||||
|
value=system.biodata.origineSociale
|
||||||
|
rootId=partId
|
||||||
|
disabled=isPlayMode
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
@@ -82,142 +88,6 @@
|
|||||||
}}
|
}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.backstory"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.backstory
|
|
||||||
enriched=enrichedBackstory
|
|
||||||
value=system.backstory
|
|
||||||
name="system.backstory"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div class="splitted-text">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.appearance"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.appearance
|
|
||||||
enriched=enrichedAppearance
|
|
||||||
value=system.appearance
|
|
||||||
name="system.appearance"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.scars"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.scars
|
|
||||||
enriched=scars
|
|
||||||
value=system.scars
|
|
||||||
name="system.scars"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="splitted-text">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.likes"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.likes
|
|
||||||
enriched=enrichedLikes
|
|
||||||
value=system.likes
|
|
||||||
name="system.likes"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.dislikes"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.dislikes
|
|
||||||
enriched=enrichedDislikes
|
|
||||||
value=system.dislikes
|
|
||||||
name="system.dislikes"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="splitted-text">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.fears"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.fears
|
|
||||||
enriched=enrichedFears
|
|
||||||
value=system.fears
|
|
||||||
name="system.fears"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.vices"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.vices
|
|
||||||
enriched=enrichedVices
|
|
||||||
value=system.vices
|
|
||||||
name="system.vices"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="splitted-text">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.goals"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.goals
|
|
||||||
enriched=enrichedGoals
|
|
||||||
value=system.goals
|
|
||||||
name="system.goals"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.ambitions"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.ambitions
|
|
||||||
enriched=enrichedAmbitions
|
|
||||||
value=system.ambitions
|
|
||||||
name="system.ambitions"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="splitted-text">
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.values"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.values
|
|
||||||
enriched=enrichedValues
|
|
||||||
value=system.values
|
|
||||||
name="system.values"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.bonds"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.bonds
|
|
||||||
enriched=enrichedBonds
|
|
||||||
value=system.bonds
|
|
||||||
name="system.bonds"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<fieldset>
|
|
||||||
<legend>{{localize "HAMALRON.Label.notes"}}</legend>
|
|
||||||
{{formInput
|
|
||||||
systemFields.notes
|
|
||||||
enriched=enrichedNotes
|
|
||||||
value=system.notes
|
|
||||||
name="system.notes"
|
|
||||||
toggled=true
|
|
||||||
}}
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -50,6 +50,21 @@
|
|||||||
<i class="fas fa-bolt"></i>
|
<i class="fas fa-bolt"></i>
|
||||||
{{localize "HAMALRON.TarotDeck.DrawTension"}}
|
{{localize "HAMALRON.TarotDeck.DrawTension"}}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="action-button draw-three-trumps-button" data-action="drawThreeTrumps" {{#unless hasCards}}disabled{{/unless}}>
|
||||||
|
<i class="fas fa-crown"></i>
|
||||||
|
{{localize "HAMALRON.TarotDeck.DrawThreeTrumps"}}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="action-button draw-eight-numbered-button" data-action="drawEightNumbered" {{#unless hasCards}}disabled{{/unless}}>
|
||||||
|
<i class="fas fa-hashtag"></i>
|
||||||
|
{{localize "HAMALRON.TarotDeck.DrawEightNumbered"}}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="action-button draw-one-trump-button" data-action="drawOneTrump" {{#unless hasCards}}disabled{{/unless}}>
|
||||||
|
<i class="fas fa-star"></i>
|
||||||
|
{{localize "HAMALRON.TarotDeck.DrawOneTrump"}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#unless hasCards}}
|
{{#unless hasCards}}
|
||||||
|
|||||||
Reference in New Issue
Block a user