extra counters

This commit is contained in:
Viktor Rådberg
2023-07-03 22:45:35 +02:00
parent affb1dd294
commit f072c29a7e
12 changed files with 368 additions and 19 deletions

View File

@@ -60,10 +60,10 @@ const initialPlayers: Player[] = [
color: '#808080',
settings: {
useCommanderDamage: true,
usePartner: true,
useEnergy: true,
useExperience: true,
usePoison: true,
usePartner: false,
useEnergy: false,
useExperience: false,
usePoison: false,
flipped: true,
},
},
@@ -74,9 +74,9 @@ const initialPlayers: Player[] = [
settings: {
useCommanderDamage: true,
usePartner: false,
useEnergy: true,
useExperience: true,
usePoison: true,
useEnergy: false,
useExperience: false,
usePoison: false,
flipped: true,
},
},
@@ -87,9 +87,9 @@ const initialPlayers: Player[] = [
settings: {
useCommanderDamage: true,
usePartner: false,
useEnergy: true,
useExperience: true,
usePoison: true,
useEnergy: false,
useExperience: false,
usePoison: false,
flipped: false,
},
},
@@ -100,9 +100,9 @@ const initialPlayers: Player[] = [
settings: {
useCommanderDamage: true,
usePartner: false,
useEnergy: true,
useExperience: true,
usePoison: true,
useEnergy: false,
useExperience: false,
usePoison: false,
flipped: false,
},
},

View File

@@ -1,5 +1,6 @@
import { useRef, useState } from 'react';
import CommanderTaxIcon from '../../Icons/CommanderTaxIcon';
import PoisonIcon from '../../Icons/PoisonIcon';
import styled from 'styled-components';
export const StyledCommanderTaxButton = styled.button`

View File

@@ -0,0 +1,67 @@
import { useRef, useState } from 'react';
import styled from 'styled-components';
import EnergyIcon from '../../Icons/EnergyIcon';
export const StyledEnergyButton = styled.button`
flex-grow: 1;
border: none;
outline: none;
cursor: pointer;
background-color: transparent;
user-select: none;
`;
const EnergyButton = () => {
const [energyCount, setEnergyCount] = useState(0);
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const [timeoutFinished, setTimeoutFinished] = useState(false);
const [hasPressedDown, setHasPressedDown] = useState(false);
const handleEnergyCountChange = (increment: number) => {
setEnergyCount(energyCount + increment);
};
const handleDownInput = () => {
setTimeoutFinished(false);
setHasPressedDown(true);
timeoutRef.current = setTimeout(() => {
setTimeoutFinished(true);
handleEnergyCountChange(-1);
}, 500);
};
const handleUpInput = () => {
if (!(hasPressedDown && !timeoutFinished)) {
return;
}
clearTimeout(timeoutRef.current);
handleEnergyCountChange(1);
setHasPressedDown(false);
};
const handleLeaveInput = () => {
setTimeoutFinished(true);
clearTimeout(timeoutRef.current);
setHasPressedDown(false);
};
return (
<StyledEnergyButton
onPointerDown={handleDownInput}
onPointerUp={handleUpInput}
onPointerLeave={handleLeaveInput}
onContextMenu={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
}}
>
<EnergyIcon
size="8vh"
text={energyCount ? energyCount : undefined}
color=""
/>
</StyledEnergyButton>
);
};
export default EnergyButton;

View File

@@ -0,0 +1,67 @@
import { useRef, useState } from 'react';
import styled from 'styled-components';
import ExperienceIcon from '../../Icons/ExperienceIcon';
export const StyledExperienceButton = styled.button`
flex-grow: 1;
border: none;
outline: none;
cursor: pointer;
background-color: transparent;
user-select: none;
`;
const ExperienceButton = () => {
const [experienceCount, setExperienceCount] = useState(0);
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const [timeoutFinished, setTimeoutFinished] = useState(false);
const [hasPressedDown, setHasPressedDown] = useState(false);
const handleExperienceCountChange = (increment: number) => {
setExperienceCount(experienceCount + increment);
};
const handleDownInput = () => {
setTimeoutFinished(false);
setHasPressedDown(true);
timeoutRef.current = setTimeout(() => {
setTimeoutFinished(true);
handleExperienceCountChange(-1);
}, 500);
};
const handleUpInput = () => {
if (!(hasPressedDown && !timeoutFinished)) {
return;
}
clearTimeout(timeoutRef.current);
handleExperienceCountChange(1);
setHasPressedDown(false);
};
const handleLeaveInput = () => {
setTimeoutFinished(true);
clearTimeout(timeoutRef.current);
setHasPressedDown(false);
};
return (
<StyledExperienceButton
onPointerDown={handleDownInput}
onPointerUp={handleUpInput}
onPointerLeave={handleLeaveInput}
onContextMenu={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
}}
>
<ExperienceIcon
size="8vh"
text={experienceCount ? experienceCount : undefined}
color=""
/>
</StyledExperienceButton>
);
};
export default ExperienceButton;

View File

@@ -0,0 +1,68 @@
import { useRef, useState } from 'react';
import CommanderTaxIcon from '../../Icons/CommanderTaxIcon';
import PoisonIcon from '../../Icons/PoisonIcon';
import styled from 'styled-components';
export const StyledPoisonButton = styled.button`
flex-grow: 1;
border: none;
outline: none;
cursor: pointer;
background-color: transparent;
user-select: none;
`;
const PoisonButton = () => {
const [poisonCount, setPoisonCount] = useState(0);
const timeoutRef = useRef<NodeJS.Timeout | undefined>(undefined);
const [timeoutFinished, setTimeoutFinished] = useState(false);
const [hasPressedDown, setHasPressedDown] = useState(false);
const handlePoisonCountChange = (increment: number) => {
setPoisonCount(poisonCount + increment);
};
const handleDownInput = () => {
setTimeoutFinished(false);
setHasPressedDown(true);
timeoutRef.current = setTimeout(() => {
setTimeoutFinished(true);
handlePoisonCountChange(-1);
}, 500);
};
const handleUpInput = () => {
if (!(hasPressedDown && !timeoutFinished)) {
return;
}
clearTimeout(timeoutRef.current);
handlePoisonCountChange(1);
setHasPressedDown(false);
};
const handleLeaveInput = () => {
setTimeoutFinished(true);
clearTimeout(timeoutRef.current);
setHasPressedDown(false);
};
return (
<StyledPoisonButton
onPointerDown={handleDownInput}
onPointerUp={handleUpInput}
onPointerLeave={handleLeaveInput}
onContextMenu={(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
}}
>
<PoisonIcon
size="8vh"
text={poisonCount ? poisonCount : undefined}
color=""
/>
</StyledPoisonButton>
);
};
export default PoisonButton;

View File

@@ -8,6 +8,9 @@ import AddLifeButton from '../Buttons/AddLifeButton';
import SubtractLifeButton from '../Buttons/SubtractLifeButton';
import CommanderDamageBar from '../Buttons/CommanderDamageBar';
import PlayerMenu from '../PlayerMenu/PlayerMenu';
import PoisonButton from '../Buttons/PoisonButton';
import EnergyButton from '../Buttons/EnergyButton';
import ExperienceButton from '../Buttons/ExperienceButton';
type LifeCounterProps = {
player: Player;
@@ -60,6 +63,9 @@ const LifeCounter = ({
{Boolean(
player.settings.useCommanderDamage && player.settings.usePartner
) && <PartnerCommanderTaxButton />}
{player.settings.usePoison && <PoisonButton />}
{player.settings.useEnergy && <EnergyButton />}
{player.settings.useExperience && <ExperienceButton />}
</S.ExtraCountersGrid>
</S.LifeCounterContentContainer>

View File

@@ -49,6 +49,8 @@ const Settings = ({ player, onChange }: SettingsProps) => {
checked={player.settings.useCommanderDamage}
onChange={handleSettingsChange}
/>
</label>
<label>
Use Partner Commander:
<input
type="checkbox"
@@ -57,6 +59,42 @@ const Settings = ({ player, onChange }: SettingsProps) => {
onChange={handleSettingsChange}
/>
</label>
<label>
Show Poison Damage:
<input
type="checkbox"
name="usePoison"
checked={player.settings.usePoison}
onChange={handleSettingsChange}
/>
</label>
<label>
Show Energy:
<input
type="checkbox"
name="useEnergy"
checked={player.settings.useEnergy}
onChange={handleSettingsChange}
/>
</label>
<label>
Show Energy:
<input
type="checkbox"
name="useEnergy"
checked={player.settings.useEnergy}
onChange={handleSettingsChange}
/>
</label>
<label>
Show Experience:
<input
type="checkbox"
name="useExperience"
checked={player.settings.useExperience}
onChange={handleSettingsChange}
/>
</label>
<button
onClick={() => {
const updatedPlayer = {

View File

@@ -1,9 +1,6 @@
type CommanderTaxIconProps = {
size?: string;
text?: number;
};
import { IconProps } from '../Types/Icon';
const CommanderTaxIcon = ({ size, text }: CommanderTaxIconProps) => {
const CommanderTaxIcon = ({ size, text, color }: IconProps) => {
return (
<div style={{ position: 'relative', display: 'inline-block' }}>
<svg
@@ -12,9 +9,10 @@ const CommanderTaxIcon = ({ size, text }: CommanderTaxIconProps) => {
viewBox="0 0 325 325"
width={size || 'auto'}
height={size || 'auto'}
fill={color || 'black'}
fillOpacity="0.5"
>
<title>CommanderTaxIcon</title>
<style>{`.s0 { fill: #000000; fill-opacity: 0.5}`}</style>
<path
id="Lager 1"
className="s0"

View File

@@ -0,0 +1,33 @@
import { IconProps } from '../Types/Icon';
const EnergyIcon = ({ color, size, text }: IconProps) => {
return (
<div style={{ position: 'relative', display: 'inline-block' }}>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve"
viewBox="-30 0 500 500"
width={size}
height={size}
fill={color || 'black'}
fillOpacity="0.5"
>
<path d="M234.896 485.029c-2.669-2.858-3.364-8.205-5.593-11.658-2.645-4.099-5.889-7.763-8.697-11.742-3.68-5.217-7.881-10.06-11.601-15.262-6.362-8.897-13.587-16.63-21.201-24.468-18.683-19.234-38.196-37.019-60.371-52.199-34.356-23.52-70.771-44.106-109.819-58.761-2.709-1.017 0 0-17.614-8.609 3.325-5.34 23.831-34.407 28.638-42.12 8.028-12.881 13.8-26.964 19.782-40.866 7.616-17.7 14.438-35.819 19.899-54.296 6.976-23.604 12.835-47.549 17.354-71.747C86.931 86.566 94.42 29.508 98.888.314c39.192 11.299 25.749 7.891 34.636 10.185 24.621 6.357 50.451 7.612 75.722 9.557 14.404 1.109 28.678.999 43.104.777 21.448-.33 42.94-1.344 64.203-4.293 10.585-1.468 21.127-3.467 31.478-6.126 8.192-2.104 13.47-3.289 31.032-10.1 1.937 7.533 21.898 144.985 48.764 208.185 10.624 24.992 42.674 79.876 52.745 92.264-14.321 5.362-71.933 31.841-101.849 49.629-36.743 21.848-71.48 48.623-100.156 80.446-13.532 15.02-24.152 32.606-35.086 49.537-4.266 6.604-5.912 7.501-8.585 4.654zm11.489-54.904c7.625-39.942 29.623-90.766 63.953-147.75 11.581-19.223 33.603-52.214 46.967-70.363 8.287-11.254 10.945-15.403 10.945-17.086 0-1.254-.476-2.405-1.093-2.642-.602-.231-5.917.457-11.813 1.529-36.192 6.578-73.021 8.765-101.648 6.036-12.956-1.235-22.442-2.794-23.514-3.865-.759-.759 2.172-19.29 4.559-28.822 9.985-39.881 33.304-81.786 63.095-113.384 4.589-4.866 8.156-9.034 7.93-9.26-.228-.227-3.052.433-6.277 1.467-37.805 12.116-79.837 13.334-110.1 3.191-4.133-1.386-7.625-2.414-7.762-2.287-.136.128.165 4.227.669 9.11 4.746 45.95-17.074 106.187-62.849 173.502-6.884 10.124-20.352 28.227-28.176 37.875-3.156 3.891-4.503 6.084-3.834 6.239.567.132 6.354-1.116 12.86-2.772 18.57-4.727 34.105-7.629 55.329-10.332 16.237-2.068 56.226-1.88 70.125.33 9.04 1.437 21.549 4.209 22.277 4.938.15.15-.213 1.752-.806 3.561-3.145 9.582-7.186 28.637-9.049 42.662-3.581 26.956-3.578 70.348.006 102.375 1.409 12.596 3.907 28.753 4.624 29.913.611.986.929-.272 3.582-14.165z" />
</svg>
<div
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
fontSize: '8vh',
fontWeight: 'bold',
}}
>
{text}
</div>
</div>
);
};
export default EnergyIcon;

View File

@@ -0,0 +1,33 @@
import { IconProps } from '../Types/Icon';
const ExperienceIcon = ({ color, size, text }: IconProps) => {
return (
<div style={{ position: 'relative', display: 'inline-block' }}>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve"
viewBox="0 0 980 980"
width={size}
height={size}
fill={color || 'black'}
fillOpacity="0.5"
>
<path d="M.775 171.102c96.217.111 192.488-.717 288.65.386 26.868 13.406 51.584 31.281 75.087 50.039-11.696 41.378-8.552 88.438 16.055 124.74 17.434 27.474 47.611 45.239 79.445 50.314l.055 497.248C351.107 834.08 244.959 767.49 151.445 685.175c-32.053-28.467-63.28-62.729-70.893-106.423-9.103-51.97 12.689-102.395 14.345-154.035.717-40.108-.111-81.541-16.331-118.946-15.227-40.494-46.783-71.224-70.065-106.865-6.014-8.054-7.503-17.985-7.724-27.805zm624.469 50.148c23.834-18.316 48.551-36.301 75.418-49.763 96.108-1.103 192.268-.275 288.43-.386-.719 8.219-.497 16.992-5.572 23.999-21.572 35.253-52.523 64.548-68.963 103.057-19.475 40.108-20.799 85.734-19.529 129.485 2.481 50.369 22.675 99.581 14.454 150.339-7.613 44.134-39.115 78.616-71.39 107.36-94.23 83.251-201.702 149.842-311.491 210.418-.055-166.337-.055-332.675-.055-499.012 35.75-4.359 69.403-25.378 86.837-57.156 20.965-35.418 22.731-79.334 11.861-118.34z" />
</svg>
<div
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
fontSize: '8vh',
fontWeight: 'bold',
}}
>
{text}
</div>
</div>
);
};
export default ExperienceIcon;

View File

@@ -0,0 +1,33 @@
import { IconProps } from '../Types/Icon';
const PhyrexianIcon = ({ color, size, text }: IconProps) => {
return (
<div style={{ position: 'relative', display: 'inline-block' }}>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve"
viewBox="0 0 152.667 223"
width={size}
height={size}
fill={color || 'black'}
fillOpacity="0.5"
>
<path d="M64.333 20.833V223l24-20.333V0M76.334 46.5C34.176 46.5 0 75.644 0 111.454c0 35.904 34.176 65.048 76.334 65.048 42.157 0 76.333-29.144 76.333-65.048 0-35.81-34.176-64.954-76.333-64.954zm.166 101.667c-23.748 0-43-16.146-43-36.083S52.752 76 76.5 76s43 16.147 43 36.083-19.252 36.084-43 36.084z" />
</svg>
<div
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
fontSize: '8vh',
fontWeight: 'bold',
}}
>
{text}
</div>
</div>
);
};
export default PhyrexianIcon;

5
my-app/src/Types/Icon.ts Normal file
View File

@@ -0,0 +1,5 @@
export type IconProps = {
size?: string;
text?: number;
color?: string; // Add color prop
};