forked from mico/idle_moloch
162 lines
5.9 KiB
TypeScript
162 lines
5.9 KiB
TypeScript
import { useEffect, useMemo, useState } from 'react';
|
|
import { UnitType, usePlayer } from '../providers/PlayerProvider';
|
|
import styles from '../styles/Army.module.css';
|
|
import { toReadable } from './Counter';
|
|
|
|
const PRECISION = BigInt(10000);
|
|
const BASE_PRICE = BigInt(380000);
|
|
const PRICE_FACTOR = BigInt(11500);
|
|
const APPRENTICE_PROFIT = BigInt(61000);
|
|
const ANOINTED_PROFIT = BigInt(6 * 64000);
|
|
const CHAMPION_PROFIT = BigInt(BigInt(67000 * 61000 * 64000) / PRECISION / PRECISION);
|
|
|
|
function calculateUnitPrice(unit: UnitType, currentLevel: number, units: number) {
|
|
let rollingPriceCalculation = BigInt(unit + 1) * BASE_PRICE;
|
|
let price = BigInt(0);
|
|
|
|
// Each level costs 15% more than previous
|
|
for (let i = 0; i < currentLevel + units; i++) {
|
|
if (i >= currentLevel) {
|
|
price += rollingPriceCalculation;
|
|
}
|
|
rollingPriceCalculation = rollingPriceCalculation * PRICE_FACTOR / PRECISION;
|
|
}
|
|
return price;
|
|
}
|
|
|
|
function calculateProfitPerSecond(unit: UnitType, level: number) {
|
|
// Each next unit scales progressivelly better
|
|
switch (unit) {
|
|
case 0: return BigInt(level) * PRECISION
|
|
case 1: return BigInt(level) * APPRENTICE_PROFIT
|
|
case 2: return BigInt(level) * ANOINTED_PROFIT
|
|
case 3: return BigInt(level) * CHAMPION_PROFIT
|
|
}
|
|
}
|
|
|
|
const unitTypeToCss: Record<UnitType, string> = {
|
|
0: styles.moloch_denier,
|
|
1: styles.apprentice,
|
|
2: styles.anointed,
|
|
3: styles.champion
|
|
}
|
|
|
|
const unitTypeToName: Record<UnitType, string> = {
|
|
0: "Moloch denier",
|
|
1: "Apprentice",
|
|
2: "Anointed",
|
|
3: "Champion"
|
|
}
|
|
|
|
const defaultAvailabilityMap: Record<UnitType, boolean> = {
|
|
0: false,
|
|
1: false,
|
|
2: false,
|
|
3: false
|
|
}
|
|
|
|
const unitDiscoveredAt: Record<UnitType, bigint> = {
|
|
0: BigInt(0),
|
|
1: BigInt(2_000_0000),
|
|
2: BigInt(2_000_000_0000),
|
|
3: BigInt(200_000_000_0000)
|
|
}
|
|
const unitAvailableToDiscoverAt: Record<UnitType, bigint> = {
|
|
0: BigInt(0),
|
|
1: BigInt(1_000_0000),
|
|
2: BigInt(1_000_000_0000),
|
|
3: BigInt(100_000_000_0000),
|
|
}
|
|
|
|
interface UnitProps {
|
|
addUnit: (unitType: UnitType) => void;
|
|
unitType: UnitType;
|
|
canPurchase: boolean;
|
|
isShrouded: boolean;
|
|
n_units: number
|
|
}
|
|
|
|
const Unit = ({ addUnit, unitType, canPurchase, isShrouded, n_units }: UnitProps) => {
|
|
const [unitPrice, unitProfit] = useMemo(() => {
|
|
return [
|
|
toReadable(calculateUnitPrice(unitType, n_units, 1)) + " geld",
|
|
toReadable(calculateProfitPerSecond(unitType, n_units)) + " geld / sec"
|
|
]
|
|
}, [n_units, unitType]);
|
|
return <div onClick={() => addUnit(unitType)} className={`${styles.armyUnit} ${canPurchase ? "" : styles.isUnavailable}`}>
|
|
<div className={`
|
|
${unitTypeToCss[unitType]}
|
|
${styles.person}
|
|
${styles.static}
|
|
${isShrouded ? styles.isShrouded : ""}
|
|
`} />
|
|
<span className={`${styles.unitName} ${styles.uiElement}`}>{isShrouded ? "???????" : unitTypeToName[unitType]}</span>
|
|
{isShrouded ? null : <span className={`${styles.unitPrice} ${styles.uiElement}`}>{unitPrice}</span>}
|
|
{n_units > 0 ? <span className={`${styles.unitSupply} ${styles.uiElement}`}>{n_units}</span> : null}
|
|
{n_units > 0 ? <span className={`${styles.unitProfit} ${styles.uiElement}`}>{unitProfit}</span> : null}
|
|
</div>
|
|
}
|
|
|
|
const Army = () => {
|
|
const { army, addUnit, isRegistered, player, balance } = usePlayer()
|
|
const [canPurchase, setCanPurchase] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap);
|
|
const [isShrouded, setIsShrouded] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap);
|
|
const [canKnowAbout, setCanKnowAbout] = useState<Record<UnitType, boolean>>(defaultAvailabilityMap);
|
|
|
|
console.log(canPurchase, "\nshroud", isShrouded, "\ncanknowabout", canKnowAbout)
|
|
|
|
useEffect(() => {
|
|
if (isRegistered) {
|
|
const totalMinted = player?.total_minted ?? BigInt(0);
|
|
const n_units: Record<UnitType, number> = {
|
|
0: army?.moloch_denier.level ?? 0,
|
|
1: army?.apprentice.level ?? 0,
|
|
2: army?.anointed.level ?? 0,
|
|
3: army?.champion.level ?? 0,
|
|
}
|
|
const inShroud = {
|
|
0: totalMinted < unitDiscoveredAt[0],
|
|
1: totalMinted < unitDiscoveredAt[1],
|
|
2: totalMinted < unitDiscoveredAt[2],
|
|
3: totalMinted < unitDiscoveredAt[3],
|
|
}
|
|
const isKnown = {
|
|
0: totalMinted >= unitAvailableToDiscoverAt[0],
|
|
1: totalMinted >= unitAvailableToDiscoverAt[1],
|
|
2: totalMinted >= unitAvailableToDiscoverAt[2],
|
|
3: totalMinted >= unitAvailableToDiscoverAt[3],
|
|
}
|
|
const canActuallyBuy = {
|
|
0: balance >= calculateUnitPrice(0, n_units[0], 1) && isKnown[0] && !inShroud[0],
|
|
1: balance >= calculateUnitPrice(1, n_units[1], 1) && isKnown[1] && !inShroud[1],
|
|
2: balance >= calculateUnitPrice(2, n_units[2], 1) && isKnown[2] && !inShroud[2],
|
|
3: balance >= calculateUnitPrice(3, n_units[3], 1) && isKnown[3] && !inShroud[3],
|
|
};
|
|
setCanPurchase(canActuallyBuy)
|
|
setIsShrouded(inShroud)
|
|
setCanKnowAbout(isKnown)
|
|
} else {
|
|
setCanPurchase(defaultAvailabilityMap)
|
|
setIsShrouded(defaultAvailabilityMap)
|
|
setCanKnowAbout(defaultAvailabilityMap)
|
|
}
|
|
}, [
|
|
balance,
|
|
army,
|
|
isRegistered,
|
|
player?.total_minted
|
|
])
|
|
|
|
return <>
|
|
<div className={`${styles.tavern_keeper} ${styles.person} ${styles.static}`} />
|
|
<div className={styles.armyUnits}>
|
|
{canKnowAbout[0] && <Unit n_units={army?.moloch_denier.level ?? 0} addUnit={addUnit} unitType={0} canPurchase={canPurchase[0]} isShrouded={isShrouded[0]} />}
|
|
{canKnowAbout[1] && <Unit n_units={army?.apprentice.level ?? 0} addUnit={addUnit} unitType={1} canPurchase={canPurchase[1]} isShrouded={isShrouded[1]} />}
|
|
{canKnowAbout[2] && <Unit n_units={army?.anointed.level ?? 0} addUnit={addUnit} unitType={2} canPurchase={canPurchase[2]} isShrouded={isShrouded[2]} />}
|
|
{canKnowAbout[3] && <Unit n_units={army?.champion.level ?? 0} addUnit={addUnit} unitType={3} canPurchase={canPurchase[3]} isShrouded={isShrouded[3]} />}
|
|
</div>
|
|
</>
|
|
}
|
|
|
|
export default Army
|