mobile css and small display fixes
Some checks are pending
CI / Foundry project (push) Waiting to run

This commit is contained in:
mindxploit 2024-10-31 20:04:26 +01:00
parent 7ccc036b2d
commit 8e547576e0
12 changed files with 397 additions and 247 deletions

View File

@ -80,7 +80,7 @@ const unitAvailableToDiscoverAt: Record<UnitType, bigint> = {
}; };
interface UnitProps { interface UnitProps {
addUnit: (unitType: UnitType) => void; addUnit: (unitType: UnitType, amount?: number) => void;
unitType: UnitType; unitType: UnitType;
canPurchase: boolean; canPurchase: boolean;
isShrouded: boolean; isShrouded: boolean;
@ -92,18 +92,19 @@ const Unit = ({
unitType, unitType,
canPurchase, canPurchase,
isShrouded, isShrouded,
n_units, n_units: unitLevel,
}: UnitProps) => { }: UnitProps) => {
const [unitPrice, unitProfit] = useMemo(() => { const [unitPrice, unitProfit] = useMemo(() => {
return [ return [
toReadable(calculateUnitPrice(unitType, n_units, 1)), toReadable(calculateUnitPrice(unitType, unitLevel, 1)),
toReadable(calculateProfitPerSecond(unitType, n_units)), toReadable(calculateProfitPerSecond(unitType, unitLevel)),
]; ];
}, [n_units, unitType]); }, [unitLevel, unitType]);
return ( return (
<div <div
onClick={() => addUnit(unitType)} onClick={() => addUnit(unitType, 10)}
className={`${styles.armyUnit} ${canPurchase ? "" : styles.isUnavailable className={`${styles.armyUnit} ${
canPurchase ? "" : styles.isUnavailable
}`} }`}
> >
<div <div
@ -122,12 +123,12 @@ const Unit = ({
{unitPrice} <small>GELD</small> {unitPrice} <small>GELD</small>
</span> </span>
)} )}
{n_units > 0 ? ( {unitLevel > 0 ? (
<span className={`${styles.unitSupply} ${styles.uiElement}`}> <span className={`${styles.unitSupply} ${styles.uiElement}`}>
{n_units} {`lvl ${unitLevel}`}
</span> </span>
) : null} ) : null}
{n_units > 0 ? ( {unitLevel > 0 ? (
<span className={`${styles.unitProfit} ${styles.uiElement}`}> <span className={`${styles.unitProfit} ${styles.uiElement}`}>
{unitProfit} <small>per sec</small> {unitProfit} <small>per sec</small>
</span> </span>

View File

@ -16,26 +16,27 @@ export const calculateBalance = (balance: bigint, perSecond: bigint, lastRaidedA
export const toReadable = (rawValue: bigint) => { export const toReadable = (rawValue: bigint) => {
const value = rawValue / BigInt(10000); const value = rawValue / BigInt(10000);
const suffixes = [ const suffixes = [
{ value: BigInt('1000'), suffix: 'thousand' }, { value: BigInt('1000'), suffix: 'k' }, // Thousand
{ value: BigInt('1000000'), suffix: 'million' }, { value: BigInt('1000000'), suffix: 'M' }, // Million
{ value: BigInt('1000000000'), suffix: 'billion' }, { value: BigInt('1000000000'), suffix: 'B' }, // Billion
{ value: BigInt('1000000000000'), suffix: 'trillion' }, { value: BigInt('1000000000000'), suffix: 'T' }, // Trillion
{ value: BigInt('1000000000000000'), suffix: 'quadrillion' }, { value: BigInt('1000000000000000'), suffix: 'Qd' }, // Quadrillion
{ value: BigInt('1000000000000000000'), suffix: 'quintillion' }, { value: BigInt('1000000000000000000'), suffix: 'Qi' }, // Quintillion
{ value: BigInt('1000000000000000000000'), suffix: 'sextillion' }, { value: BigInt('1000000000000000000000'), suffix: 'Sx' }, // Sextillion
{ value: BigInt('1000000000000000000000000'), suffix: 'septillion' }, { value: BigInt('1000000000000000000000000'), suffix: 'Sp' }, // Septillion
{ value: BigInt('1000000000000000000000000000'), suffix: 'octillion' }, { value: BigInt('1000000000000000000000000000'), suffix: 'Oc' }, // Octillion
{ value: BigInt('1000000000000000000000000000000'), suffix: 'nonillion' }, { value: BigInt('1000000000000000000000000000000'), suffix: 'No' }, // Nonillion
{ value: BigInt('1000000000000000000000000000000000'), suffix: 'decillion' }, { value: BigInt('1000000000000000000000000000000000'), suffix: 'Dc' }, // Decillion
{ value: BigInt('1000000000000000000000000000000000000'), suffix: 'undecillion' }, { value: BigInt('1000000000000000000000000000000000000'), suffix: 'Ud' }, // Undecillion
{ value: BigInt('1000000000000000000000000000000000000000'), suffix: 'duodecillion' }, { value: BigInt('1000000000000000000000000000000000000000'), suffix: 'Dd' }, // Duodecillion
{ value: BigInt('1000000000000000000000000000000000000000000'), suffix: 'tredecillion' }, { value: BigInt('1000000000000000000000000000000000000000000'), suffix: 'Td' }, // Tredecillion
{ value: BigInt('1000000000000000000000000000000000000000000000'), suffix: 'quattuordecillion' }, { value: BigInt('1000000000000000000000000000000000000000000000'), suffix: 'Qt' }, // Quattuordecillion
{ value: BigInt('1000000000000000000000000000000000000000000000000'), suffix: 'quindecillion' }, { value: BigInt('1000000000000000000000000000000000000000000000000'), suffix: 'Qn' }, // Quindecillion
{ value: BigInt('1000000000000000000000000000000000000000000000000000'), suffix: 'sexdecillion' }, { value: BigInt('1000000000000000000000000000000000000000000000000000'), suffix: 'Sd' }, // Sexdecillion
{ value: BigInt('1000000000000000000000000000000000000000000000000000000'), suffix: 'septendecillion' }, { value: BigInt('1000000000000000000000000000000000000000000000000000000'), suffix: 'St' }, // Septendecillion
]; ];
for (let i = 0; i < suffixes.length; i++) { for (let i = 0; i < suffixes.length; i++) {
if (value < suffixes[i].value) { if (value < suffixes[i].value) {
if (i == 0) { if (i == 0) {

View File

@ -1,8 +1,8 @@
import React, { useCallback, useMemo } from "react" import React, { useCallback, useMemo } from "react";
import styles from "../styles/Header.module.css" import styles from "../styles/Header.module.css";
import bgStyles from "../styles/Background.module.css" import bgStyles from "../styles/Background.module.css";
import { usePlayer } from "../providers/PlayerProvider"; import { usePlayer } from "../providers/PlayerProvider";
import { useAccount } from 'wagmi'; import { useAccount } from "wagmi";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import Counter, { toReadable } from "./Counter"; import Counter, { toReadable } from "./Counter";
import { useModal } from "../providers/ModalProvider"; import { useModal } from "../providers/ModalProvider";
@ -13,38 +13,56 @@ const Header = () => {
const { openRegistrationModal } = useModal(); const { openRegistrationModal } = useModal();
const title = useMemo(() => { const title = useMemo(() => {
return isRegistered && !player?.has_active_session ? `You died 😇 Click here to start again and ...` : return isRegistered && !player?.has_active_session
isRegistered ? `SLAY THE MOLOCH` : ? `You died 😇 Click here to start again and ...`
!isConnected ? "Connect your wallet traveler ☝️ and then ..." : : isRegistered
"Click here to start 😈" ? `SLAY THE MOLOCH`
}, [isConnected, isRegistered, player?.has_active_session]) : !isConnected
? "Connect your wallet traveler ☝️ and then ..."
: "Click here to start 😈";
}, [isConnected, isRegistered, player?.has_active_session]);
const subtitle = useMemo(() => { const subtitle = useMemo(() => {
if (isRegistered && player?.has_active_session) { if (isRegistered && player?.has_active_session) {
return <Counter /> return <Counter />;
} else { } else {
return <p className={`${styles.counter} ${isConnected && !player?.has_active_session ? bgStyles.excited : ""}`}>SLAY THE MOLOCH</p> return (
<p
className={`${styles.counter} ${
isConnected && !player?.has_active_session ? bgStyles.excited : ""
}`}
>
SLAY THE MOLOCH
</p>
);
} }
}, [isRegistered, player?.has_active_session, isConnected]) }, [isRegistered, player?.has_active_session, isConnected]);
const perSecondParagraph = useMemo(() => { const perSecondParagraph = useMemo(() => {
const perSecond = toReadable(army?.profit_per_second ?? BigInt(0)) const perSecond = toReadable(army?.profit_per_second ?? BigInt(0));
return (isRegistered && player?.has_active_session) ? return isRegistered && player?.has_active_session ? (
<p className={styles.counter_per_seconds}>per second: {perSecond}</p> <p className={styles.counter_per_seconds}>per second: {perSecond}</p>
: null ) : null;
}, [isRegistered, army?.profit_per_second, player?.has_active_session]) }, [isRegistered, army?.profit_per_second, player?.has_active_session]);
const onRegister = useCallback(() => { const onRegister = useCallback(() => {
if (player?.has_active_session) return if (player?.has_active_session) return;
openRegistrationModal() openRegistrationModal();
}, [player?.has_active_session, openRegistrationModal]) }, [player?.has_active_session, openRegistrationModal]);
return <header onClick={onRegister} className={`${styles.header} ${isConnected && !player?.has_active_session ? styles.clickable : ""}`}> return (
<header
onClick={onRegister}
className={`${styles.header} ${
isConnected && !player?.has_active_session ? styles.clickable : ""
}`}
>
<h1 className={`${styles.title}`}>{title}</h1> <h1 className={`${styles.title}`}>{title}</h1>
{subtitle} {subtitle}
{perSecondParagraph} {perSecondParagraph}
</header> </header>
} );
};
// export default Header // export default Header

View File

@ -151,7 +151,9 @@ const EARLY_GAME_QUOTES = [
function PixelatedQuote() { function PixelatedQuote() {
const { player } = usePlayer(); const { player } = usePlayer();
const [isShown, setIsShown] = useState(true); const [isShown, setIsShown] = useState(true);
const [currentQuote, setCurrentQuote] = useState("Welcome to the Dark Forest!"); const [currentQuote, setCurrentQuote] = useState(
"Welcome to the Dark Forest!"
);
const intervalIdRef = useRef<NodeJS.Timeout | null>(null); const intervalIdRef = useRef<NodeJS.Timeout | null>(null);
const hasShownWelcome = useRef(false); const hasShownWelcome = useRef(false);
@ -185,7 +187,9 @@ function PixelatedQuote() {
} else if (totalMinted < PROGRESSION_TIERS.BEGINNER) { } else if (totalMinted < PROGRESSION_TIERS.BEGINNER) {
// Show early game quotes until player reaches beginner level // Show early game quotes until player reaches beginner level
setCurrentQuote( setCurrentQuote(
EARLY_GAME_QUOTES[Math.floor(Math.random() * EARLY_GAME_QUOTES.length)] EARLY_GAME_QUOTES[
Math.floor(Math.random() * EARLY_GAME_QUOTES.length)
]
); );
} else { } else {
const tier = getQuoteTier(totalMinted); const tier = getQuoteTier(totalMinted);
@ -198,8 +202,8 @@ function PixelatedQuote() {
setTimeout(() => { setTimeout(() => {
setIsShown(false); setIsShown(false);
}, 4000); }, 5000);
}, 6000); }, 10000);
return () => { return () => {
if (intervalIdRef.current !== null) { if (intervalIdRef.current !== null) {

View File

@ -1,5 +1,5 @@
import React, { useCallback, useState } from "react" import React, { useCallback, useState } from "react";
import styles from '../styles/Background.module.css'; import styles from "../styles/Background.module.css";
import Tower from "./Tower"; import Tower from "./Tower";
import Army from "./Army"; import Army from "./Army";
import MarchingBand from "./MarchingBand"; import MarchingBand from "./MarchingBand";
@ -17,26 +17,32 @@ const bossToMountainsClass = {
4: styles.mountains4, 4: styles.mountains4,
5: styles.mountains5, 5: styles.mountains5,
6: styles.mountains6, 6: styles.mountains6,
} };
const Scene = () => { const Scene = () => {
const { isRegistered, boss, player } = usePlayer(); const { isRegistered, boss, player } = usePlayer();
const [isLeaderboardOpen, setIsLeaderboardOpen] = useState(false); const [isLeaderboardOpen, setIsLeaderboardOpen] = useState(false);
const handleMusicReady = useCallback((unmute: () => void) => { const handleMusicReady = useCallback(
(unmute: () => void) => {
if (isRegistered) { if (isRegistered) {
unmute(); unmute();
} }
}, [isRegistered]); },
[isRegistered]
);
const variant = boss?.variants[boss.level] || 0; const variant = boss?.variants[boss.level] || 0;
return <div className={styles.frame}> return (
<div className={styles.frame}>
<div className={`${styles.air} ${styles.background_asset}`} /> <div className={`${styles.air} ${styles.background_asset}`} />
<div className={`${styles.clouds_large} ${styles.background_asset}`} /> <div className={`${styles.clouds_large} ${styles.background_asset}`} />
<Boss /> <Boss />
<Tower /> <Tower />
<div className={`${styles.clouds_small} ${styles.background_asset}`} /> <div className={`${styles.clouds_small} ${styles.background_asset}`} />
<div className={`${styles.mountains} ${styles.background_asset} ${bossToMountainsClass[variant]}`} /> <div
className={`${styles.mountains} ${styles.background_asset} ${bossToMountainsClass[variant]}`}
/>
<div className={`${styles.village} ${styles.background_asset}`} /> <div className={`${styles.village} ${styles.background_asset}`} />
{isRegistered && player?.has_active_session && <BossInfo />} {isRegistered && player?.has_active_session && <BossInfo />}
<MarchingBand /> <MarchingBand />
@ -48,7 +54,7 @@ const Scene = () => {
className={styles.leaderboardButton} className={styles.leaderboardButton}
title="Leaderboard" title="Leaderboard"
> >
📜 🏆
</button> </button>
{isLeaderboardOpen && ( {isLeaderboardOpen && (
<div className={styles.leaderboardOverlay}> <div className={styles.leaderboardOverlay}>
@ -64,6 +70,7 @@ const Scene = () => {
</div> </div>
)} )}
</div> </div>
} );
};
export default Scene export default Scene;

View File

@ -1,9 +1,9 @@
import { ConnectButton } from '@rainbow-me/rainbowkit'; import { ConnectButton } from "@rainbow-me/rainbowkit";
import type { NextPage } from 'next'; import type { NextPage } from "next";
import Head from 'next/head'; import Head from "next/head";
import styles from '../styles/Home.module.css'; import styles from "../styles/Home.module.css";
import Header from '../components/Header'; import Header from "../components/Header";
import Scene from '../components/Scene'; import Scene from "../components/Scene";
const Home: NextPage = () => { const Home: NextPage = () => {
return ( return (
@ -26,7 +26,10 @@ const Home: NextPage = () => {
</main> </main>
<footer className={styles.footer}> <footer className={styles.footer}>
Made with by your frens at 😈 Slay the Moloch team for Cohort VII of <a href="https://www.raidguild.org/" target="blank">RaidGuild</a> Made with by your frens at 😈 Slay the Moloch team for Cohort VII of{" "}
<a href="https://www.raidguild.org/" target="blank">
RaidGuild
</a>
</footer> </footer>
</div> </div>
); );

View File

@ -1,48 +1,63 @@
import React, { createContext, ReactNode, useCallback, useContext, useEffect, useState } from 'react' import React, {
import { useAccount, useReadContract, useWriteContract } from 'wagmi' createContext,
import contractAbi from "../../../out/RaidGeld.sol/RaidGeld.json" ReactNode,
import { Hash, parseEther } from 'viem' useCallback,
import contracts from '../../contract_address' useContext,
import WaitingForTxModal from '../components/WaitingForTxModal' useEffect,
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";
const { contractAddress, daoTokenAddress } = contracts const { contractAddress, daoTokenAddress } = contracts;
const abi = contractAbi.abi const abi = contractAbi.abi;
export type UnitType = 0 | 1 | 2 | 3 export type UnitType = 0 | 1 | 2 | 3;
export type BossLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 export type BossLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6;
export interface Player { export interface Player {
created_at: bigint, created_at: bigint;
last_raided_at: bigint, last_raided_at: bigint;
total_minted: bigint total_minted: bigint;
total_rewards: bigint, total_rewards: bigint;
n_runs: number, n_runs: number;
prestige_level: number, prestige_level: number;
is_registered: boolean, is_registered: boolean;
has_active_session: boolean, has_active_session: boolean;
} }
export interface Army { export interface Army {
anointed: { level: number } anointed: { level: number };
apprentice: { level: number } apprentice: { level: number };
champion: { level: number } champion: { level: number };
moloch_denier: { level: number } moloch_denier: { level: number };
profit_per_second: bigint profit_per_second: bigint;
} }
export interface Boss { export interface Boss {
level: BossLevel; level: BossLevel;
variants: [BossLevel, BossLevel, BossLevel, BossLevel, BossLevel, BossLevel, BossLevel] variants: [
BossLevel,
BossLevel,
BossLevel,
BossLevel,
BossLevel,
BossLevel,
BossLevel
];
} }
export interface PlayerContextType { export interface PlayerContextType {
isRegistered: boolean, isRegistered: boolean;
player: null | Player, player: null | Player;
army: null | Army, army: null | Army;
boss: null | Boss, boss: null | Boss;
balance: bigint, balance: bigint;
register: (arg: "ETH" | "RGCVII") => void, register: (arg: "ETH" | "RGCVII") => void;
raid: () => void, raid: () => void;
battleWithBoss: () => void; battleWithBoss: () => void;
addUnit: (unit: UnitType) => void addUnit: (unit: UnitType, amount?: number) => void;
} }
const PlayerContext = createContext<PlayerContextType>({ const PlayerContext = createContext<PlayerContextType>({
@ -51,150 +66,172 @@ const PlayerContext = createContext<PlayerContextType>({
army: null, army: null,
boss: null, boss: null,
balance: BigInt(0), balance: BigInt(0),
register: () => { }, register: () => {},
raid: () => { }, raid: () => {},
battleWithBoss: () => { }, battleWithBoss: () => {},
addUnit: () => { } addUnit: () => {},
}); });
const PlayerProvider = ({ children }: { children: ReactNode }) => { const PlayerProvider = ({ children }: { children: ReactNode }) => {
const { address, isConnected } = useAccount(); const { address, isConnected } = useAccount();
const { writeContract, error } = useWriteContract(); const { writeContract, error } = useWriteContract();
const [[txHash, callbackFn], setHashAndCallback] = useState<[Hash | null, () => void]>([null, () => { }]) const [[txHash, callbackFn], setHashAndCallback] = useState<
[Hash | null, () => void]
>([null, () => {}]);
useEffect(() => { useEffect(() => {
console.warn(error) console.error(error?.message);
}, [error]) }, [error]);
const resetHashAndCallback = useCallback(() => { const resetHashAndCallback = useCallback(() => {
setHashAndCallback([null, () => { }]) setHashAndCallback([null, () => {}]);
}, []) }, []);
const { data: isRegistered } = useReadContract({ const { data: isRegistered } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'isRegistered', functionName: "isRegistered",
args: [address], args: [address],
query: { query: {
enabled: isConnected, enabled: isConnected,
refetchInterval: 15, refetchInterval: 15,
} },
}); });
const { data: balance, } = useReadContract({ const { data: balance } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'balanceOf', functionName: "balanceOf",
args: [address], args: [address],
query: { query: {
refetchInterval: 15, refetchInterval: 15,
enabled: isConnected enabled: isConnected,
} },
}); });
const { data: player } = useReadContract({ const { data: player } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'getPlayer', functionName: "getPlayer",
args: [address], args: [address],
query: { query: {
enabled: isConnected, enabled: isConnected,
refetchInterval: 15 refetchInterval: 15,
} },
}); });
const { data: army } = useReadContract({ const { data: army } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'getArmy', functionName: "getArmy",
args: [address], args: [address],
query: { query: {
enabled: isConnected, enabled: isConnected,
refetchInterval: 15 refetchInterval: 15,
} },
}); });
const { data: boss } = useReadContract({ const { data: boss } = useReadContract({
address: contractAddress, address: contractAddress,
abi, abi,
functionName: 'getBoss', functionName: "getBoss",
args: [address], args: [address],
query: { query: {
enabled: isConnected, enabled: isConnected,
refetchInterval: 15 refetchInterval: 15,
} },
}); });
console.log(balance, player, army, boss) console.log(balance, player, army, boss);
const register = useCallback((arg: "RGCVII" | "ETH") => { const register = useCallback(
if (arg === 'ETH') { (arg: "RGCVII" | "ETH") => {
writeContract({ if (arg === "ETH") {
writeContract(
{
abi, abi,
address: contractAddress, address: contractAddress,
functionName: 'register_eth', functionName: "register_eth",
value: parseEther("0.0005"), value: parseEther("0.0005"),
}, { },
{
onSuccess: (hash) => { onSuccess: (hash) => {
setHashAndCallback([hash, resetHashAndCallback]) setHashAndCallback([hash, resetHashAndCallback]);
},
} }
}) );
} else if (arg === "RGCVII") { } else if (arg === "RGCVII") {
writeContract({ writeContract(
{
abi, abi,
address: daoTokenAddress, address: daoTokenAddress,
functionName: 'approve', functionName: "approve",
args: [contractAddress, parseEther("500")], args: [contractAddress, parseEther("500")],
}, { },
{
onSuccess: (hash) => { onSuccess: (hash) => {
setHashAndCallback([ setHashAndCallback([
hash, hash,
() => writeContract({ () =>
writeContract(
{
abi, abi,
address: contractAddress, address: contractAddress,
functionName: 'register_dao', functionName: "register_dao",
}, { },
{
onSuccess: (hash) => { onSuccess: (hash) => {
setHashAndCallback([hash, resetHashAndCallback]) setHashAndCallback([hash, resetHashAndCallback]);
},
} }
}) ),
]) ]);
},
} }
}); );
} }
}, [writeContract, resetHashAndCallback]) },
[writeContract, resetHashAndCallback]
);
const raid = useCallback(() => { const raid = useCallback(() => {
writeContract({ writeContract(
{
abi, abi,
address: contractAddress, address: contractAddress,
functionName: 'raid', functionName: "raid",
}, { },
{
onSuccess: (hash) => { onSuccess: (hash) => {
setHashAndCallback([hash, resetHashAndCallback]) setHashAndCallback([hash, resetHashAndCallback]);
},
} }
}) );
}, [writeContract, resetHashAndCallback]) }, [writeContract, resetHashAndCallback]);
const addUnit = useCallback((unit: UnitType) => { const addUnit = useCallback(
(unit: UnitType, amount: number = 1) => {
writeContract({ writeContract({
abi, abi,
address: contractAddress, address: contractAddress,
functionName: 'addUnit', functionName: "addUnit",
args: [unit, 1] args: [unit, amount],
}) });
}, [writeContract]) },
[writeContract]
);
const battleWithBoss = useCallback(() => { const battleWithBoss = useCallback(() => {
writeContract({ writeContract({
abi, abi,
address: contractAddress, address: contractAddress,
functionName: 'battle_with_boss', functionName: "battle_with_boss",
}) });
}, [writeContract]) }, [writeContract]);
return ( return (
<PlayerContext.Provider value={{ <PlayerContext.Provider
value={{
isRegistered: isRegistered as boolean, isRegistered: isRegistered as boolean,
player: player as Player, player: player as Player,
army: army as Army, army: army as Army,
@ -203,17 +240,17 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
register, register,
raid, raid,
addUnit, addUnit,
battleWithBoss battleWithBoss,
}}> }}
>
{children} {children}
{txHash && <WaitingForTxModal hash={txHash} callbackFn={callbackFn} />} {txHash && <WaitingForTxModal hash={txHash} callbackFn={callbackFn} />}
</PlayerContext.Provider> </PlayerContext.Provider>
); );
} };
export const usePlayer = () => { export const usePlayer = () => {
return useContext(PlayerContext); return useContext(PlayerContext);
} };
export default PlayerProvider
export default PlayerProvider;

View File

@ -130,8 +130,17 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@media only screen and (max-width: 600px) {
left: 10px;
bottom: 5px;
overflow: auto;
}
} }
.armyUnit { .armyUnit {
@media only screen and (max-width: 600px) {
transform: scale(0.75);
}
position: relative; position: relative;
height: 100%; height: 100%;
width: 120px; width: 120px;
@ -152,6 +161,7 @@
} }
} }
.uiElement { .uiElement {
width: fit-content;
position: absolute; position: absolute;
border-radius: 10px; border-radius: 10px;
background: rgba(0, 0, 0, 0.89); background: rgba(0, 0, 0, 0.89);
@ -161,18 +171,22 @@
text-align: center; text-align: center;
} }
.unitSupply { .unitSupply {
top: 0; top: -30px;
right: 0; right: 0;
left: 2rem;
white-space: nowrap;
} }
.unitName { .unitName {
left: 0; left: 0;
right: 0; right: 0;
bottom: 45px; bottom: 45px;
white-space: nowrap;
} }
.unitPrice { .unitPrice {
left: 0; left: 0;
right: 0; right: 0;
bottom: 25px; bottom: 25px;
white-space: nowrap;
} }
.unitProfit { .unitProfit {
left: 0; left: 0;
@ -201,18 +215,24 @@
height: 90px; height: 90px;
user-select: none; user-select: none;
.pixelQuote { .pixelQuote {
min-width: 150px; min-width: 200px;
width: fit-content;
max-width: 300px;
color: black; color: black;
font-size: 0.7rem; font-size: 0.7rem;
line-height: 0.9rem;
position: absolute; position: absolute;
bottom: 5.5rem; bottom: 5.5rem;
left: -20px; left: -70px;
right: 0; right: 0;
padding: 0.7rem; padding: 0.7rem;
line-height: 0.8rem;
transition: opacity 1s ease-in-out; transition: opacity 1s ease-in-out;
box-shadow: 0px 5px 10px 5px rgba(0, 0, 0, 0.4); box-shadow: 0px 5px 10px 5px rgba(0, 0, 0, 0.4);
} }
@media only screen and (max-width: 600px) {
right: 60px;
}
} }
.static.moloch_denier { .static.moloch_denier {
background-image: url("/roles/scribe2.png"); background-image: url("/roles/scribe2.png");
@ -257,6 +277,40 @@
} }
} }
@media only screen and (max-width: 600px) {
@keyframes marching {
0% {
transform: translate(-54px, -59px); /* -100px scaled to ~-54px */
}
8% {
/* approaches fire */
transform: translate(15px, -100px); /* 72px scaled to ~39px */
}
15% {
/* approaches road */
transform: translate(82px, -123px); /* 152px scaled to ~82px */
}
25% {
/* first road turn */
transform: translate(66px, -200px); /* 122px scaled to ~66px */
}
45% {
/* second road turn */
transform: translate(138px, -264px); /* 256px scaled to ~138px */
}
75% {
/* third road turn */
transform: translate(86px, -293px); /* 159px scaled to ~86px */
}
100% {
/* vanishes into distance */
transform: translate(97px, -300px); /* 180px scaled to ~97px */
}
}
}
@keyframes marchingPerson { @keyframes marchingPerson {
0% { 0% {
background-size: 100% 100%; background-size: 100% 100%;

View File

@ -6,6 +6,12 @@
border-image: url("/background/frame.png") 22 fill / auto space; border-image: url("/background/frame.png") 22 fill / auto space;
width: 720px; width: 720px;
height: 960px; height: 960px;
max-height: 90vh;
@media only screen and (max-width: 600px) {
max-width: 100vw;
max-height: 90vh;
}
} }
.background_asset { .background_asset {
@ -34,7 +40,7 @@
height: 150px; height: 150px;
background-image: url("/background/clouds_large.png"); background-image: url("/background/clouds_large.png");
animation: animation:
scrollBackground 80s linear infinite, scrollBackground 280s linear infinite,
thunder 4s linear infinite; thunder 4s linear infinite;
} }
.clouds_small { .clouds_small {
@ -42,7 +48,7 @@
height: 82px; height: 82px;
background-image: url("/background/clouds_small.png"); background-image: url("/background/clouds_small.png");
animation: animation:
scrollBackground 20s linear infinite, scrollBackground 200s linear infinite,
thunder 12s linear infinite; thunder 12s linear infinite;
} }
@ -215,6 +221,11 @@
background-image: url("/background/village.png"); background-image: url("/background/village.png");
height: 540px; height: 540px;
bottom: 22px; bottom: 22px;
@media only screen and (max-width: 600px) {
height: 300px;
bottom: 80px;
}
} }
.bonfire { .bonfire {
background-image: url("/background/bonfire.png"); background-image: url("/background/bonfire.png");
@ -226,6 +237,12 @@
animation: animation:
bonfire 12s linear infinite, bonfire 12s linear infinite,
bonfire_skew 5s infinite linear; bonfire_skew 5s infinite linear;
@media only screen and (max-width: 600px) {
left: 80px;
bottom: 105px;
scale: .7;
}
} }
.musicButton { .musicButton {
position: absolute; position: absolute;

View File

@ -5,10 +5,18 @@
&.clickable { &.clickable {
cursor: pointer; cursor: pointer;
} }
@media only screen and (max-width: 600px) {
margin-top: 3rem;
}
} }
.title { .title {
font-size: 1.5rem; font-size: 1.5rem;
margin: 0; margin: 0;
@media only screen and (max-width: 600px) {
display: none;
}
} }
.counter { .counter {
font-size: 2rem; font-size: 2rem;

View File

@ -16,14 +16,14 @@
align-items: center; align-items: center;
width: 100%; width: 100%;
max-width: 720px; max-width: 720px;
height: 100vh;
margin: 0 auto; margin: 0 auto;
height: 90vh;
} }
.footer { .footer {
margin-top: 2rem; padding: 0;
padding: 2rem 0; margin-top: 10px;
border-top: 1px solid #eaeaea;
text-align: center; text-align: center;
} }

@ -1 +1 @@
Subproject commit 3291252c866ad698f6a55ec660259e49a67eb3d0 Subproject commit 448efeea6640bbbc09373f03fbc9c88e280147ba