From 2e2ee0c6f004f9ed215f4c95fade9055a9f34602 Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 6 Aug 2024 18:16:00 -0700 Subject: [PATCH] Selling joker, negative, ectoplasm, ankh, hex --- src/App.tsx | 2 +- src/Constants.ts | 4 ++-- src/GameState.ts | 26 ++++++++++++++++++++------ src/components/Card.tsx | 1 - src/components/Consumable.css | 9 +++++---- src/components/Consumable.tsx | 34 ++++++++++++++++++++++++++++++---- src/components/Joker.css | 23 +++++++++++++++++++++++ src/components/Joker.tsx | 13 ++++++++----- 8 files changed, 89 insertions(+), 23 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 4a42a05..894579b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -94,7 +94,7 @@ export default function App() { )} -
0/5
+
{`${game.jokers.length}/${game.stats.jokerSize}`}
diff --git a/src/Constants.ts b/src/Constants.ts index c612dc0..609c2fa 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -429,7 +429,7 @@ export const Consumables: ConsumableType[] = [ type: 'Spectral' }, { name: 'Ectoplasm', - description: 'Add Negative to a random Joker.\n{red}-1/ hand size', + description: 'Add /{indigo}Negative/ to\na random Joker.\n{red}-1/ hand size', type: 'Spectral' }, { name: 'Immolate', @@ -437,7 +437,7 @@ export const Consumables: ConsumableType[] = [ type: 'Spectral' }, { name: 'Ankh', - description: 'Create a copy of a random Joker, destroy all other Jokers (Removes Negative from copy)', + description: 'Create a copy of\na random Joker,\ndestroy all other Jokers\n/{small grey}(Removes Negative from copy)', type: 'Spectral' }, { name: 'Deja Vu', diff --git a/src/GameState.ts b/src/GameState.ts index d14c896..2dfe056 100644 --- a/src/GameState.ts +++ b/src/GameState.ts @@ -79,14 +79,14 @@ type GameAction = { 'stat' | 'select' | 'submit' | 'discard' | 'draw' | 'setSort' | 'updateCards' | 'addCard' | 'removeCard' | - 'setLastUsedConsumable' | 'addJoker' | + 'setLastUsedConsumable' | 'addJoker' | 'removeJoker' | 'shop-select' | 'shop-remove' | 'reroll' payload?: { deck?: DeckType, state?: GameStates - stat?: 'handSize' | 'hands' | 'discards' | 'money' | 'ante' | 'score' + stat?: keyof typeof initialGameState['stats'] previous?: 'played' | 'discarded' // To know during a draw which came previously amount?: number @@ -145,10 +145,10 @@ export const initialGameState: GameState = { played: [], consumables: [{ id: 53, - consumable: Consumables[3] + consumable: Consumables[19] }, { id: 54, - consumable: Consumables[43] + consumable: Consumables[21] }], lastCon: undefined }, @@ -587,7 +587,6 @@ export const gameReducer = (state: GameState, action: GameAction): GameState => hand: state.cards.hand.sort(sort), sort: action.payload?.sort! }} - console.log('game state setsort snap') setTimeout(() => cardSnap({cards: state.cards.hand, idPrefix: 'card'})) break case 'updateCards': @@ -629,14 +628,29 @@ export const gameReducer = (state: GameState, action: GameAction): GameState => selected: false, shopMode: false, } - console.log(newJoker) next = {...next, + ...(newJoker.edition === Edition?.Negative && { + stats: {...state.stats, + jokerSize: state.stats.jokerSize + 1 + } + }), jokers: [...state.jokers, newJoker], cards: {...state.cards, nextId: state.cards.nextId + 1 } } break + case 'removeJoker': + let joker = action.payload?.card as JokerInstance + next = {...next, + ...(joker.edition === Edition?.Negative && { + stats: {...state.stats, + jokerSize: state.stats.jokerSize - 1 + } + }), + jokers: state.jokers.filter(j => j.id !== joker.id) + } + break case 'shop-select': let updated = state.shop.offers updated.forEach((o) => { diff --git a/src/components/Card.tsx b/src/components/Card.tsx index 80d3081..363f8e8 100644 --- a/src/components/Card.tsx +++ b/src/components/Card.tsx @@ -165,7 +165,6 @@ export const Card = ({ const mouseUp = () => { if (dragElem) { - console.log('after drag card snap') cardSnap({cards: gameRef.current.cards.hand, idPrefix: 'card'}) document.removeEventListener('mousemove', mouseMove) document.removeEventListener('mouseup', mouseUp) diff --git a/src/components/Consumable.css b/src/components/Consumable.css index 9ff5927..45c111b 100644 --- a/src/components/Consumable.css +++ b/src/components/Consumable.css @@ -68,6 +68,11 @@ div[id^='consumable_'] img { border-radius: 0 8px 8px 0; } +.consumable-tab:hover { + cursor: pointer; + filter: brightness(.75); +} + #sell-consumable { background-color: var(--green); font-size: 24px; @@ -161,10 +166,6 @@ div[id^='consumable_']:hover > #consumable-popup { #consumable-info > div > div.nospace { margin: 0 0 0 -2px; } -.planet-upgrade { - display: flex; -} - #consumable-type { font-size: 24px; text-align: center; diff --git a/src/components/Consumable.tsx b/src/components/Consumable.tsx index 0f74b3e..98dee21 100644 --- a/src/components/Consumable.tsx +++ b/src/components/Consumable.tsx @@ -119,8 +119,13 @@ export const Consumable = ({ selected = false, consumable: cons, ...props }: Con game.cards.hand.forEach(c => c.rank = Rank[rank]) dispatch({type: 'stat', payload: {stat: 'handSize'}}) break - case 'Ectoplasm': // TODO (after jokers) - dispatch({type: 'stat', payload: {stat: 'handSize'}}) + case 'Ectoplasm': + let nonEditionJokers = game.jokers.filter(j => j.edition === undefined) + if(nonEditionJokers.length > 0) { + nonEditionJokers[Math.floor(Math.random() * nonEditionJokers.length)].edition = Edition.Negative + dispatch({type: 'stat', payload: {stat: 'handSize'}}) + dispatch({type: 'stat', payload: {stat: 'jokerSize', amount: 1}}) + } break case 'Immolate': if(game.state !== 'scoring') { return } @@ -131,13 +136,34 @@ export const Consumable = ({ selected = false, consumable: cons, ...props }: Con dispatch({type: 'updateCards', payload: {cardLocation: 'hand', update: update}}) dispatch({type: 'stat', payload: {stat: 'money', amount: 20}}) break - case 'Ankh': // TODO (after jokers) + case 'Ankh': + if(game.jokers.length > 0) { + let toCopy = game.jokers[Math.floor(Math.random() * game.jokers.length)] + game.jokers.forEach(j => { + if(j.id !== toCopy.id) { + dispatch({type: 'removeJoker', payload: {card: j}}) + } + }) + dispatch({type: 'addJoker', payload: {card: {...toCopy, edition: (toCopy.edition === Edition?.Negative ? undefined : toCopy.edition)}}}) + } break case 'Deja Vu': if(game.state !== 'scoring' || game.cards.selected.length !== 1) { return } game.cards.selected[0].seal = Seal.Red break - case 'Hex': // TODO (after jokers) + case 'Hex': + if(game.jokers.length > 0) { + let nonEditionJokers = game.jokers.filter(j => j.edition === undefined) + if(nonEditionJokers.length > 0) { + let toPoly = nonEditionJokers[Math.floor(Math.random() * nonEditionJokers.length)] + game.jokers.forEach(j => { + if(j.id !== toPoly.id) { + dispatch({type: 'removeJoker', payload: {card: j}}) + } + }) + toPoly.edition = Edition.Polychrome + } + } break case 'Trance': if(game.state !== 'scoring' || game.cards.selected.length !== 1) { return } diff --git a/src/components/Joker.css b/src/components/Joker.css index dbe608f..099f62c 100644 --- a/src/components/Joker.css +++ b/src/components/Joker.css @@ -124,4 +124,27 @@ div[id^='joker_']:hover #joker-description-outline { display: initial; } #joker-buy-button:hover { filter: brightness(.75); cursor: pointer; +} + +#sell-joker { + position: absolute; + top: 50%; + transform: translateY(-50%); + right: -56px; + width: 48px; + text-align: right; + margin: 4px 0; + padding: 4px; + border-radius: 0 8px 8px 0; + background-color: var(--green); + font-size: 24px; +} + +#sell-joker:hover { + filter: brightness(.75); + cursor: pointer; +} + +#joker-sell-price { + font-size: 36px; } \ No newline at end of file diff --git a/src/components/Joker.tsx b/src/components/Joker.tsx index 8043389..1e8aaf5 100644 --- a/src/components/Joker.tsx +++ b/src/components/Joker.tsx @@ -9,6 +9,7 @@ const images: Record = import.meta.glob('../assets/ export const Joker = ({id, joker, selected = false, ...props}: JokerInstance) => { const { state: game, dispatch } = useContext(GameStateContext) const image = getImage(`../assets/jokers/${joker.rarity}/${joker.name.replace(/\s/g, '_')}.png`, images) + const self: JokerInstance = {id, joker, selected, ...props} const price = joker.cost const sellPrice = Math.floor(price / 2) @@ -33,9 +34,9 @@ export const Joker = ({id, joker, selected = false, ...props}: JokerInstance) => > { if(props.shopMode) { - dispatch({type: 'shop-select', payload: {card: {id, joker, selected, ...props}}}) + dispatch({type: 'shop-select', payload: {card: self}}) } else { - dispatch({type: 'select', payload: {card: {id, joker, selected, ...props}}}) + dispatch({type: 'select', payload: {card: self}}) } }} draggable={false} />
@@ -62,16 +63,18 @@ export const Joker = ({id, joker, selected = false, ...props}: JokerInstance) =>
{ if(game.stats.money >= price && game.jokers.length < game.stats.jokerSize) { dispatch({type: 'stat', payload: {stat: 'money', amount: -price}}) - dispatch({type: 'shop-remove', payload: {card: {id, joker, selected, ...props}}}) - dispatch({type: 'addJoker', payload: {card: {id, joker, selected, ...props}}}) + dispatch({type: 'shop-remove', payload: {card: self}}) + dispatch({type: 'addJoker', payload: {card: self}}) } }}>BUY
} {!props.shopMode && selected &&
{ dispatch({type: 'stat', payload: {stat: 'money', amount: sellPrice}}) - dispatch({type: 'discard'}) + dispatch({type: 'removeJoker', payload: {card: self}}) }}> + SELL +
{`$${sellPrice}`}
}