From 32bc1177bacf67d475f6f52661448e97be28d6a2 Mon Sep 17 00:00:00 2001
From: Mitja Belak
Date: Thu, 31 Oct 2024 21:01:45 +0100
Subject: [PATCH 1/3] Added LastBossResult struct
---
app/src/components/BossInfo.tsx | 2 +-
app/src/components/BossOutcomeModal.tsx | 31 +++++++++++++++++++++++++
app/src/providers/PlayerProvider.tsx | 23 +++++++++++++-----
app/src/wagmi.ts | 2 --
src/RaidGeld.sol | 24 ++++++++++++++++++-
src/RaidGeldStructs.sol | 8 +++++++
test/RaidGeld.t.sol | 19 ++++++++++++++-
7 files changed, 98 insertions(+), 11 deletions(-)
create mode 100644 app/src/components/BossOutcomeModal.tsx
diff --git a/app/src/components/BossInfo.tsx b/app/src/components/BossInfo.tsx
index eede405..4ee06ae 100644
--- a/app/src/components/BossInfo.tsx
+++ b/app/src/components/BossInfo.tsx
@@ -24,7 +24,7 @@ const bossToName: Record = {
6: "Greedy",
}
-const bossToReward: Record = {
+export const bossToReward: Record = {
0: BigInt("200000000000000000"),
1: BigInt("28274420000000000000"),
2: BigInt("174191628800000000000"),
diff --git a/app/src/components/BossOutcomeModal.tsx b/app/src/components/BossOutcomeModal.tsx
new file mode 100644
index 0000000..3f1fd33
--- /dev/null
+++ b/app/src/components/BossOutcomeModal.tsx
@@ -0,0 +1,31 @@
+import { formatUnits } from "viem";
+import { BossLevel, usePlayer } from "../providers/PlayerProvider";
+import styles from "../styles/Modal.module.css";
+import { bossToReward } from "./BossInfo";
+
+interface BossOutcomeModalProps {
+ setIsOpen: (val: boolean) => void,
+ outcome: boolean,
+ ascended: boolean,
+ bossLevel: BossLevel
+}
+
+const BossOutcomeModal = ({ setIsOpen, outcome, ascended, bossLevel }: BossOutcomeModalProps) => {
+ const text = outcome ? "and you won! 🤩" : "and you lost 😔";
+ const rewardAmount = parseFloat(parseFloat(formatUnits(bossToReward[bossLevel], 18).toString()).toFixed(4));
+ const rewardText =
+ ascended ? You won {rewardAmount} RGCVII and ASCENDED!!! . This means you beat the bosses and gained a Prestige level . Your GELD is now forfeit, but your legend lives on.
+ : outcome ? You won {rewardAmount} RGCVII
+ : Your GELD is now forfeit. Try again 💪 we know you can do it!
+
+ return
+
You battled a boss
+
{text}
+ {rewardText}
+
+ setIsOpen(false)}>Proceed
+
+
+}
+
+export default BossOutcomeModal
diff --git a/app/src/providers/PlayerProvider.tsx b/app/src/providers/PlayerProvider.tsx
index 6941033..8562031 100644
--- a/app/src/providers/PlayerProvider.tsx
+++ b/app/src/providers/PlayerProvider.tsx
@@ -61,6 +61,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
const { address, isConnected } = useAccount();
const { writeContract, error } = useWriteContract();
const [[txHash, callbackFn], setHashAndCallback] = useState<[Hash | null, () => void]>([null, () => { }])
+ const [bossJustBattled, setBossJustBattled] = useState(false);
useEffect(() => {
console.warn(error)
@@ -133,11 +134,12 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
abi,
address: contractAddress,
functionName: 'register_eth',
- value: parseEther("0.0005"),
+ value: parseEther("0.00005"),
}, {
onSuccess: (hash) => {
setHashAndCallback([hash, resetHashAndCallback])
- }
+ },
+ onError: () => resetHashAndCallback()
})
} else if (arg === "RGCVII") {
writeContract({
@@ -156,10 +158,12 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
}, {
onSuccess: (hash) => {
setHashAndCallback([hash, resetHashAndCallback])
- }
+ },
+ onError: () => resetHashAndCallback()
})
])
- }
+ },
+ onError: () => resetHashAndCallback()
});
}
}, [writeContract, resetHashAndCallback])
@@ -172,7 +176,8 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
}, {
onSuccess: (hash) => {
setHashAndCallback([hash, resetHashAndCallback])
- }
+ },
+ onError: () => resetHashAndCallback()
})
}, [writeContract, resetHashAndCallback])
@@ -190,8 +195,13 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
abi,
address: contractAddress,
functionName: 'battle_with_boss',
+ }, {
+ onSuccess: (hash) => {
+ setHashAndCallback([hash, () => resetHashAndCallback()])
+ },
+ onError: () => resetHashAndCallback()
})
- }, [writeContract])
+ }, [writeContract, resetHashAndCallback])
return (
{
}}>
{children}
{txHash && }
+ {bossJustBattled && }
);
}
diff --git a/app/src/wagmi.ts b/app/src/wagmi.ts
index 332811c..9cf52cd 100644
--- a/app/src/wagmi.ts
+++ b/app/src/wagmi.ts
@@ -2,7 +2,6 @@ import { getDefaultConfig } from '@rainbow-me/rainbowkit';
import {
base,
baseSepolia,
- sepolia,
foundry
} from 'wagmi/chains';
@@ -13,7 +12,6 @@ export const config = getDefaultConfig({
baseSepolia,
foundry,
base,
- ...(process.env.NEXT_PUBLIC_ENABLE_TESTNETS === 'true' ? [sepolia] : []),
],
ssr: true,
});
diff --git a/src/RaidGeld.sol b/src/RaidGeld.sol
index 6f69b2e..ed70fa9 100644
--- a/src/RaidGeld.sol
+++ b/src/RaidGeld.sol
@@ -5,7 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import {RaidGeldUtils} from "../src/RaidGeldUtils.sol";
-import {Army, Player, Raider, Boss} from "../src/RaidGeldStructs.sol";
+import {Army, Player, Raider, Boss, LastBossResult} from "../src/RaidGeldStructs.sol";
import "../src/Constants.sol";
contract RaidGeld is ERC20, Ownable, Constants {
@@ -16,6 +16,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
mapping(address => Player) private players;
mapping(address => Army) private armies;
mapping(address => Boss) private bosses;
+ mapping(address => LastBossResult) private lastBossResults;
// WETH
IWETH public immutable weth = IWETH(WETH);
@@ -44,6 +45,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
event DaoTokenBuyInAmountSet(address indexed owner, uint256 oldAmount, uint256 newAmount);
event PrestigeGained(address indexed player, uint32 prestigeLevel);
event BossDefeated(address indexed player, uint8 bossLevel, uint256 earnings);
+ event BossBattle(address indexed player, uint8 bossLevel, bool hasWon);
// Modifier for functions that should only be available to registered players
modifier onlyPlayer() {
@@ -106,6 +108,9 @@ contract RaidGeld is ERC20, Ownable, Constants {
profit_per_second: 0
});
bosses[_playerAddress] = Boss({level: 0, variants: RaidGeldUtils.generate_boss_variants(block.prevrandao)});
+
+ // dont change lastBossResult
+ // that only changes after boss battles and on init
}
// New player want to register with ETH
@@ -171,6 +176,11 @@ contract RaidGeld is ERC20, Ownable, Constants {
return bosses[addr];
}
+ // Function to get the Boss struct
+ function getLastBossResult(address addr) public view returns (LastBossResult memory) {
+ return lastBossResults[addr];
+ }
+
// Quick fn to check if user is registered
function isRegistered(address addr) public view returns (bool) {
return players[addr].created_at != 0;
@@ -248,6 +258,14 @@ contract RaidGeld is ERC20, Ownable, Constants {
? RaidGeldUtils.getBossPower(boss_to_attack.level)
: balanceOf(msg.sender);
bool hasWonBattle = RaidGeldUtils.calculateBossFight(boss_to_attack.level, geld_to_burn, block.prevrandao);
+ emit BossBattle(msg.sender, boss_to_attack.level, hasWonBattle);
+ lastBossResults[msg.sender] = LastBossResult({
+ battled_at: block.timestamp,
+ level: boss_to_attack.level,
+ variant: boss_to_attack.variants[boss_to_attack.level],
+ prestigeGained: false,
+ reward: 0
+ });
if (hasWonBattle) {
// Burn geld, send some sweet DAO Token and continue
_burn(msg.sender, geld_to_burn);
@@ -256,11 +274,14 @@ contract RaidGeld is ERC20, Ownable, Constants {
daoToken.transfer(msg.sender, reward);
emit BossDefeated(msg.sender, boss_to_attack.level, reward);
+ lastBossResults[msg.sender].reward = reward;
+
if (boss_to_attack.level == 6) {
// User ascends! Moloch is defeated, user can start a new run
players[msg.sender].prestige_level += 1;
emit PrestigeGained(msg.sender, players[msg.sender].prestige_level);
player_dies(msg.sender);
+ lastBossResults[msg.sender].prestigeGained = true;
return [hasWonBattle, true /* New prestige level! */ ];
} else {
// else go to next boss
@@ -268,6 +289,7 @@ contract RaidGeld is ERC20, Ownable, Constants {
}
} else {
// Whoops u died, boss defeated you
+ lastBossResults[msg.sender].reward = 0;
player_dies(msg.sender);
}
return [hasWonBattle, false /* hasnt gotten prestige level */ ];
diff --git a/src/RaidGeldStructs.sol b/src/RaidGeldStructs.sol
index f30deed..e045916 100644
--- a/src/RaidGeldStructs.sol
+++ b/src/RaidGeldStructs.sol
@@ -28,3 +28,11 @@ struct Boss {
uint8 level;
uint8[7] variants;
}
+
+struct LastBossResult {
+ uint256 battled_at;
+ uint256 reward;
+ uint8 level;
+ uint8 variant;
+ bool prestigeGained;
+}
diff --git a/test/RaidGeld.t.sol b/test/RaidGeld.t.sol
index 1d32a09..54dda56 100644
--- a/test/RaidGeld.t.sol
+++ b/test/RaidGeld.t.sol
@@ -3,7 +3,7 @@ pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import {stdStorage, StdStorage} from "forge-std/Test.sol";
-import {RaidGeld, Army, Player, Boss} from "../src/RaidGeld.sol";
+import {RaidGeld, Army, Player, Boss, LastBossResult} from "../src/RaidGeld.sol";
import "../src/RaidGeldUtils.sol";
import {Constants} from "../src/Constants.sol";
@@ -283,6 +283,13 @@ contract raid_geldTest is Test, Constants {
uint256 afterBossDaoBalance = raid_geld.daoToken().balanceOf(player1);
uint256 afterBossContractBalance = raid_geld.daoToken().balanceOf(address(raid_geld));
+ LastBossResult memory bossResult = raid_geld.getLastBossResult(player1);
+
+ assertEq(bossResult.battled_at, block.timestamp);
+ assertEq(bossResult.reward, afterBossDaoBalance - initialDaoBalance);
+ assertEq(bossResult.level, boss.level);
+ assertEq(bossResult.variant, boss.variants[boss.level]);
+ assertEq(bossResult.prestigeGained, false);
// User should receive funs, contract should lose them
assertLt(initialDaoBalance, afterBossDaoBalance);
@@ -306,6 +313,7 @@ contract raid_geldTest is Test, Constants {
registerPlayerWithDaoToken();
raid_geld.addUnit(0, 1);
+ Boss memory boss = raid_geld.getBoss(player1);
bool[2] memory results = raid_geld.battle_with_boss();
// Should lose with just starting GELD
assertEq(results[0], false);
@@ -321,6 +329,13 @@ contract raid_geldTest is Test, Constants {
assertEq(raid_geld.balanceOf(player1), 0);
// Units should reset
assertEq(army.moloch_denier.level, 0);
+
+ LastBossResult memory bossResult = raid_geld.getLastBossResult(player1);
+ assertEq(bossResult.battled_at, block.timestamp);
+ assertEq(bossResult.reward, 0);
+ assertEq(bossResult.level, boss.level);
+ assertEq(bossResult.variant, boss.variants[boss.level]);
+ assertEq(bossResult.prestigeGained, false);
}
function test_08_player_who_lost_can_restart() public {
@@ -388,6 +403,8 @@ contract raid_geldTest is Test, Constants {
if (results[0] == true && results[1] == true) {
success = true;
Player memory player = raid_geld.getPlayer(player1);
+ LastBossResult memory bossResult = raid_geld.getLastBossResult(player1);
+ assertEq(bossResult.prestigeGained, true);
vm.assertEq(player.prestige_level, 1);
vm.assertEq(player.n_runs, tries);
break;
From e46d6991a4659815f8230928f621489e1666265b Mon Sep 17 00:00:00 2001
From: Mitja Belak
Date: Thu, 31 Oct 2024 22:09:39 +0100
Subject: [PATCH 2/3] Adds overlays for modal, adds MAX chance geld required
---
app/src/components/BossInfo.tsx | 10 +++---
app/src/components/BossOutcomeModal.tsx | 36 ++++++++++++-------
app/src/components/RegistrationModal.tsx | 7 ++--
app/src/providers/PlayerProvider.tsx | 45 +++++++++++++++++++++---
app/src/styles/Modal.module.css | 35 ++++++++++++++++++
5 files changed, 109 insertions(+), 24 deletions(-)
diff --git a/app/src/components/BossInfo.tsx b/app/src/components/BossInfo.tsx
index 4ee06ae..c8f023e 100644
--- a/app/src/components/BossInfo.tsx
+++ b/app/src/components/BossInfo.tsx
@@ -2,7 +2,7 @@ import { formatUnits } from "viem"
import { BossLevel, usePlayer } from "../providers/PlayerProvider"
import styles from "../styles/Info.module.css"
import { useEffect, useReducer, useRef } from "react"
-import { calculateBalance } from "./Counter"
+import { calculateBalance, toReadable } from "./Counter"
export const bossLevelToClass: Record = {
0: styles.boss0,
@@ -14,7 +14,7 @@ export const bossLevelToClass: Record = {
6: styles.boss6,
}
-const bossToName: Record = {
+export const bossToName: Record = {
0: "Gluttonous",
1: "Slothful",
2: "Lusty",
@@ -70,11 +70,12 @@ const BossInfo = () => {
const [, render] = useReducer(p => !p, false);
useEffect(() => {
const tickInterval = setInterval(() => {
- chanceToDefeat.current = getBossChanceToDefeat(boss?.level ?? 0, calculateBalance(
+ const _balance = calculateBalance(
balance ?? BigInt(0),
army?.profit_per_second ?? BigInt(0),
player?.last_raided_at ?? BigInt(0)
- ))
+ );
+ chanceToDefeat.current = getBossChanceToDefeat(boss?.level ?? 0, _balance)
render();
}, 100);
return () => clearInterval(tickInterval)
@@ -86,6 +87,7 @@ const BossInfo = () => {
{parseFloat((chanceToDefeat.current * 100).toFixed(2))} % to slay {" "}
{chanceToDefeat.current == maxChance ? (MAXED) : (Max {maxChance * 100}%) }
+ {toReadable(bossToBossPower[boss?.level ?? 0])} GELD = max chance
}
diff --git a/app/src/components/BossOutcomeModal.tsx b/app/src/components/BossOutcomeModal.tsx
index 3f1fd33..793b082 100644
--- a/app/src/components/BossOutcomeModal.tsx
+++ b/app/src/components/BossOutcomeModal.tsx
@@ -1,29 +1,39 @@
import { formatUnits } from "viem";
-import { BossLevel, usePlayer } from "../providers/PlayerProvider";
+import { usePlayer } from "../providers/PlayerProvider";
import styles from "../styles/Modal.module.css";
-import { bossToReward } from "./BossInfo";
+import bgStyles from "../styles/Background.module.css";
+import { bossToName, bossToReward } from "./BossInfo";
+import { bossLevelToClass } from "./Boss";
+
interface BossOutcomeModalProps {
setIsOpen: (val: boolean) => void,
- outcome: boolean,
- ascended: boolean,
- bossLevel: BossLevel
}
-const BossOutcomeModal = ({ setIsOpen, outcome, ascended, bossLevel }: BossOutcomeModalProps) => {
- const text = outcome ? "and you won! 🤩" : "and you lost 😔";
- const rewardAmount = parseFloat(parseFloat(formatUnits(bossToReward[bossLevel], 18).toString()).toFixed(4));
+const BossOutcomeModal = ({ setIsOpen }: BossOutcomeModalProps) => {
+ const { lastBossResult } = usePlayer();
+ if (lastBossResult == null) return null;
+
+ const outcome = lastBossResult.reward != BigInt(0);
+ const ascended = lastBossResult.prestigeGained;
+
+ const text = outcome ? and you won! 🤩 : and you lost 😔 ;
+ const rewardAmount = parseFloat(parseFloat(formatUnits(bossToReward[lastBossResult.level], 18).toString()).toFixed(4));
const rewardText =
ascended ? You won {rewardAmount} RGCVII and ASCENDED!!! . This means you beat the bosses and gained a Prestige level . Your GELD is now forfeit, but your legend lives on.
: outcome ? You won {rewardAmount} RGCVII
- : Your GELD is now forfeit. Try again 💪 we know you can do it!
+ : Your GELD is now forfeit. Try again 💪 we know you can do it!
- return
-
You battled a boss
-
{text}
+ const bossName = bossToName[lastBossResult.variant];
+ const bossClass = bossLevelToClass[lastBossResult.variant];
+
+ return
+
You battled {bossName} Moloch!
+
+
{text}
{rewardText}
- setIsOpen(false)}>Proceed
+ setIsOpen(false)}>Onward!
}
diff --git a/app/src/components/RegistrationModal.tsx b/app/src/components/RegistrationModal.tsx
index 540d8ab..279fdad 100644
--- a/app/src/components/RegistrationModal.tsx
+++ b/app/src/components/RegistrationModal.tsx
@@ -1,6 +1,7 @@
import { useCallback } from "react";
import { usePlayer } from "../providers/PlayerProvider";
import styles from "../styles/Modal.module.css";
+import bgStyles from "../styles/Background.module.css";
interface RegistrationModalProps {
isOpen: boolean;
@@ -14,13 +15,13 @@ const RegistrationModal = ({ isOpen, setIsOpen }: RegistrationModalProps) => {
setIsOpen(false);
}, [register, setIsOpen])
if (!isOpen) return null;
- return
-
Insert coins to continue
+ return
+
Insert coins to continue
onRegister("RGCVII")}>500 RGCVII
onRegister("ETH")}>0.0005 ETH
-
+
}
export default RegistrationModal
diff --git a/app/src/providers/PlayerProvider.tsx b/app/src/providers/PlayerProvider.tsx
index 8562031..fbcdd9d 100644
--- a/app/src/providers/PlayerProvider.tsx
+++ b/app/src/providers/PlayerProvider.tsx
@@ -1,9 +1,11 @@
-import React, { createContext, ReactNode, useCallback, useContext, useEffect, useState } from 'react'
+import React, { createContext, ReactNode, useCallback, useContext, useEffect, useRef, useState } from 'react'
import { useAccount, useReadContract, useWriteContract } from 'wagmi'
import contractAbi from "../../../out/RaidGeld.sol/RaidGeld.json"
import { Hash, parseEther } from 'viem'
import contracts from '../../contract_address'
import WaitingForTxModal from '../components/WaitingForTxModal'
+import BossOutcomeModal from '../components/BossOutcomeModal'
+import styles from "../styles/Background.module.css"
const { contractAddress, daoTokenAddress } = contracts
const abi = contractAbi.abi
@@ -33,11 +35,20 @@ export interface Boss {
variants: [BossLevel, BossLevel, BossLevel, BossLevel, BossLevel, BossLevel, BossLevel]
}
+export interface LastBossResult {
+ level: BossLevel;
+ variant: BossLevel;
+ battled_at: bigint;
+ reward: bigint;
+ prestigeGained: boolean;
+}
+
export interface PlayerContextType {
isRegistered: boolean,
player: null | Player,
army: null | Army,
boss: null | Boss,
+ lastBossResult: null | LastBossResult,
balance: bigint,
register: (arg: "ETH" | "RGCVII") => void,
raid: () => void,
@@ -50,6 +61,7 @@ const PlayerContext = createContext
({
player: null,
army: null,
boss: null,
+ lastBossResult: null,
balance: BigInt(0),
register: () => { },
raid: () => { },
@@ -61,7 +73,8 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
const { address, isConnected } = useAccount();
const { writeContract, error } = useWriteContract();
const [[txHash, callbackFn], setHashAndCallback] = useState<[Hash | null, () => void]>([null, () => { }])
- const [bossJustBattled, setBossJustBattled] = useState(false);
+ const [bossBattledModalOpen, setBossBattlesModalOpen] = useState(false);
+ const hasFetchedLastBossFirstTime = useRef(false);
useEffect(() => {
console.warn(error)
@@ -126,6 +139,17 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
}
});
+ const { data: lastBossResult } = useReadContract({
+ address: contractAddress,
+ abi,
+ functionName: 'getLastBossResult',
+ args: [address],
+ query: {
+ enabled: isConnected,
+ refetchInterval: 15
+ }
+ });
+
console.log(balance, player, army, boss)
const register = useCallback((arg: "RGCVII" | "ETH") => {
@@ -203,6 +227,16 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
})
}, [writeContract, resetHashAndCallback])
+ useEffect(() => {
+ if (lastBossResult != null) {
+ if (hasFetchedLastBossFirstTime.current) {
+ setBossBattlesModalOpen(true);
+ } else {
+ hasFetchedLastBossFirstTime.current = true;
+ }
+ }
+ }, [lastBossResult])
+
return (
{
army: army as Army,
boss: boss as Boss,
balance: balance as bigint,
+ lastBossResult: lastBossResult as LastBossResult,
register,
raid,
addUnit,
battleWithBoss
}}>
{children}
- {txHash && }
- {bossJustBattled && }
+
+ {txHash && }
+ {bossBattledModalOpen && }
+
);
}
diff --git a/app/src/styles/Modal.module.css b/app/src/styles/Modal.module.css
index a1ec842..9ed569c 100644
--- a/app/src/styles/Modal.module.css
+++ b/app/src/styles/Modal.module.css
@@ -47,6 +47,41 @@
margin-bottom: 0;
}
}
+.bossModal {
+ padding: 32px;
+ z-index: 3;
+ max-width: 100%;
+ width: 500px;
+ text-align: center;
+ margin-top: 50px;
+ .outcome {
+ font-size: 1.7rem;
+ }
+ .image {
+ position: relative;
+ margin: 0 auto;
+ top: 0;
+ &::after {
+ display: none;
+ }
+ }
+ & p {
+ margin: 0.5rem 0;
+ }
+ & button {
+ margin: 1rem;
+ }
+ .lost {
+ color: var(--accent-color);
+ }
+ .won {
+ color: var(--hover-color);
+ }
+ .lost,
+ .won {
+ font-size: 2rem;
+ }
+}
@keyframes spin {
0% {
From d9e8c2f8fd5634fbe60b7b88dae8fa06e3fc5c6a Mon Sep 17 00:00:00 2001
From: Mitja Belak
Date: Thu, 31 Oct 2024 22:40:18 +0100
Subject: [PATCH 3/3] QoL updates
---
app/src/components/BossInfo.tsx | 2 +-
app/src/components/Counter.tsx | 4 ++--
app/src/components/PixelatedQuote.tsx | 4 ++--
app/src/components/RegistrationModal.tsx | 3 ++-
app/src/components/Scene.tsx | 2 +-
app/src/pages/_app.tsx | 1 +
app/src/styles/Background.module.css | 4 ++--
app/src/styles/Modal.module.css | 24 ++++++++++++++++++++++++
8 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/app/src/components/BossInfo.tsx b/app/src/components/BossInfo.tsx
index c8f023e..a17e8be 100644
--- a/app/src/components/BossInfo.tsx
+++ b/app/src/components/BossInfo.tsx
@@ -81,7 +81,7 @@ const BossInfo = () => {
return () => clearInterval(tickInterval)
}, [balance, army?.profit_per_second, player?.last_raided_at, boss?.level])
return
-
{bossToName[variant]} Moloch (lvl {boss ? boss.level + 1 : 0})
+
{bossToName[variant]} Moloch (lvl {boss ? boss.level + 1 : 0})
{parseFloat(parseFloat(formatUnits(bossToReward[boss?.level || 0], 18).toString()).toFixed(4))} RGCVII reward
{parseFloat((chanceToDefeat.current * 100).toFixed(2))} % to slay {" "}
diff --git a/app/src/components/Counter.tsx b/app/src/components/Counter.tsx
index 843fa32..13a6404 100644
--- a/app/src/components/Counter.tsx
+++ b/app/src/components/Counter.tsx
@@ -43,8 +43,8 @@ export const toReadable = (rawValue: bigint) => {
} else {
const divided = value / suffixes[i - 1].value;
const numStr = (value % suffixes[i - 1].value).toString().slice(0, 3);
- const remainder = parseInt(numStr.replace(/0+$/, ''), 10);
- return `${divided.toString()}.${remainder.toString()} ${suffixes[i - 1].suffix}`;
+ const remainder = numStr == "0" ? "" : "." + parseInt(numStr.replace(/0+$/, ''), 10);
+ return `${divided.toString()}${remainder.toString()} ${suffixes[i - 1].suffix}`;
}
}
}
diff --git a/app/src/components/PixelatedQuote.tsx b/app/src/components/PixelatedQuote.tsx
index fc4f07a..6e7d19d 100644
--- a/app/src/components/PixelatedQuote.tsx
+++ b/app/src/components/PixelatedQuote.tsx
@@ -198,8 +198,8 @@ function PixelatedQuote() {
setTimeout(() => {
setIsShown(false);
- }, 4000);
- }, 6000);
+ }, 8000);
+ }, 10000);
return () => {
if (intervalIdRef.current !== null) {
diff --git a/app/src/components/RegistrationModal.tsx b/app/src/components/RegistrationModal.tsx
index 279fdad..ed05ec6 100644
--- a/app/src/components/RegistrationModal.tsx
+++ b/app/src/components/RegistrationModal.tsx
@@ -16,7 +16,8 @@ const RegistrationModal = ({ isOpen, setIsOpen }: RegistrationModalProps) => {
}, [register, setIsOpen])
if (!isOpen) return null;
return
-
Insert coins to continue
+
setIsOpen(false)}>x
+
Insert coins to continue
onRegister("RGCVII")}>500 RGCVII
onRegister("ETH")}>0.0005 ETH
diff --git a/app/src/components/Scene.tsx b/app/src/components/Scene.tsx
index 739eba3..7ceeffa 100644
--- a/app/src/components/Scene.tsx
+++ b/app/src/components/Scene.tsx
@@ -48,7 +48,7 @@ const Scene = () => {
className={styles.leaderboardButton}
title="Leaderboard"
>
- 📜
+ Top players 📜
{isLeaderboardOpen && (
diff --git a/app/src/pages/_app.tsx b/app/src/pages/_app.tsx
index 533f4e8..23c9c58 100644
--- a/app/src/pages/_app.tsx
+++ b/app/src/pages/_app.tsx
@@ -36,6 +36,7 @@ function MyApp({ Component, pageProps }: AppProps) {
h4,
h5,
h6,
+ button,
.title {
font-family: ${font.style.fontFamily};
}
diff --git a/app/src/styles/Background.module.css b/app/src/styles/Background.module.css
index 9fee508..9980837 100644
--- a/app/src/styles/Background.module.css
+++ b/app/src/styles/Background.module.css
@@ -373,8 +373,8 @@
.leaderboardButton {
position: absolute;
- top: 80px;
- right: 30px;
+ top: 30px;
+ left: 80px;
background: rgba(0, 0, 0, 0.5);
border: none;
border-radius: 5px;
diff --git a/app/src/styles/Modal.module.css b/app/src/styles/Modal.module.css
index 9ed569c..08a220d 100644
--- a/app/src/styles/Modal.module.css
+++ b/app/src/styles/Modal.module.css
@@ -82,6 +82,30 @@
font-size: 2rem;
}
}
+.textCenter {
+ text-align: center;
+}
+.closeBtn {
+ display: inline-block;
+ width: 32px;
+ height: 32px;
+ text-align: center;
+ line-height: 26px;
+ border-radius: 4px;
+ position: absolute;
+ right: 32px;
+ top: 32px;
+ background: black;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+.closeBtn:hover {
+ color: var(--hover-color);
+ transform: scale(1.1);
+}
+.closeBtn::active {
+ transform: scale(1.2);
+}
@keyframes spin {
0% {