This commit is contained in:
lubiana 2025-07-12 18:45:33 +02:00
parent db0673b77f
commit d45b7e48ca
Signed by: lubiana
SSH key fingerprint: SHA256:vW1EA0fRR3Fw+dD/sM0K+x3Il2gSry6YRYHqOeQwrfk
3 changed files with 24 additions and 8 deletions

View file

@ -20,10 +20,15 @@ const TIERS: Tier[] = [
{ name: 'Gold', unlockPrice: 15, buyPrice: 10, gubblePointChance: 0.1 }, { name: 'Gold', unlockPrice: 15, buyPrice: 10, gubblePointChance: 0.1 },
{ name: 'Platinum', unlockPrice: 30, buyPrice: 20, gubblePointChance: 0.1 }, { name: 'Platinum', unlockPrice: 30, buyPrice: 20, gubblePointChance: 0.1 },
{ name: 'Diamond', unlockPrice: 75, buyPrice: 50, gubblePointChance: 0.2 }, { name: 'Diamond', unlockPrice: 75, buyPrice: 50, gubblePointChance: 0.2 },
{ name: 'Master', unlockPrice: 750, buyPrice: 500, gubblePointChance: 0.2 }, { name: 'Legend', unlockPrice: 750, buyPrice: 500, gubblePointChance: 0.2 },
{ name: 'Legend', unlockPrice: 10000, buyPrice: 8000, gubblePointChance: 0.3 }, { name: 'Ultra', unlockPrice: 10000, buyPrice: 8000, gubblePointChance: 0.3 },
{ name: 'Ultimate', unlockPrice: 100000, buyPrice: 80000, gubblePointChance: 0.3 }, { name: 'Ultimate', unlockPrice: 100000, buyPrice: 80000, gubblePointChance: 0.3 },
{ name: 'Champion', unlockPrice: 5000000, buyPrice: 4000000, gubblePointChance: 0.4 }, { name: 'Champion', unlockPrice: 5000000, buyPrice: 4000000, gubblePointChance: 0.4 },
{ name: 'King', unlockPrice: 100000000, buyPrice: 80000000, gubblePointChance: 0.5 },
{ name: 'Queen', unlockPrice: 1000000000, buyPrice: 800000000, gubblePointChance: 0.6 },
{ name: 'Emperor', unlockPrice: 10000000000, buyPrice: 8000000000, gubblePointChance: 0.7 },
{ name: 'God', unlockPrice: 100000000000, buyPrice: 80000000000, gubblePointChance: 0.8 },
{ name: 'Goddess', unlockPrice: 1000000000000, buyPrice: 800000000000, gubblePointChance: 0.9 },
]; ];
const START_MONEY = 6; const START_MONEY = 6;
@ -47,7 +52,7 @@ function App() {
}[]>([]); }[]>([]);
// --- Gubble Store State --- // --- Gubble Store State ---
const [isStoreOpen, setIsStoreOpen] = useState(false); const [isStoreOpen, setIsStoreOpen] = useState(false);
const [upgrades, setUpgrades] = useState<Upgrades>({ evenDouble: false, oddDouble: false, allTripple: false, gubbleDouble: false }); const [upgrades, setUpgrades] = useState<Upgrades>({ evenDouble: false, oddDouble: false, allTripple: false, gubbleDouble: false, addFourthNumber: false });
const [upgradeBought, setUpgradeBought] = useState(false); const [upgradeBought, setUpgradeBought] = useState(false);
// --- Tier Unlock Logic --- // --- Tier Unlock Logic ---
@ -64,9 +69,10 @@ function App() {
setMoney(m => { setMoney(m => {
if (m < tier.buyPrice) return m; if (m < tier.buyPrice) return m;
if (!unlockedTiers.includes(tier.name)) return m; if (!unlockedTiers.includes(tier.name)) return m;
// Generate 3 unique winning numbers (1-9) // Generate unique winning numbers
const winningNumbers: number[] = []; const winningNumbers: number[] = [];
while (winningNumbers.length < 3) { const winningCount = upgrades.addFourthNumber ? 4 : 3;
while (winningNumbers.length < winningCount) {
const n = Math.floor(Math.random() * 9) + 1; const n = Math.floor(Math.random() * 9) + 1;
if (!winningNumbers.includes(n)) winningNumbers.push(n); if (!winningNumbers.includes(n)) winningNumbers.push(n);
} }
@ -79,7 +85,7 @@ function App() {
]); ]);
return m - tier.buyPrice; return m - tier.buyPrice;
}); });
}, [unlockedTiers]); }, [unlockedTiers, upgrades]);
// --- Gubble Store Logic --- // --- Gubble Store Logic ---
const handleBuyUpgrade = useCallback((upgrade: keyof Upgrades, cost: number) => { const handleBuyUpgrade = useCallback((upgrade: keyof Upgrades, cost: number) => {

View file

@ -5,6 +5,7 @@ type Upgrades = {
oddDouble: boolean; oddDouble: boolean;
allTripple: boolean; allTripple: boolean;
gubbleDouble: boolean; gubbleDouble: boolean;
addFourthNumber: boolean;
}; };
type GubbleStoreProps = { type GubbleStoreProps = {
@ -20,6 +21,7 @@ const UPGRADE_LIST: { key: keyof Upgrades; label: string; cost: number; descript
{ key: 'oddDouble', label: 'Double Odd Winnings', cost: 60, description: 'Double winnings from odd numbers.' }, { key: 'oddDouble', label: 'Double Odd Winnings', cost: 60, description: 'Double winnings from odd numbers.' },
{ key: 'allTripple', label: 'Tripple All Winnings', cost: 150, description: 'Tripple all winnings.' }, { key: 'allTripple', label: 'Tripple All Winnings', cost: 150, description: 'Tripple all winnings.' },
{ key: 'gubbleDouble', label: 'Double Gubble Point Gains', cost: 50, description: 'Double gubble point gains.' }, { key: 'gubbleDouble', label: 'Double Gubble Point Gains', cost: 50, description: 'Double gubble point gains.' },
{ key: 'addFourthNumber', label: 'Add Fourth Winning Number', cost: 200, description: 'Adds a fourth winning number to each card.' },
]; ];
const GubbleStore: React.FC<GubbleStoreProps> = ({ isOpen, onClose, gubblePoints, upgrades, onBuyUpgrade }) => { const GubbleStore: React.FC<GubbleStoreProps> = ({ isOpen, onClose, gubblePoints, upgrades, onBuyUpgrade }) => {

View file

@ -11,6 +11,10 @@ type TierCardProps = {
}; };
const TierCard: React.FC<TierCardProps> = React.memo(({ tier, unlocked, money, onUnlock, onBuy }) => { const TierCard: React.FC<TierCardProps> = React.memo(({ tier, unlocked, money, onUnlock, onBuy }) => {
const formatter = Intl.NumberFormat(
'en',
{ 'notation': 'compact' }
)
return ( return (
<button <button
className={`rounded-lg shadow p-2 flex flex-col items-center w-32 font-bold text-white mb-1 disabled:opacity-50 ${ className={`rounded-lg shadow p-2 flex flex-col items-center w-32 font-bold text-white mb-1 disabled:opacity-50 ${
@ -22,8 +26,12 @@ const TierCard: React.FC<TierCardProps> = React.memo(({ tier, unlocked, money, o
onClick={() => (!unlocked ? onUnlock(tier) : onBuy(tier))} onClick={() => (!unlocked ? onUnlock(tier) : onBuy(tier))}
> >
<div className="text-lg font-semibold mb-1">{tier.name}</div> <div className="text-lg font-semibold mb-1">{tier.name}</div>
<div className="text-gray-500 text-xs mb-1">Unlock: ${tier.unlockPrice}</div> <div className="text-gray-500 text-xs mb-1">
<div className="text-gray-500 text-xs mb-1">Buy: ${tier.buyPrice}</div> Unlock: ${formatter.format(tier.unlockPrice)}
</div>
<div className="text-gray-500 text-xs mb-1">
Buy: ${formatter.format(tier.buyPrice)}
</div>
<div className="text-gray-500 text-xs mb-1">Point Chance: {tier.gubblePointChance * 100}%</div> <div className="text-gray-500 text-xs mb-1">Point Chance: {tier.gubblePointChance * 100}%</div>
<div> <div>
{!unlocked ? 'Unlock' : 'Buy Card'} {!unlocked ? 'Unlock' : 'Buy Card'}