Better UX: player now can add units wven if funds are not yet minted

This commit is contained in:
mic0 2024-10-26 13:49:29 +02:00
parent fefa2641e4
commit 84c0aeff03
Signed by: mico
GPG Key ID: A3F8023524CF1C8D
3 changed files with 26 additions and 14 deletions

View File

@ -1,7 +1,7 @@
import { useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { UnitType, usePlayer } from '../providers/PlayerProvider'; import { UnitType, usePlayer } from '../providers/PlayerProvider';
import styles from '../styles/Army.module.css'; import styles from '../styles/Army.module.css';
import { toReadable } from './Counter'; import { calculateBalance, toReadable } from './Counter';
const PRECISION = BigInt(10000); const PRECISION = BigInt(10000);
const BASE_PRICE = BigInt(380000); const BASE_PRICE = BigInt(380000);
@ -102,10 +102,9 @@ const Army = () => {
const [canPurchase, setCanPurchase] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap); const [canPurchase, setCanPurchase] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap);
const [isShrouded, setIsShrouded] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap); const [isShrouded, setIsShrouded] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap);
const [canKnowAbout, setCanKnowAbout] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap); const [canKnowAbout, setCanKnowAbout] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap);
const balanceCount = useRef(BigInt(balance ?? 0))
console.log(canPurchase, "\nshroud", isShrouded, "\ncanknowabout", canKnowAbout) const setAvailabilities = useCallback(() => {
useEffect(() => {
if (isRegistered) { if (isRegistered) {
const totalMinted = player?.total_minted ?? BigInt(0); const totalMinted = player?.total_minted ?? BigInt(0);
const n_units: Record<UnitType, number> = { const n_units: Record<UnitType, number> = {
@ -127,10 +126,10 @@ const Army = () => {
3: totalMinted >= unitAvailableToDiscoverAt[3], 3: totalMinted >= unitAvailableToDiscoverAt[3],
} }
const canActuallyBuy = { const canActuallyBuy = {
0: balance >= calculateUnitPrice(0, n_units[0], 1) && isKnown[0] && !inShroud[0], 0: balanceCount.current >= calculateUnitPrice(0, n_units[0], 1) && isKnown[0] && !inShroud[0],
1: balance >= calculateUnitPrice(1, n_units[1], 1) && isKnown[1] && !inShroud[1], 1: balanceCount.current >= calculateUnitPrice(1, n_units[1], 1) && isKnown[1] && !inShroud[1],
2: balance >= calculateUnitPrice(2, n_units[2], 1) && isKnown[2] && !inShroud[2], 2: balanceCount.current >= calculateUnitPrice(2, n_units[2], 1) && isKnown[2] && !inShroud[2],
3: balance >= calculateUnitPrice(3, n_units[3], 1) && isKnown[3] && !inShroud[3], 3: balanceCount.current >= calculateUnitPrice(3, n_units[3], 1) && isKnown[3] && !inShroud[3],
}; };
setCanPurchase(canActuallyBuy) setCanPurchase(canActuallyBuy)
setIsShrouded(inShroud) setIsShrouded(inShroud)
@ -141,12 +140,23 @@ const Army = () => {
setCanKnowAbout(defaultAvailabilityMap) setCanKnowAbout(defaultAvailabilityMap)
} }
}, [ }, [
balance,
army, army,
isRegistered, isRegistered,
player?.total_minted player?.total_minted
]) ])
useEffect(() => {
const tickInterval = setInterval(() => {
balanceCount.current = calculateBalance(
balance ?? BigInt(0),
army?.profit_per_second ?? BigInt(0),
player?.last_raided_at ?? BigInt(0)
);
setAvailabilities()
}, 100);
return () => clearInterval(tickInterval)
}, [balance, army?.profit_per_second, player?.last_raided_at, setAvailabilities])
return <> return <>
<div className={`${styles.tavern_keeper} ${styles.person} ${styles.static}`} /> <div className={`${styles.tavern_keeper} ${styles.person} ${styles.static}`} />
<div className={styles.armyUnits}> <div className={styles.armyUnits}>

View File

@ -2,7 +2,7 @@ import { useEffect, useReducer, useRef } from "react";
import { usePlayer } from "../providers/PlayerProvider" import { usePlayer } from "../providers/PlayerProvider"
import styles from "../styles/Header.module.css" import styles from "../styles/Header.module.css"
const calculateBalance = (balance: bigint, perSecond: bigint, lastRaidedAt: bigint) => { export const calculateBalance = (balance: bigint, perSecond: bigint, lastRaidedAt: bigint) => {
// convert to milliseconds trick so we get a more smooth counter // convert to milliseconds trick so we get a more smooth counter
const millisecondsSinceLastRaid = const millisecondsSinceLastRaid =
(new Date()).getTime() - parseInt(lastRaidedAt.toString()) * 1000; (new Date()).getTime() - parseInt(lastRaidedAt.toString()) * 1000;

View File

@ -61,14 +61,13 @@ contract RaidGeld is ERC20, Ownable {
// Helper so we can use it when buying units too // Helper so we can use it when buying units too
function performRaid(address player) private { function performRaid(address player) private {
uint256 time_past = block.timestamp - players[player].last_raided_at; uint256 time_past = block.timestamp - players[player].last_raided_at;
uint256 new_geld = armies[player].profit_per_second * time_past; uint256 new_geld = armies[player].profit_per_second * time_past;
// TODO: Pink noise, make it so sometimes its better than expected // TODO: Pink noise, make it so sometimes its better than expected
_mint(player, new_geld); _mint(player, new_geld);
players[player].last_raided_at = block.timestamp; players[player].last_raided_at = block.timestamp;
players[player].total_minted = new_geld; players[player].total_minted += new_geld;
} }
// Function to get Player struct // Function to get Player struct
@ -108,8 +107,11 @@ contract RaidGeld is ERC20, Ownable {
uint256 cost = RaidGeldUtils.calculateUnitPrice(unit, currentLevel, n_units); uint256 cost = RaidGeldUtils.calculateUnitPrice(unit, currentLevel, n_units);
// First trigger a raid so player receives what he is due at to this moment // First trigger a raid so player receives what he is due at to this moment
uint256 time_past = block.timestamp - players[msg.sender].last_raided_at;
uint256 new_geld = armies[msg.sender].profit_per_second * time_past;
require(balanceOf(msg.sender) + new_geld > cost, "Not enough GELD to add this unit");
performRaid(msg.sender); performRaid(msg.sender);
require(balanceOf(msg.sender) > cost, "Not enough GELD to add this much");
// TODO: Since we are first minting then burning the token, this could be simplified // TODO: Since we are first minting then burning the token, this could be simplified
// by first calculating the difference and then minting / burning in just one operation // by first calculating the difference and then minting / burning in just one operation