Bosses in client
This commit is contained in:
parent
3504059ba8
commit
86ad9c5e1a
BIN
app/public/background/frame_small.png
Normal file
BIN
app/public/background/frame_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
24
app/src/components/Boss.tsx
Normal file
24
app/src/components/Boss.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { BossLevel, usePlayer } from '../providers/PlayerProvider';
|
||||||
|
import styles from '../styles/Background.module.css';
|
||||||
|
|
||||||
|
export const bossLevelToClass: Record<BossLevel, string> = {
|
||||||
|
0: styles.boss0,
|
||||||
|
1: styles.boss1,
|
||||||
|
2: styles.boss2,
|
||||||
|
3: styles.boss3,
|
||||||
|
4: styles.boss4,
|
||||||
|
5: styles.boss5,
|
||||||
|
6: styles.boss6,
|
||||||
|
}
|
||||||
|
|
||||||
|
const Boss = () => {
|
||||||
|
const { battleWithBoss, boss } = usePlayer();
|
||||||
|
const variant = boss?.variants[boss.level] ?? 0;
|
||||||
|
return <div onClick={battleWithBoss} className={`
|
||||||
|
${styles.boss}
|
||||||
|
${bossLevelToClass[variant]}
|
||||||
|
${styles.background_asset}
|
||||||
|
`} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Boss
|
||||||
92
app/src/components/BossInfo.tsx
Normal file
92
app/src/components/BossInfo.tsx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
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"
|
||||||
|
|
||||||
|
export const bossLevelToClass: Record<BossLevel, string> = {
|
||||||
|
0: styles.boss0,
|
||||||
|
1: styles.boss1,
|
||||||
|
2: styles.boss2,
|
||||||
|
3: styles.boss3,
|
||||||
|
4: styles.boss4,
|
||||||
|
5: styles.boss5,
|
||||||
|
6: styles.boss6,
|
||||||
|
}
|
||||||
|
|
||||||
|
const bossToName: Record<BossLevel, string> = {
|
||||||
|
0: "Gluttonous",
|
||||||
|
1: "Slothful",
|
||||||
|
2: "Lusty",
|
||||||
|
3: "Wrathful",
|
||||||
|
4: "Envious",
|
||||||
|
5: "Prideful",
|
||||||
|
6: "Greedy",
|
||||||
|
}
|
||||||
|
|
||||||
|
const bossToReward: Record<BossLevel, bigint> = {
|
||||||
|
0: BigInt("200000000000000000"),
|
||||||
|
1: BigInt("28274420000000000000"),
|
||||||
|
2: BigInt("174191628800000000000"),
|
||||||
|
3: BigInt("513254698112000000000"),
|
||||||
|
4: BigInt("963499867554252800000"),
|
||||||
|
5: BigInt("1424610762718861153000"),
|
||||||
|
6: BigInt("1758160308403017784500"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// for boss chances (percent) [99, 89, 80, 70, 62, 51, 40]
|
||||||
|
const bossToChance: Record<BossLevel, number> = {
|
||||||
|
0: 0.99,
|
||||||
|
1: 0.89,
|
||||||
|
2: 0.8,
|
||||||
|
3: 0.7,
|
||||||
|
4: 0.62,
|
||||||
|
5: 0.51,
|
||||||
|
6: 0.40
|
||||||
|
}
|
||||||
|
|
||||||
|
const bossToBossPower: Record<BossLevel, bigint> = {
|
||||||
|
0: BigInt("9000000"),
|
||||||
|
1: BigInt("90000000"),
|
||||||
|
2: BigInt("900000000"),
|
||||||
|
3: BigInt("9000000000"),
|
||||||
|
4: BigInt("90000000000"),
|
||||||
|
5: BigInt("900000000000"),
|
||||||
|
6: BigInt("9000000000000"),
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBossChanceToDefeat = (bossLevel: BossLevel, geld_balance: bigint) => {
|
||||||
|
const bossPower = bossToBossPower[bossLevel]
|
||||||
|
const geldBurnt = geld_balance >= bossPower ? bossPower : geld_balance;
|
||||||
|
const relativePower = (geldBurnt * geldBurnt * BigInt("100")) / (bossPower * bossPower);
|
||||||
|
return bossToChance[bossLevel] * Number(relativePower) / 100
|
||||||
|
}
|
||||||
|
|
||||||
|
const BossInfo = () => {
|
||||||
|
const { boss, balance, player, army } = usePlayer();
|
||||||
|
const variant = boss?.variants[boss.level] || 0;
|
||||||
|
const maxChance = bossToChance[boss?.level || 0];
|
||||||
|
const chanceToDefeat = useRef(getBossChanceToDefeat(boss?.level || 0, balance ?? BigInt(0)));
|
||||||
|
const [, render] = useReducer(p => !p, false);
|
||||||
|
useEffect(() => {
|
||||||
|
const tickInterval = setInterval(() => {
|
||||||
|
chanceToDefeat.current = getBossChanceToDefeat(boss?.level ?? 0, calculateBalance(
|
||||||
|
balance ?? BigInt(0),
|
||||||
|
army?.profit_per_second ?? BigInt(0),
|
||||||
|
player?.last_raided_at ?? BigInt(0)
|
||||||
|
))
|
||||||
|
render();
|
||||||
|
}, 100);
|
||||||
|
return () => clearInterval(tickInterval)
|
||||||
|
}, [balance, army?.profit_per_second, player?.last_raided_at, boss?.level])
|
||||||
|
return <div className={styles.bossInfo}>
|
||||||
|
<p><strong className={bossLevelToClass[boss?.level || 0]}>{bossToName[variant]}</strong> Moloch <small>(lvl {boss ? boss.level + 1 : 0})</small></p>
|
||||||
|
<p><strong className={styles.reward}>{formatUnits(bossToReward[boss?.level || 0], 18)} RGCVII</strong> <small>reward</small></p>
|
||||||
|
<p>
|
||||||
|
<strong>{chanceToDefeat.current * 100} % to slay</strong>{" "}
|
||||||
|
{chanceToDefeat.current == maxChance ? <small className={styles.maxed}>(MAXED)</small> : <small>(Max {maxChance * 100}%)</small>}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BossInfo
|
||||||
@ -55,8 +55,8 @@ export const toReadable = (rawValue: bigint) => {
|
|||||||
const Counter = () => {
|
const Counter = () => {
|
||||||
const { balance, army, player } = usePlayer();
|
const { balance, army, player } = usePlayer();
|
||||||
const [, render] = useReducer(p => !p, false);
|
const [, render] = useReducer(p => !p, false);
|
||||||
const balanceCount = useRef(balance.toString() ?? "0")
|
const balanceCount = useRef(balance ? balance.toString() : "0")
|
||||||
const availableBalance = useRef(balance.toString() ?? "0")
|
const availableBalance = useRef(balance ? balance.toString() : "0")
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const tickInterval = setInterval(() => {
|
const tickInterval = setInterval(() => {
|
||||||
balanceCount.current = toReadable(calculateBalance(
|
balanceCount.current = toReadable(calculateBalance(
|
||||||
|
|||||||
@ -5,22 +5,37 @@ import Army from "./Army";
|
|||||||
import MarchingBand from "./MarchingBand";
|
import MarchingBand from "./MarchingBand";
|
||||||
import MusicPlayer from "./MusicPlayer";
|
import MusicPlayer from "./MusicPlayer";
|
||||||
import { usePlayer } from "../providers/PlayerProvider";
|
import { usePlayer } from "../providers/PlayerProvider";
|
||||||
|
import Boss from "./Boss";
|
||||||
|
import BossInfo from "./BossInfo";
|
||||||
|
|
||||||
|
const bossToMountainsClass = {
|
||||||
|
0: styles.mountains0,
|
||||||
|
1: styles.mountains1,
|
||||||
|
2: styles.mountains2,
|
||||||
|
3: styles.mountains3,
|
||||||
|
4: styles.mountains4,
|
||||||
|
5: styles.mountains5,
|
||||||
|
6: styles.mountains6,
|
||||||
|
}
|
||||||
|
|
||||||
const Scene = () => {
|
const Scene = () => {
|
||||||
const { isRegistered } = usePlayer();
|
const { isRegistered, boss } = usePlayer();
|
||||||
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;
|
||||||
|
|
||||||
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_small} ${styles.background_asset}`} />
|
|
||||||
<div className={`${styles.clouds_large} ${styles.background_asset}`} />
|
<div className={`${styles.clouds_large} ${styles.background_asset}`} />
|
||||||
|
<Boss />
|
||||||
<Tower />
|
<Tower />
|
||||||
<div className={`${styles.mountains} ${styles.background_asset}`} />
|
<div className={`${styles.clouds_small} ${styles.background_asset}`} />
|
||||||
|
<div className={`${styles.mountains} ${styles.background_asset} ${bossToMountainsClass[variant]}`} />
|
||||||
<div className={`${styles.village} ${styles.background_asset}`} />
|
<div className={`${styles.village} ${styles.background_asset}`} />
|
||||||
|
<BossInfo />
|
||||||
<MarchingBand />
|
<MarchingBand />
|
||||||
<div className={`${styles.bonfire} ${styles.background_asset}`} />
|
<div className={`${styles.bonfire} ${styles.background_asset}`} />
|
||||||
<Army />
|
<Army />
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useReducer, useRef } from 'react';
|
import { useEffect, useReducer, useRef } from 'react';
|
||||||
import { usePlayer } from '../providers/PlayerProvider';
|
import { BossLevel, usePlayer } from '../providers/PlayerProvider';
|
||||||
import styles from '../styles/Background.module.css';
|
import styles from '../styles/Background.module.css';
|
||||||
|
|
||||||
const onCooldown = (lastRaidedAt: bigint) => (
|
const onCooldown = (lastRaidedAt: bigint) => (
|
||||||
@ -10,10 +10,21 @@ const onCooldown = (lastRaidedAt: bigint) => (
|
|||||||
|
|
||||||
const emptyFn = () => { }
|
const emptyFn = () => { }
|
||||||
|
|
||||||
|
const bossLevelToClass: Record<BossLevel, string> = {
|
||||||
|
0: styles.tower0,
|
||||||
|
1: styles.tower1,
|
||||||
|
2: styles.tower2,
|
||||||
|
3: styles.tower3,
|
||||||
|
4: styles.tower4,
|
||||||
|
5: styles.tower5,
|
||||||
|
6: styles.tower6,
|
||||||
|
}
|
||||||
|
|
||||||
const Tower = () => {
|
const Tower = () => {
|
||||||
const { raid, player } = usePlayer();
|
const { raid, player, boss } = usePlayer();
|
||||||
const isOnCooldown = useRef(false);
|
const isOnCooldown = useRef(false);
|
||||||
const [, render] = useReducer(p => !p, false);
|
const [, render] = useReducer(p => !p, false);
|
||||||
|
const variant = boss?.variants[boss.level] ?? 0;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkCooldownInterval = setInterval(() => {
|
const checkCooldownInterval = setInterval(() => {
|
||||||
@ -25,6 +36,7 @@ const Tower = () => {
|
|||||||
|
|
||||||
return <div onClick={isOnCooldown.current ? emptyFn : raid} className={`
|
return <div onClick={isOnCooldown.current ? emptyFn : raid} className={`
|
||||||
${styles.tower}
|
${styles.tower}
|
||||||
|
${bossLevelToClass[variant]}
|
||||||
${styles.background_asset}
|
${styles.background_asset}
|
||||||
${isOnCooldown.current ? styles.cooldown : ""}
|
${isOnCooldown.current ? styles.cooldown : ""}
|
||||||
`} />
|
`} />
|
||||||
|
|||||||
@ -9,11 +9,17 @@ 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 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,
|
||||||
|
n_runs: number,
|
||||||
|
prestige_level: number,
|
||||||
|
is_registered: boolean,
|
||||||
|
has_active_session: boolean,
|
||||||
}
|
}
|
||||||
export interface Army {
|
export interface Army {
|
||||||
anointed: { level: number }
|
anointed: { level: number }
|
||||||
@ -22,14 +28,20 @@ export interface Army {
|
|||||||
moloch_denier: { level: number }
|
moloch_denier: { level: number }
|
||||||
profit_per_second: bigint
|
profit_per_second: bigint
|
||||||
}
|
}
|
||||||
|
export interface Boss {
|
||||||
|
level: 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,
|
||||||
balance: bigint,
|
balance: bigint,
|
||||||
register: (arg: "ETH" | "RGCVII") => void,
|
register: (arg: "ETH" | "RGCVII") => void,
|
||||||
raid: () => void,
|
raid: () => void,
|
||||||
|
battleWithBoss: () => void;
|
||||||
addUnit: (unit: UnitType) => void
|
addUnit: (unit: UnitType) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +49,11 @@ const PlayerContext = createContext<PlayerContextType>({
|
|||||||
isRegistered: false,
|
isRegistered: false,
|
||||||
player: null,
|
player: null,
|
||||||
army: null,
|
army: null,
|
||||||
|
boss: null,
|
||||||
balance: BigInt(0),
|
balance: BigInt(0),
|
||||||
register: () => { },
|
register: () => { },
|
||||||
raid: () => { },
|
raid: () => { },
|
||||||
|
battleWithBoss: () => { },
|
||||||
addUnit: () => { }
|
addUnit: () => { }
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -100,7 +114,18 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(balance, player, army)
|
const { data: boss } = useReadContract({
|
||||||
|
address: contractAddress,
|
||||||
|
abi,
|
||||||
|
functionName: 'getBoss',
|
||||||
|
args: [address],
|
||||||
|
query: {
|
||||||
|
enabled: isConnected,
|
||||||
|
refetchInterval: 15
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(balance, player, army, boss)
|
||||||
|
|
||||||
const register = useCallback((arg: "RGCVII" | "ETH") => {
|
const register = useCallback((arg: "RGCVII" | "ETH") => {
|
||||||
if (arg === 'ETH') {
|
if (arg === 'ETH') {
|
||||||
@ -108,7 +133,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
abi,
|
abi,
|
||||||
address: contractAddress,
|
address: contractAddress,
|
||||||
functionName: 'register_eth',
|
functionName: 'register_eth',
|
||||||
value: parseEther("0.00005"),
|
value: parseEther("0.0005"),
|
||||||
}, {
|
}, {
|
||||||
onSuccess: (hash) => {
|
onSuccess: (hash) => {
|
||||||
setHashAndCallback([hash, resetHashAndCallback])
|
setHashAndCallback([hash, resetHashAndCallback])
|
||||||
@ -119,7 +144,7 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
abi,
|
abi,
|
||||||
address: daoTokenAddress,
|
address: daoTokenAddress,
|
||||||
functionName: 'approve',
|
functionName: 'approve',
|
||||||
args: [contractAddress, parseEther("50")],
|
args: [contractAddress, parseEther("500")],
|
||||||
}, {
|
}, {
|
||||||
onSuccess: (hash) => {
|
onSuccess: (hash) => {
|
||||||
setHashAndCallback([
|
setHashAndCallback([
|
||||||
@ -156,15 +181,25 @@ const PlayerProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
})
|
})
|
||||||
}, [writeContract])
|
}, [writeContract])
|
||||||
|
|
||||||
|
const battleWithBoss = useCallback(() => {
|
||||||
|
writeContract({
|
||||||
|
abi,
|
||||||
|
address: contractAddress,
|
||||||
|
functionName: 'battle_with_boss',
|
||||||
|
})
|
||||||
|
}, [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,
|
||||||
|
boss: boss as Boss,
|
||||||
balance: balance as bigint,
|
balance: balance as bigint,
|
||||||
register,
|
register,
|
||||||
raid,
|
raid,
|
||||||
addUnit
|
addUnit,
|
||||||
|
battleWithBoss
|
||||||
}}>
|
}}>
|
||||||
{children}
|
{children}
|
||||||
{txHash && <WaitingForTxModal hash={txHash} callbackFn={callbackFn} />}
|
{txHash && <WaitingForTxModal hash={txHash} callbackFn={callbackFn} />}
|
||||||
|
|||||||
@ -199,7 +199,7 @@
|
|||||||
bottom: 160px;
|
bottom: 160px;
|
||||||
width: 90px;
|
width: 90px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
|
user-select: none;
|
||||||
.pixelQuote {
|
.pixelQuote {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
color: black;
|
color: black;
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
left: 22px;
|
left: 22px;
|
||||||
right: 22px;
|
right: 22px;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.air {
|
.air {
|
||||||
@ -44,14 +45,100 @@
|
|||||||
scrollBackground 20s linear infinite,
|
scrollBackground 20s linear infinite,
|
||||||
thunder 12s linear infinite;
|
thunder 12s linear infinite;
|
||||||
}
|
}
|
||||||
.tower {
|
|
||||||
background-image: url("/background/tower.png");
|
.boss {
|
||||||
width: 218px;
|
background-image: url("/background/boss/0_gluttony.svg");
|
||||||
height: 240px;
|
background-size: cover;
|
||||||
top: 150px;
|
width: 270px;
|
||||||
|
height: 270px;
|
||||||
|
top: 130px;
|
||||||
|
right: 10px;
|
||||||
|
left: auto;
|
||||||
animation: thunder_hue_hard 12s linear infinite;
|
animation: thunder_hue_hard 12s linear infinite;
|
||||||
transition: all 0.1s cubic-bezier(0.265, 1.4, 0.68, 1.65);
|
transition: all 0.1s cubic-bezier(0.265, 1.4, 0.68, 1.65);
|
||||||
transform-origin: bottom center;
|
transform-origin: bottom center;
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
transform: scale(1.05, 1.1);
|
||||||
|
transform-origin: bottom center;
|
||||||
|
&::after {
|
||||||
|
text-shadow: #0f0 1px 1px 10px;
|
||||||
|
animation: excited 0.5s infinite linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
transform: scale(1.1, 1.22);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.boss0 {
|
||||||
|
background-image: url("/background/boss/0_gluttony.svg");
|
||||||
|
}
|
||||||
|
&.boss1 {
|
||||||
|
background-image: url("/background/boss/1_sloth.svg");
|
||||||
|
}
|
||||||
|
&.boss2 {
|
||||||
|
background-image: url("/background/boss/2_lust.svg");
|
||||||
|
}
|
||||||
|
&.boss3 {
|
||||||
|
background-image: url("/background/boss/3_wrath.svg");
|
||||||
|
}
|
||||||
|
&.boss4 {
|
||||||
|
background-image: url("/background/boss/4_envy.svg");
|
||||||
|
}
|
||||||
|
&.boss5 {
|
||||||
|
background-image: url("/background/boss/5_pride.svg");
|
||||||
|
}
|
||||||
|
&.boss6 {
|
||||||
|
background-image: url("/background/boss/6_greed.svg");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.boss::after {
|
||||||
|
position: absolute;
|
||||||
|
content: "BOSS\A(Risk & Earn RGCVII)";
|
||||||
|
text-align: center;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: break-word;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
top: 40%;
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tower {
|
||||||
|
background-image: url("/background/tower/0_gluttony.svg");
|
||||||
|
background-size: cover;
|
||||||
|
width: 372px;
|
||||||
|
height: 372px;
|
||||||
|
top: 90px;
|
||||||
|
left: -10px;
|
||||||
|
animation: thunder_hue_hard 12s linear infinite;
|
||||||
|
transition: all 0.1s cubic-bezier(0.265, 1.4, 0.68, 1.65);
|
||||||
|
transform-origin: bottom center;
|
||||||
|
pointer-events: all;
|
||||||
|
&.tower0 {
|
||||||
|
background-image: url("/background/tower/0_gluttony.svg");
|
||||||
|
}
|
||||||
|
&.tower1 {
|
||||||
|
background-image: url("/background/tower/1_sloth.svg");
|
||||||
|
}
|
||||||
|
&.tower2 {
|
||||||
|
background-image: url("/background/tower/2_lust.svg");
|
||||||
|
}
|
||||||
|
&.tower3 {
|
||||||
|
background-image: url("/background/tower/3_wrath.svg");
|
||||||
|
}
|
||||||
|
&.tower4 {
|
||||||
|
background-image: url("/background/tower/4_envy.svg");
|
||||||
|
}
|
||||||
|
&.tower5 {
|
||||||
|
background-image: url("/background/tower/5_pride.svg");
|
||||||
|
}
|
||||||
|
&.tower6 {
|
||||||
|
background-image: url("/background/tower/6_greed.svg");
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transform: scale(1.05, 1.1);
|
transform: scale(1.05, 1.1);
|
||||||
@ -71,8 +158,6 @@
|
|||||||
content: "RAID IN PROGRESS";
|
content: "RAID IN PROGRESS";
|
||||||
color: var(--hover-color);
|
color: var(--hover-color);
|
||||||
top: calc(50% - 15px);
|
top: calc(50% - 15px);
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
animation: excited 0.5s infinite linear;
|
animation: excited 0.5s infinite linear;
|
||||||
@ -86,16 +171,39 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
left: 50px;
|
left: 0;
|
||||||
top: 22px;
|
width: 100%;
|
||||||
|
top: 40%;
|
||||||
|
margin-top: -10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mountains {
|
.mountains {
|
||||||
background-image: url("/background/mountains.png");
|
background-image: url("/background/mountains/0_gluttony.svg");
|
||||||
height: 181px;
|
height: 181px;
|
||||||
top: 285px;
|
top: 285px;
|
||||||
animation: thunder_hue 12s linear infinite;
|
animation: thunder_hue 12s linear infinite;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
&.mountains0 {
|
||||||
|
background-image: url("/background/mountains/0_gluttony.svg");
|
||||||
|
}
|
||||||
|
&.mountains1 {
|
||||||
|
background-image: url("/background/mountains/1_sloth.svg");
|
||||||
|
}
|
||||||
|
&.mountains2 {
|
||||||
|
background-image: url("/background/mountains/2_lust.svg");
|
||||||
|
}
|
||||||
|
&.mountains3 {
|
||||||
|
background-image: url("/background/mountains/3_wrath.svg");
|
||||||
|
}
|
||||||
|
&.mountains4 {
|
||||||
|
background-image: url("/background/mountains/4_envy.svg");
|
||||||
|
}
|
||||||
|
&.mountains5 {
|
||||||
|
background-image: url("/background/mountains/5_pride.svg");
|
||||||
|
}
|
||||||
|
&.mountains6 {
|
||||||
|
background-image: url("/background/mountains/6_greed.svg");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.village {
|
.village {
|
||||||
background-image: url("/background/village.png");
|
background-image: url("/background/village.png");
|
||||||
|
|||||||
59
app/src/styles/Info.module.css
Normal file
59
app/src/styles/Info.module.css
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
.bossInfo {
|
||||||
|
position: absolute;
|
||||||
|
top: 350px;
|
||||||
|
right: 28px;
|
||||||
|
background: var(--bg-color);
|
||||||
|
border-image: url("/background/frame_small.png") 11 fill / auto space;
|
||||||
|
padding: 18px 22px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
& > p {
|
||||||
|
text-align: center;
|
||||||
|
margin: 0.2rem 0;
|
||||||
|
& > .reward {
|
||||||
|
color: var(--hover-color);
|
||||||
|
}
|
||||||
|
& > .maxed {
|
||||||
|
display: inline-block;
|
||||||
|
color: var(--accent-color);
|
||||||
|
opacity: 1;
|
||||||
|
animation: excited 0.5s infinite linear;
|
||||||
|
}
|
||||||
|
& > .boss0 {
|
||||||
|
color: #a44016;
|
||||||
|
}
|
||||||
|
& > .boss1 {
|
||||||
|
color: #99554d;
|
||||||
|
}
|
||||||
|
& > .boss2 {
|
||||||
|
color: #9b215e;
|
||||||
|
}
|
||||||
|
& > .boss3 {
|
||||||
|
color: #ebb638;
|
||||||
|
}
|
||||||
|
& > .boss4 {
|
||||||
|
color: #c6282e;
|
||||||
|
}
|
||||||
|
& > .boss5 {
|
||||||
|
color: #d06b53;
|
||||||
|
}
|
||||||
|
& > .boss6 {
|
||||||
|
color: #8f968f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& small {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes excited {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: scale(1, 1) skew(0deg, 0deg);
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
transform: scale(1.2, 1.2) skew(0.5deg, -0.5deg);
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
transform: scale(1.02, 1.03) skew(0deg, -1deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,7 +10,7 @@ import "../src/Constants.sol";
|
|||||||
|
|
||||||
contract RaidGeld is ERC20, Ownable, Constants {
|
contract RaidGeld is ERC20, Ownable, Constants {
|
||||||
uint256 public constant MANTISSA = 1e4;
|
uint256 public constant MANTISSA = 1e4;
|
||||||
uint256 public constant BUY_IN_AMOUNT = 0.00005 ether;
|
uint256 public constant BUY_IN_AMOUNT = 0.0005 ether;
|
||||||
uint256 public immutable BUY_IN_DAO_TOKEN_AMOUNT;
|
uint256 public immutable BUY_IN_DAO_TOKEN_AMOUNT;
|
||||||
uint256 public constant INITIAL_GELD = 50 * MANTISSA;
|
uint256 public constant INITIAL_GELD = 50 * MANTISSA;
|
||||||
mapping(address => Player) private players;
|
mapping(address => Player) private players;
|
||||||
|
|||||||
@ -98,7 +98,7 @@ library RaidGeldUtils {
|
|||||||
// TODO: This could as well just be pre-calculated
|
// TODO: This could as well just be pre-calculated
|
||||||
uint256 cumulativeChance = getBossCumulativeChance(bossLevel); // 0 - 1e18 range
|
uint256 cumulativeChance = getBossCumulativeChance(bossLevel); // 0 - 1e18 range
|
||||||
uint256 rewardMultiplier = ((2 * (1e18 - cumulativeChance)) ** 2) / 1e18;
|
uint256 rewardMultiplier = ((2 * (1e18 - cumulativeChance)) ** 2) / 1e18;
|
||||||
return (baseReward * rewardMultiplier) / 1e18;
|
return (baseReward * rewardMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates whether user survives the fight
|
// Calculates whether user survives the fight
|
||||||
|
|||||||
@ -138,4 +138,14 @@ contract raid_geldTest is Test {
|
|||||||
vm.assertTrue(successCount >= lowerProb && successCount <= upperProb, "Success rate not within expected range");
|
vm.assertTrue(successCount >= lowerProb && successCount <= upperProb, "Success rate not within expected range");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_4_print_boss_rewards() public {
|
||||||
|
uint256 total = 0;
|
||||||
|
for (uint8 i = 0; i < 7; i++) {
|
||||||
|
uint256 reward = RaidGeldUtils.calculateBossReward(i, 500);
|
||||||
|
console.log("Reward", i,reward);
|
||||||
|
total += reward;
|
||||||
|
}
|
||||||
|
console.log("Total", total);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user