Skip to content

Commit

Permalink
Selling joker, negative, ectoplasm, ankh, hex
Browse files Browse the repository at this point in the history
  • Loading branch information
imisaacwu committed Aug 7, 2024
1 parent b073eab commit 2e2ee0c
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default function App() {
<Joker {...j}/>
)}
</div>
<div id='joker-label' className='counter'>0/5</div>
<div id='joker-label' className='counter'>{`${game.jokers.length}/${game.stats.jokerSize}`}</div>
</div>
<div id='consumables' className='card-container'>
<div id='consumables-area' className='card-area'>
Expand Down
4 changes: 2 additions & 2 deletions src/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -429,15 +429,15 @@ 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',
description: 'Destroys /{orange}5/ random cards in hand, gain /{yellow}$20/',
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',
Expand Down
26 changes: 20 additions & 6 deletions src/GameState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
},
Expand Down Expand Up @@ -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':
Expand Down Expand Up @@ -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) => {
Expand Down
1 change: 0 additions & 1 deletion src/components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 5 additions & 4 deletions src/components/Consumable.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
34 changes: 30 additions & 4 deletions src/components/Consumable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -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 }
Expand Down
23 changes: 23 additions & 0 deletions src/components/Joker.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
13 changes: 8 additions & 5 deletions src/components/Joker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const images: Record<string, { default: string }> = 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)
Expand All @@ -33,9 +34,9 @@ export const Joker = ({id, joker, selected = false, ...props}: JokerInstance) =>
>
<img src={image} onClick={() => {
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} />
<div id='joker-description-outline'>
Expand All @@ -62,16 +63,18 @@ export const Joker = ({id, joker, selected = false, ...props}: JokerInstance) =>
<div id='joker-buy-button' onClick={() => {
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</div>
}
{!props.shopMode && selected &&
<div id='sell-joker' onClick={() => {
dispatch({type: 'stat', payload: {stat: 'money', amount: sellPrice}})
dispatch({type: 'discard'})
dispatch({type: 'removeJoker', payload: {card: self}})
}}>
SELL
<div id='joker-sell-price'>{`$${sellPrice}`}</div>
</div>
}
</div>
Expand Down

0 comments on commit 2e2ee0c

Please sign in to comment.