|
|
@ -7,6 +7,7 @@ import { NotificationContainer, NotificationManager } from 'react-notifications'
|
|
|
|
import { AwesomeButton } from 'react-awesome-button';
|
|
|
|
import { AwesomeButton } from 'react-awesome-button';
|
|
|
|
import Typewriter from 'react-ts-typewriter';
|
|
|
|
import Typewriter from 'react-ts-typewriter';
|
|
|
|
import Slider from 'rc-slider';
|
|
|
|
import Slider from 'rc-slider';
|
|
|
|
|
|
|
|
import { debounce } from "lodash";
|
|
|
|
|
|
|
|
|
|
|
|
import Boomer from '../img/unaboomer.png';
|
|
|
|
import Boomer from '../img/unaboomer.png';
|
|
|
|
import Newspapers from '../img/newspapers.png';
|
|
|
|
import Newspapers from '../img/newspapers.png';
|
|
|
@ -22,14 +23,6 @@ import '../styles/sections.css';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const contractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3';
|
|
|
|
const contractAddress = '0x5FbDB2315678afecb367f032d93F642f64180aa3';
|
|
|
|
function debounce(callback, wait) {
|
|
|
|
|
|
|
|
let timeout;
|
|
|
|
|
|
|
|
return (...args) => {
|
|
|
|
|
|
|
|
const context = this;
|
|
|
|
|
|
|
|
clearTimeout(timeout);
|
|
|
|
|
|
|
|
timeout = setTimeout(() => callback.apply(context, args), wait);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export class Section1 extends React.Component {
|
|
|
|
export class Section1 extends React.Component {
|
|
|
|
constructor(props) {
|
|
|
|
constructor(props) {
|
|
|
@ -81,8 +74,8 @@ class GenerateBombOverlay extends React.Component {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ifOver(amt) {
|
|
|
|
ifOver(amt) {
|
|
|
|
if (amt > 100) {
|
|
|
|
if (amt > 200) {
|
|
|
|
return 100;
|
|
|
|
return 200;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
return amt;
|
|
|
|
return amt;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -91,8 +84,8 @@ class GenerateBombOverlay extends React.Component {
|
|
|
|
generateCoords(amt) {
|
|
|
|
generateCoords(amt) {
|
|
|
|
let bombCoords = [];
|
|
|
|
let bombCoords = [];
|
|
|
|
for (let i = 0; i < amt; i++) {
|
|
|
|
for (let i = 0; i < amt; i++) {
|
|
|
|
let randX = Math.floor(Math.random() * 100);
|
|
|
|
let randX = Math.floor(Math.random() * 99);
|
|
|
|
let randY = Math.floor(Math.random() * 100);
|
|
|
|
let randY = Math.floor(Math.random() * 99);
|
|
|
|
let o = {
|
|
|
|
let o = {
|
|
|
|
x: `${randX}%`,
|
|
|
|
x: `${randX}%`,
|
|
|
|
y: `${randY}%`
|
|
|
|
y: `${randY}%`
|
|
|
@ -112,7 +105,7 @@ class GenerateBombOverlay extends React.Component {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
render() {
|
|
|
|
render() {
|
|
|
|
return this.state.coords.map((obj) => <div className={this.props.type} style={{top: obj.y, left: obj.x, backgroundColor: this.state.color}} />)
|
|
|
|
return this.state.coords.map((obj, idx) => <div key={idx} className={this.props.type} style={{top: obj.y, left: obj.x, backgroundColor: this.state.color}} />)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -152,14 +145,18 @@ class GameMap extends React.Component {
|
|
|
|
return (
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<>
|
|
|
|
<h1 id="gameMapTitle">Metaverse Map</h1>
|
|
|
|
<h1 id="gameMapTitle">Metaverse Map</h1>
|
|
|
|
|
|
|
|
<p id="gameMapText">
|
|
|
|
|
|
|
|
{this.state.unaboomerSupply} / {this.props.unaboomerMaxSupply} Unaboomers radicalized and terrorizing the metaverse.
|
|
|
|
|
|
|
|
The game will stop when 1000 Unaboomers remain standing.
|
|
|
|
|
|
|
|
</p>
|
|
|
|
{this.state.unaboomerSupply > 0 && (
|
|
|
|
{this.state.unaboomerSupply > 0 && (
|
|
|
|
<div id="gameStats">
|
|
|
|
<div id="gameStats">
|
|
|
|
<ul>
|
|
|
|
<ul>
|
|
|
|
<li>Active Unaboomers: {this.state.unaboomerSupply - this.state.unaboomersKilled}</li>
|
|
|
|
<li>Active Unaboomers: {this.state.unaboomerSupply - this.state.unaboomersKilled}</li>
|
|
|
|
<li>Dead Unaboomers: {this.state.unaboomersKilled}</li>
|
|
|
|
<li>Dead Unaboomers: {this.state.unaboomersKilled}</li>
|
|
|
|
<li><p className="dots" style={{backgroundColor: 'white'}}></p> _ Active Bombs: {this.state.bombSupply - this.state.bombsExploded}</li>
|
|
|
|
<li><p className="dots" style={{backgroundColor: '#E3B505'}}></p> _ Active Bombs: {this.state.bombSupply - this.state.bombsExploded}</li>
|
|
|
|
<li><p className="dots" style={{backgroundColor: '#E0FF4F'}}></p> _ Exploded Bombs: {this.state.bombsExploded}</li>
|
|
|
|
<li><p className="dots" style={{backgroundColor: '#D01500'}}></p> _ Exploded Bombs: {this.state.bombsExploded}</li>
|
|
|
|
<li><p className="dots" style={{backgroundColor: '#FF2ECC'}}></p> _ Dud Bombs: {this.state.bombsExploded - this.state.unaboomersKilled}</li>
|
|
|
|
<li><p className="dots" style={{backgroundColor: '#0095FF'}}></p> _ Dud Bombs: {this.state.bombsExploded - this.state.unaboomersKilled}</li>
|
|
|
|
</ul>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
)}
|
|
|
@ -180,9 +177,9 @@ class GameMap extends React.Component {
|
|
|
|
)}
|
|
|
|
)}
|
|
|
|
<div className="map">
|
|
|
|
<div className="map">
|
|
|
|
<img src={Map} />
|
|
|
|
<img src={Map} />
|
|
|
|
<GenerateBombOverlay amount={this.state.bombSupply - this.state.bombsExploded} color={'white'} type={'dots'} />
|
|
|
|
<GenerateBombOverlay amount={this.state.bombSupply - this.state.bombsExploded} color={'#E3B505'} type={'dots'} />
|
|
|
|
<GenerateBombOverlay amount={this.state.bombsExploded} color={'#E0FF4F'} type={'dots'} />
|
|
|
|
<GenerateBombOverlay amount={this.state.bombsExploded} color={'#D01500'} type={'dots'} />
|
|
|
|
<GenerateBombOverlay amount={this.state.bombsExploded - this.state.unaboomersKilled} color={'#FF2ECC'} type={'dots'} />
|
|
|
|
<GenerateBombOverlay amount={this.state.bombsExploded - this.state.unaboomersKilled} color={'#0095FF'} type={'dots'} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -194,6 +191,9 @@ function Section3() {
|
|
|
|
unaboomerAmount: 1,
|
|
|
|
unaboomerAmount: 1,
|
|
|
|
bombAmount: 1,
|
|
|
|
bombAmount: 1,
|
|
|
|
sendBombAmount: 1,
|
|
|
|
sendBombAmount: 1,
|
|
|
|
|
|
|
|
unaboomerPreviewAmount: 1,
|
|
|
|
|
|
|
|
bombPreviewAmount: 1,
|
|
|
|
|
|
|
|
sendBombPreviewAmount: 1,
|
|
|
|
unaboomerPrice: ethers.utils.parseEther('.01'),
|
|
|
|
unaboomerPrice: ethers.utils.parseEther('.01'),
|
|
|
|
bombPrice: ethers.utils.parseEther('.01'),
|
|
|
|
bombPrice: ethers.utils.parseEther('.01'),
|
|
|
|
unaboomerBalance: 0,
|
|
|
|
unaboomerBalance: 0,
|
|
|
@ -204,10 +204,11 @@ function Section3() {
|
|
|
|
unaboomersKilled: 0,
|
|
|
|
unaboomersKilled: 0,
|
|
|
|
leaderboardPointer: 0,
|
|
|
|
leaderboardPointer: 0,
|
|
|
|
leaderAddress: '',
|
|
|
|
leaderAddress: '',
|
|
|
|
leaderKillCount: 0
|
|
|
|
leaderKillCount: 0,
|
|
|
|
|
|
|
|
unaboomerMaxSupply: 0
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const handleStateChange = (obj) =>{
|
|
|
|
function handleStateChange(obj) {
|
|
|
|
setOptions(preState => ({...preState , ...obj}))
|
|
|
|
setOptions(preState => ({...preState , ...obj}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const { isConnected, address } = useAccount();
|
|
|
|
const { isConnected, address } = useAccount();
|
|
|
|
const defOpt = {
|
|
|
|
const defOpt = {
|
|
|
@ -254,10 +255,14 @@ function Section3() {
|
|
|
|
{
|
|
|
|
{
|
|
|
|
...defOpt,
|
|
|
|
...defOpt,
|
|
|
|
functionName: 'leaderboardPointer'
|
|
|
|
functionName: 'leaderboardPointer'
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
...defOpt,
|
|
|
|
|
|
|
|
functionName: 'unaboomerMaxSupply'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
],
|
|
|
|
watch: true,
|
|
|
|
watch: true,
|
|
|
|
cacheTime: 10_000,
|
|
|
|
cacheTime: 3_000,
|
|
|
|
onSuccess(data) {
|
|
|
|
onSuccess(data) {
|
|
|
|
handleStateChange({
|
|
|
|
handleStateChange({
|
|
|
|
unaboomerPrice: data[0].toString(),
|
|
|
|
unaboomerPrice: data[0].toString(),
|
|
|
@ -269,6 +274,7 @@ function Section3() {
|
|
|
|
bombsExploded: data[6].toString(),
|
|
|
|
bombsExploded: data[6].toString(),
|
|
|
|
unaboomersKilled: data[7].toString(),
|
|
|
|
unaboomersKilled: data[7].toString(),
|
|
|
|
leaderboardPointer: data[8].toString(),
|
|
|
|
leaderboardPointer: data[8].toString(),
|
|
|
|
|
|
|
|
unaboomerMaxSupply: data[9].toString()
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -279,7 +285,7 @@ function Section3() {
|
|
|
|
functionName: 'leaderboard',
|
|
|
|
functionName: 'leaderboard',
|
|
|
|
args: [options.leaderboardPointer],
|
|
|
|
args: [options.leaderboardPointer],
|
|
|
|
watch: true,
|
|
|
|
watch: true,
|
|
|
|
cacheTime: 10_000,
|
|
|
|
cacheTime: 3_000,
|
|
|
|
onSuccess: async (data) => {
|
|
|
|
onSuccess: async (data) => {
|
|
|
|
handleStateChange({
|
|
|
|
handleStateChange({
|
|
|
|
leaderAddress: data,
|
|
|
|
leaderAddress: data,
|
|
|
@ -293,7 +299,7 @@ function Section3() {
|
|
|
|
functionName: 'killCount',
|
|
|
|
functionName: 'killCount',
|
|
|
|
args: [options.leaderAddress],
|
|
|
|
args: [options.leaderAddress],
|
|
|
|
watch: true,
|
|
|
|
watch: true,
|
|
|
|
cacheTime: 10_000,
|
|
|
|
cacheTime: 3_000,
|
|
|
|
onSuccess(data) {
|
|
|
|
onSuccess(data) {
|
|
|
|
handleStateChange({
|
|
|
|
handleStateChange({
|
|
|
|
leaderKillCount: data.toString(),
|
|
|
|
leaderKillCount: data.toString(),
|
|
|
@ -328,8 +334,15 @@ function Section3() {
|
|
|
|
address: contractAddress,
|
|
|
|
address: contractAddress,
|
|
|
|
abi: MainABI,
|
|
|
|
abi: MainABI,
|
|
|
|
enabled: isConnected && options.bombBalance > 0,
|
|
|
|
enabled: isConnected && options.bombBalance > 0,
|
|
|
|
|
|
|
|
staleTime: 2_000,
|
|
|
|
functionName: 'sendBombs',
|
|
|
|
functionName: 'sendBombs',
|
|
|
|
args: [options.sendBombAmount]
|
|
|
|
args: [options.sendBombAmount],
|
|
|
|
|
|
|
|
onError(err) {
|
|
|
|
|
|
|
|
// console.log(err.message);
|
|
|
|
|
|
|
|
const iface = new ethers.utils.Interface(MainABI);
|
|
|
|
|
|
|
|
const res = iface.decodeFunctionData(err.message)
|
|
|
|
|
|
|
|
console.log(res);
|
|
|
|
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
const sendBombsWrite = useContractWrite(sendBombsPrepare.config);
|
|
|
|
const sendBombsWrite = useContractWrite(sendBombsPrepare.config);
|
|
|
|
useWaitForTransaction({
|
|
|
|
useWaitForTransaction({
|
|
|
@ -364,12 +377,16 @@ function Section3() {
|
|
|
|
<p>Radicalizing a boomer will mint ERC-721 BOOMR tokens with images of a pixel art Web3 Unaboomers.</p>
|
|
|
|
<p>Radicalizing a boomer will mint ERC-721 BOOMR tokens with images of a pixel art Web3 Unaboomers.</p>
|
|
|
|
<p>You have {options.unaboomerBalance} BOOMR</p>
|
|
|
|
<p>You have {options.unaboomerBalance} BOOMR</p>
|
|
|
|
<img src={Boomer} alt="" width="120px" />
|
|
|
|
<img src={Boomer} alt="" width="120px" />
|
|
|
|
|
|
|
|
{options.unaboomerSupply < options.unaboomerMaxSupply && (
|
|
|
|
|
|
|
|
<>
|
|
|
|
<p>
|
|
|
|
<p>
|
|
|
|
<AwesomeButton type="secondary" ripple={true} disabled={!radicalizeBoomersWrite.write} onPress={() => radicalizeBoomersWrite.write?.()}>
|
|
|
|
<AwesomeButton type="secondary" ripple={true} disabled={radicalizeBoomersPrepare.status == 'error'} onPress={() => radicalizeBoomersWrite.write?.()}>
|
|
|
|
{radicalizeBoomersWrite.isLoading && <>minting {options.unaboomerAmount}</> || <>mint {options.unaboomerAmount} ({ethers.utils.formatEther((options.unaboomerPrice * options.unaboomerAmount).toString())} Ξ)</>}
|
|
|
|
{radicalizeBoomersWrite.isLoading && <>minting {options.unaboomerAmount}</> || <>mint {options.unaboomerPreviewAmount} ({ethers.utils.formatEther((options.unaboomerPrice * options.unaboomerPreviewAmount).toString())} Ξ)</>}
|
|
|
|
</AwesomeButton>
|
|
|
|
</AwesomeButton>
|
|
|
|
</p>
|
|
|
|
</p>
|
|
|
|
<Slider className="slider" min={1} max={30} onChange={(v) => handleStateChange({unaboomerAmount: v})} />
|
|
|
|
<Slider className="slider" min={1} max={30} onAfterChange={(v) => handleStateChange({unaboomerAmount: v})} onChange={(v) => handleStateChange({unaboomerPreviewAmount: v})} />
|
|
|
|
|
|
|
|
</>
|
|
|
|
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="mintItem">
|
|
|
|
<div className="mintItem">
|
|
|
|
<h1>Assemble Bombs</h1>
|
|
|
|
<h1>Assemble Bombs</h1>
|
|
|
@ -377,11 +394,11 @@ function Section3() {
|
|
|
|
<p>You have {options.bombBalance} BOMB</p>
|
|
|
|
<p>You have {options.bombBalance} BOMB</p>
|
|
|
|
<img src={Bomb} alt="" width="100px" />
|
|
|
|
<img src={Bomb} alt="" width="100px" />
|
|
|
|
<p>
|
|
|
|
<p>
|
|
|
|
<AwesomeButton type="secondary" ripple={true} disabled={!assembleBombsWrite.write} onPress={() => assembleBombsWrite.write?.()}>
|
|
|
|
<AwesomeButton type="secondary" ripple={true} disabled={assembleBombsPrepare.status == 'error'} onPress={() => assembleBombsWrite.write?.()}>
|
|
|
|
{assembleBombsWrite.isLoading && <>minting {options.bombAmount}</> || <>mint {options.bombAmount} ({ethers.utils.formatEther((options.bombPrice * options.bombAmount).toString())} Ξ)</>}
|
|
|
|
{assembleBombsWrite.isLoading && <>minting {options.bombAmount}</> || <>mint {options.bombPreviewAmount} ({ethers.utils.formatEther((options.bombPrice * options.bombPreviewAmount).toString())} Ξ)</>}
|
|
|
|
</AwesomeButton>
|
|
|
|
</AwesomeButton>
|
|
|
|
</p>
|
|
|
|
</p>
|
|
|
|
<Slider className="slider" min={1} max={30} onChange={(v) => handleStateChange({bombAmount: v})} />
|
|
|
|
<Slider className="slider" min={1} max={30} onAfterChange={(v) => handleStateChange({bombAmount: v})} onChange={(v) => handleStateChange({bombPreviewAmount: v})} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="mintItem">
|
|
|
|
<div className="mintItem">
|
|
|
|
<h1>Send Bombs</h1>
|
|
|
|
<h1>Send Bombs</h1>
|
|
|
@ -389,11 +406,11 @@ function Section3() {
|
|
|
|
<p>There are {options.unaboomerSupply - options.unaboomersKilled} BOOMR available to kill</p>
|
|
|
|
<p>There are {options.unaboomerSupply - options.unaboomersKilled} BOOMR available to kill</p>
|
|
|
|
<img src={Explosion} alt="" width="120px" />
|
|
|
|
<img src={Explosion} alt="" width="120px" />
|
|
|
|
<p>
|
|
|
|
<p>
|
|
|
|
<AwesomeButton type="secondary" ripple={true} disabled={!sendBombsWrite.write} onPress={() => sendBombsWrite.write?.()}>
|
|
|
|
<AwesomeButton type="secondary" ripple={true} disabled={sendBombsPrepare.status == 'error'} onPress={() => sendBombsWrite.write?.()}>
|
|
|
|
send {options.sendBombAmount} (~0 Ξ)
|
|
|
|
send {options.sendBombPreviewAmount} (~0 Ξ)
|
|
|
|
</AwesomeButton>
|
|
|
|
</AwesomeButton>
|
|
|
|
</p>
|
|
|
|
</p>
|
|
|
|
<Slider className="slider" min={1} max={30} onChange={(v) => handleStateChange({sendBombAmount: v})} />
|
|
|
|
<Slider className="slider" min={1} max={30} onAfterChange={(v) => handleStateChange({sendBombAmount: v})} onChange={(v) => handleStateChange({sendBombPreviewAmount: v})} />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<NotificationContainer/>
|
|
|
|
<NotificationContainer/>
|
|
|
@ -405,6 +422,7 @@ function Section3() {
|
|
|
|
unaboomersKilled={options.unaboomersKilled}
|
|
|
|
unaboomersKilled={options.unaboomersKilled}
|
|
|
|
leaderAddress={options.leaderAddress}
|
|
|
|
leaderAddress={options.leaderAddress}
|
|
|
|
leaderKillCount={options.leaderKillCount}
|
|
|
|
leaderKillCount={options.leaderKillCount}
|
|
|
|
|
|
|
|
unaboomerMaxSupply={options.unaboomerMaxSupply}
|
|
|
|
/>
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
</>
|
|
|
|
||
|
|
|
|
||
|
|
|
|