addded ratmsic
This commit is contained in:
69
package-lock.json
generated
69
package-lock.json
generated
@@ -15,6 +15,7 @@
|
|||||||
"partysocket": "^1.1.4",
|
"partysocket": "^1.1.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-youtube": "^10.1.0",
|
||||||
"wouter": "^3.7.1"
|
"wouter": "^3.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -2558,8 +2559,7 @@
|
|||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.2",
|
||||||
@@ -3179,6 +3179,11 @@
|
|||||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/load-script": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA=="
|
||||||
|
},
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||||
@@ -3443,7 +3448,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -3835,6 +3839,16 @@
|
|||||||
"integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
|
"integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==",
|
||||||
"license": "Unlicense"
|
"license": "Unlicense"
|
||||||
},
|
},
|
||||||
|
"node_modules/prop-types": {
|
||||||
|
"version": "15.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
|
"dependencies": {
|
||||||
|
"loose-envify": "^1.4.0",
|
||||||
|
"object-assign": "^4.1.1",
|
||||||
|
"react-is": "^16.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
@@ -3887,6 +3901,11 @@
|
|||||||
"react": "^18.3.1"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-is": {
|
||||||
|
"version": "16.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.14.2",
|
"version": "0.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
|
||||||
@@ -3896,6 +3915,22 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-youtube": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZfGtcVpk0SSZtWCSTYOQKhfx5/1cfyEW1JN/mugGNfAxT3rmVJeMbGpA9+e78yG21ls5nc/5uZJETE3cm3knBg==",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "3.1.3",
|
||||||
|
"prop-types": "15.8.1",
|
||||||
|
"youtube-player": "5.5.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.x"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=0.14.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/read-cache": {
|
"node_modules/read-cache": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
@@ -4067,6 +4102,11 @@
|
|||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sister": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/sister/-/sister-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-p19rtTs+NksBRKW9qn0UhZ8/TUI9BPw9lmtHny+Y3TinWlOa9jWh9xB0AtPSdmOy49NJJJSSe0Ey4C7h0TrcYA=="
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
@@ -4868,6 +4908,29 @@
|
|||||||
"stacktracey": "^2.1.8"
|
"stacktracey": "^2.1.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/youtube-player": {
|
||||||
|
"version": "5.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
|
||||||
|
"integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^2.6.6",
|
||||||
|
"load-script": "^1.0.0",
|
||||||
|
"sister": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/youtube-player/node_modules/debug": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/youtube-player/node_modules/ms": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||||
|
},
|
||||||
"node_modules/zod": {
|
"node_modules/zod": {
|
||||||
"version": "3.25.76",
|
"version": "3.25.76",
|
||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"partysocket": "^1.1.4",
|
"partysocket": "^1.1.4",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
"react-youtube": "^10.1.0",
|
||||||
"wouter": "^3.7.1"
|
"wouter": "^3.7.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export interface Upgrade {
|
|||||||
mascotTiers?: MascotTier[];
|
mascotTiers?: MascotTier[];
|
||||||
oneTime?: boolean;
|
oneTime?: boolean;
|
||||||
newsTitles?: string[];
|
newsTitles?: string[];
|
||||||
|
youtubeId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MascotTier {
|
export interface MascotTier {
|
||||||
@@ -191,6 +192,16 @@ const UPGRADES: Upgrade[] = [
|
|||||||
`om`,
|
`om`,
|
||||||
`You are the Glue to my life like how Tokai Teio is glue(stick) to a child's art project`,
|
`You are the Glue to my life like how Tokai Teio is glue(stick) to a child's art project`,
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'secretVideo',
|
||||||
|
name: '🎬 Secret Video',
|
||||||
|
description: 'Unlock a secret video. Plays automatically!',
|
||||||
|
baseCost: 1000000, // Very expensive
|
||||||
|
multiplier: 1,
|
||||||
|
icon: '🎬',
|
||||||
|
oneTime: true,
|
||||||
|
youtubeId: 'ONzntmMFXGE' // The YouTube video ID
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
53
src/App.tsx
53
src/App.tsx
@@ -15,6 +15,7 @@ import { UPGRADES } from './config/upgrades'; // Import UPGRADES for upgrade con
|
|||||||
import { useLocation, Link } from 'wouter'; // Import wouter hooks
|
import { useLocation, Link } from 'wouter'; // Import wouter hooks
|
||||||
import AdminPage from './components/AdminPage'; // Import AdminPage
|
import AdminPage from './components/AdminPage'; // Import AdminPage
|
||||||
import { NewsMarquee } from './components/NewsMarquee'; // Import NewsMarquee
|
import { NewsMarquee } from './components/NewsMarquee'; // Import NewsMarquee
|
||||||
|
import YouTube from 'react-youtube'; // Import YouTube component
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { isSignedIn, isLoaded, userId: clerkUserId } = useAuth(); // Get clerkUserId from useAuth
|
const { isSignedIn, isLoaded, userId: clerkUserId } = useAuth(); // Get clerkUserId from useAuth
|
||||||
@@ -24,9 +25,10 @@ function App() {
|
|||||||
const [mascotEntities, setMascotEntities] = useState<ClickableMascotType[]>([]);
|
const [mascotEntities, setMascotEntities] = useState<ClickableMascotType[]>([]);
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||||
const gameStateRef = useRef(gameState); // Ref to hold the latest gameState
|
const gameStateRef = useRef(gameState); // Ref to hold the latest gameState
|
||||||
const clickButtonContainerRef = useRef<HTMLDivElement>(null); // New ref for the click button container
|
|
||||||
const [location] = useLocation(); // Get current location from wouter
|
const [location, setLocation] = useLocation(); // Get current location from wouter
|
||||||
const [adminBroadcastMessage, setAdminBroadcastMessage] = useState<string | null>(null); // New state for admin messages
|
const [adminBroadcastMessage, setAdminBroadcastMessage] = useState<string | null>(null); // New state for admin messages
|
||||||
|
const [showSecretVideo, setShowSecretVideo] = useState(false); // New state for secret video
|
||||||
|
|
||||||
// Admin user ID from .env
|
// Admin user ID from .env
|
||||||
const CLERK_ADMIN_USERID = import.meta.env.VITE_CLERK_ADMIN_USERID;
|
const CLERK_ADMIN_USERID = import.meta.env.VITE_CLERK_ADMIN_USERID;
|
||||||
@@ -53,6 +55,13 @@ function App() {
|
|||||||
}
|
}
|
||||||
}, [gameState, previousMilestones]);
|
}, [gameState, previousMilestones]);
|
||||||
|
|
||||||
|
// Effect for secret video
|
||||||
|
useEffect(() => {
|
||||||
|
if (gameState?.upgrades['secretVideo']?.owned > 0) {
|
||||||
|
setShowSecretVideo(true);
|
||||||
|
}
|
||||||
|
}, [gameState?.upgrades['secretVideo']?.owned]);
|
||||||
|
|
||||||
// Effect for receiving admin broadcast messages
|
// Effect for receiving admin broadcast messages
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (lastMessage) {
|
if (lastMessage) {
|
||||||
@@ -86,7 +95,7 @@ function App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ownedFriendBoost > 0 && friendBoostUpgrade && friendBoostUpgrade.mascotTiers) {
|
if (ownedFriendBoost > 0 && friendBoostUpgrade && friendBoostUpgrade.mascotTiers) {
|
||||||
const baseInterval = 12000; // Increased base interval for less frequent spawns
|
const baseInterval = 18000; // Further increased base interval for less frequent spawns
|
||||||
const minInterval = 1000; // Increased min interval
|
const minInterval = 1000; // Increased min interval
|
||||||
const interval = Math.max(minInterval, baseInterval / (1 + ownedFriendBoost * 0.2)); // Adjusted scaling
|
const interval = Math.max(minInterval, baseInterval / (1 + ownedFriendBoost * 0.2)); // Adjusted scaling
|
||||||
console.log(`Spawning mascots every ${interval} ms for friendBoost level ${ownedFriendBoost}`);
|
console.log(`Spawning mascots every ${interval} ms for friendBoost level ${ownedFriendBoost}`);
|
||||||
@@ -99,25 +108,13 @@ function App() {
|
|||||||
const currentGameState = gameStateRef.current;
|
const currentGameState = gameStateRef.current;
|
||||||
if (!currentGameState) return; // Should not happen if initial check passes
|
if (!currentGameState) return; // Should not happen if initial check passes
|
||||||
|
|
||||||
const buttonContainer = clickButtonContainerRef.current; // Use the ref
|
|
||||||
if (!buttonContainer) {
|
|
||||||
console.warn('Click button container ref not found!');
|
|
||||||
timeoutRef.current = setTimeout(spawnMascot, 1000); // Retry after 1 second
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const rect = buttonContainer.getBoundingClientRect();
|
|
||||||
const spawnAreaPadding = 150;
|
|
||||||
const minX = rect.left - spawnAreaPadding;
|
|
||||||
const maxX = rect.right + spawnAreaPadding;
|
|
||||||
const minY = rect.top - spawnAreaPadding;
|
|
||||||
const maxY = rect.bottom + spawnAreaPadding;
|
|
||||||
|
|
||||||
const viewportWidth = window.innerWidth;
|
const viewportWidth = window.innerWidth;
|
||||||
const viewportHeight = window.innerHeight;
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
const randomX = Math.max(0, Math.min(viewportWidth, minX + Math.random() * (maxX - minX)));
|
// Spawn anywhere on the viewport, with a small padding to avoid edges
|
||||||
const randomY = Math.max(0, Math.min(viewportHeight, minY + Math.random() * (maxY - minY)));
|
const padding = 50;
|
||||||
|
const randomX = Math.random() * (viewportWidth - padding * 2) + padding;
|
||||||
|
const randomY = Math.random() * (viewportHeight - padding * 2) + padding;
|
||||||
|
|
||||||
// Filter available mascots based on ownedFriendBoost level
|
// Filter available mascots based on ownedFriendBoost level
|
||||||
const availableMascots = currentMascotTiers.filter(
|
const availableMascots = currentMascotTiers.filter(
|
||||||
@@ -248,7 +245,7 @@ function App() {
|
|||||||
{/* Main Content */}
|
{/* Main Content */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
{/* Left Column - Click Button */}
|
{/* Left Column - Click Button */}
|
||||||
<div ref={clickButtonContainerRef} id="click-button-container" className="lg:col-span-1 flex flex-col items-center justify-center relative"> {/* Added ref, id and relative positioning */}
|
<div id="click-button-container" className="lg:col-span-1 flex flex-col items-center justify-center relative"> {/* Added ref, id and relative positioning */}
|
||||||
<ClickButton
|
<ClickButton
|
||||||
onClick={sendClick}
|
onClick={sendClick}
|
||||||
imageUrl={gameState.currentClickImage}
|
imageUrl={gameState.currentClickImage}
|
||||||
@@ -298,6 +295,22 @@ function App() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Secret Video Player */}
|
||||||
|
{showSecretVideo && (
|
||||||
|
<div className="fixed bottom-4 left-4 z-50">
|
||||||
|
<YouTube
|
||||||
|
videoId={UPGRADES.find(u => u.id === 'secretVideo')?.youtubeId || ''}
|
||||||
|
opts={{
|
||||||
|
height: '195',
|
||||||
|
width: '320',
|
||||||
|
playerVars: {
|
||||||
|
autoplay: 1,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Sparkle Effects */}
|
{/* Sparkle Effects */}
|
||||||
<div className="fixed inset-0 pointer-events-none z-20">
|
<div className="fixed inset-0 pointer-events-none z-20">
|
||||||
{[...Array(10)].map((_, i) => (
|
{[...Array(10)].map((_, i) => (
|
||||||
|
|||||||
@@ -124,5 +124,15 @@ export const UPGRADES: Upgrade[] = [
|
|||||||
`om`,
|
`om`,
|
||||||
`You are the Glue to my life like how Tokai Teio is glue(stick) to a child's art project`,
|
`You are the Glue to my life like how Tokai Teio is glue(stick) to a child's art project`,
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'secretVideo',
|
||||||
|
name: '🎬 Secret Video',
|
||||||
|
description: 'Unlock a secret video. Plays automatically!',
|
||||||
|
baseCost: 1000000, // Very expensive
|
||||||
|
multiplier: 1,
|
||||||
|
icon: '🎬',
|
||||||
|
oneTime: true,
|
||||||
|
youtubeId: 'ONzntmMFXGE' // The YouTube video ID
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user