diff --git a/packages/frontend/src/game/HUD/components/crosshairs/Line.tsx b/packages/frontend/src/game/HUD/components/crosshairs/Line.tsx index 7f97d99..a5f1fec 100644 --- a/packages/frontend/src/game/HUD/components/crosshairs/Line.tsx +++ b/packages/frontend/src/game/HUD/components/crosshairs/Line.tsx @@ -97,6 +97,42 @@ const crossHairDimensions = (playerState: PlayerState): LineOptions => { length: 10, spacing: { max: 120, min: 40 }, }; + // TODO: Set up correct sizes for different weapon classes https://app.clickup.com/t/86b5vm3cc + case "Submachine Gun": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; + case "Shotgun": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; + case "Sniper Rifle": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; + case "Pistol": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; + case "Melee": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; + case "Rocket Launcher": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; + case "Special": + return { + length: 10, + spacing: { max: 120, min: 40 }, + }; default: return assertNever(weaponClass); } diff --git a/packages/frontend/src/game/weapons/functions/renderWeapon.tsx b/packages/frontend/src/game/weapons/functions/renderWeapon.tsx index a709f62..e46dc8a 100644 --- a/packages/frontend/src/game/weapons/functions/renderWeapon.tsx +++ b/packages/frontend/src/game/weapons/functions/renderWeapon.tsx @@ -3,8 +3,15 @@ import { useIsAlive } from "../../player/hooks/useIsAlive"; import type { GamePlayerState } from "../../utils/geckos/geckos"; // Import Weapons Below: -import { AK47 } from "../primary/AK47/AK47"; -import { Saiga } from "../primary/Saiga/Saiga"; +import { AK47 } from "../weapons/primary/AK47/AK47"; +import { AWP } from "../weapons/primary/AWP/AWP"; +import { FiveSeven } from "../weapons/secondary/FiveSeven/FiveSeven"; +import { Knife } from "../weapons/melee/Knife"; +import { M203 } from "../weapons/secondary/M203/M203"; +import { Nova } from "../weapons/primary/Nova/Nova"; +import { RPG } from "../weapons/secondary/RPG/RPG"; +import { Saiga } from "../weapons/primary/Saiga/Saiga"; +import { Scorpion } from "../weapons/primary/Scorpion/Scorpion"; interface RenderWeaponProps { playerStateRef: React.MutableRefObject; @@ -17,10 +24,32 @@ export const RenderWeapon: React.FC = ({ playerStateRef }) => if (!isAlive) return null; switch (player.currentWeapon) { + // Assault Rifles case "AK47": return ; case "Saiga": return ; + // SMGs + case "Scorpion": + return ; + // Shotguns + case "Nova": + return ; + // Sniper Rifles + case "AWP": + return ; + // Pistols + case "FiveSeven": + return ; + // Rocket Launchers + case "RPG": + return ; + // Special Weapons + case "M203": + return ; + // Melee Weapons + case "Knife": + return ; // TODO: Bring back assertNever https://app.clickup.com/t/86b5v1m7h } diff --git a/packages/frontend/src/game/weapons/weapons/melee/Knife.tsx b/packages/frontend/src/game/weapons/weapons/melee/Knife.tsx new file mode 100644 index 0000000..00c3d44 --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/melee/Knife.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface KnifeProps { + playerStateRef: React.MutableRefObject; +} + +export const Knife: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/frontend/src/game/weapons/primary/AK47/AK47.mp3 b/packages/frontend/src/game/weapons/weapons/primary/AK47/AK47.mp3 similarity index 100% rename from packages/frontend/src/game/weapons/primary/AK47/AK47.mp3 rename to packages/frontend/src/game/weapons/weapons/primary/AK47/AK47.mp3 diff --git a/packages/frontend/src/game/weapons/primary/AK47/AK47.tsx b/packages/frontend/src/game/weapons/weapons/primary/AK47/AK47.tsx similarity index 91% rename from packages/frontend/src/game/weapons/primary/AK47/AK47.tsx rename to packages/frontend/src/game/weapons/weapons/primary/AK47/AK47.tsx index 63fe068..b4f1b09 100644 --- a/packages/frontend/src/game/weapons/primary/AK47/AK47.tsx +++ b/packages/frontend/src/game/weapons/weapons/primary/AK47/AK47.tsx @@ -1,10 +1,10 @@ import React from "react"; import ShootSound from "./AK47.mp3"; -import { GamePlayerState } from "../../../utils/geckos/geckos"; -import { PUBLIC_PATHS } from "../../../constants/publicPaths"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; import { useGLTF } from "@react-three/drei"; import { Vector3 } from "three"; -import { WeaponChild } from "../../WeaponChild"; +import { WeaponChild } from "../../../WeaponChild"; import { WEAPONS } from "@fps/lib"; interface AK47Props { diff --git a/packages/frontend/src/game/weapons/weapons/primary/AWP/AWP.tsx b/packages/frontend/src/game/weapons/weapons/primary/AWP/AWP.tsx new file mode 100644 index 0000000..3e9f870 --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/primary/AWP/AWP.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface AWPProps { + playerStateRef: React.MutableRefObject; +} + +export const AWP: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/frontend/src/game/weapons/weapons/primary/Nova/Nova.tsx b/packages/frontend/src/game/weapons/weapons/primary/Nova/Nova.tsx new file mode 100644 index 0000000..82c2292 --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/primary/Nova/Nova.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface NovaProps { + playerStateRef: React.MutableRefObject; +} + +export const Nova: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/frontend/src/game/weapons/primary/Saiga/Saiga.tsx b/packages/frontend/src/game/weapons/weapons/primary/Saiga/Saiga.tsx similarity index 88% rename from packages/frontend/src/game/weapons/primary/Saiga/Saiga.tsx rename to packages/frontend/src/game/weapons/weapons/primary/Saiga/Saiga.tsx index c042c0c..571dffb 100644 --- a/packages/frontend/src/game/weapons/primary/Saiga/Saiga.tsx +++ b/packages/frontend/src/game/weapons/weapons/primary/Saiga/Saiga.tsx @@ -1,10 +1,9 @@ import React from "react"; -import ShootSound from "../AK47/AK47.mp3"; -import { GamePlayerState } from "../../../utils/geckos/geckos"; -import { PUBLIC_PATHS } from "../../../constants/publicPaths"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; import { useGLTF } from "@react-three/drei"; import { Vector3 } from "three"; -import { WeaponChild } from "../../WeaponChild"; +import { WeaponChild } from "../../../WeaponChild"; import { WEAPONS } from "@fps/lib"; interface SaigaProps { @@ -51,7 +50,7 @@ export const Saiga: React.FC = ({ playerStateRef }) => { meshPath={PUBLIC_PATHS.weapons.Saiga} playerStateRef={playerStateRef} scale={0.01} - shootBufferUrl={ShootSound} + shootBufferUrl={""} stats={WEAPONS.Saiga} /> ); diff --git a/packages/frontend/src/game/weapons/weapons/primary/Scorpion/Scorpion.tsx b/packages/frontend/src/game/weapons/weapons/primary/Scorpion/Scorpion.tsx new file mode 100644 index 0000000..df947df --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/primary/Scorpion/Scorpion.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface ScorpionProps { + playerStateRef: React.MutableRefObject; +} + +export const Scorpion: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/frontend/src/game/weapons/weapons/secondary/FiveSeven/FiveSeven.tsx b/packages/frontend/src/game/weapons/weapons/secondary/FiveSeven/FiveSeven.tsx new file mode 100644 index 0000000..8deba15 --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/secondary/FiveSeven/FiveSeven.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface FiveSevenProps { + playerStateRef: React.MutableRefObject; +} + +export const FiveSeven: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/frontend/src/game/weapons/weapons/secondary/M203/M203.tsx b/packages/frontend/src/game/weapons/weapons/secondary/M203/M203.tsx new file mode 100644 index 0000000..8b806f1 --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/secondary/M203/M203.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface M203Props { + playerStateRef: React.MutableRefObject; +} + +export const M203: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/frontend/src/game/weapons/weapons/secondary/RPG/RPG.tsx b/packages/frontend/src/game/weapons/weapons/secondary/RPG/RPG.tsx new file mode 100644 index 0000000..4ffb440 --- /dev/null +++ b/packages/frontend/src/game/weapons/weapons/secondary/RPG/RPG.tsx @@ -0,0 +1,59 @@ +import React from "react"; +import { GamePlayerState } from "../../../../utils/geckos/geckos"; +import { PUBLIC_PATHS } from "../../../../constants/publicPaths"; +import { useGLTF } from "@react-three/drei"; +import { Vector3 } from "three"; +import { WeaponChild } from "../../../WeaponChild"; +import { WEAPONS } from "@fps/lib"; + +interface RPGProps { + playerStateRef: React.MutableRefObject; +} + +export const RPG: React.FC = ({ playerStateRef }) => { + return ( + + ); +}; + +useGLTF.preload(PUBLIC_PATHS.weapons.Saiga); // TODO: https://app.clickup.com/t/86b5vk9q1 diff --git a/packages/lib/src/functions/damagePerShot.ts b/packages/lib/src/functions/damagePerShot.ts index 45e40b7..a138aa7 100644 --- a/packages/lib/src/functions/damagePerShot.ts +++ b/packages/lib/src/functions/damagePerShot.ts @@ -29,8 +29,43 @@ export const damagePerShot = (params: DamagePerShotParams) => { dropOff.maxDamageDropoffRange = 50; dropOff.minDamageDropoffRange = 20; break; + case "Submachine Gun": + dropOff.maxDamageDropoffFromRange = 0.5; + dropOff.maxDamageDropoffRange = 30; + dropOff.minDamageDropoffRange = 10; + break; + case "Shotgun": + dropOff.maxDamageDropoffFromRange = 0.3; + dropOff.maxDamageDropoffRange = 20; + dropOff.minDamageDropoffRange = 5; + break; + case "Sniper Rifle": + dropOff.maxDamageDropoffFromRange = 0.95; + dropOff.maxDamageDropoffRange = 100; + dropOff.minDamageDropoffRange = 50; + break; + case "Pistol": + dropOff.maxDamageDropoffFromRange = 0.6; + dropOff.maxDamageDropoffRange = 25; + dropOff.minDamageDropoffRange = 5; + break; + case "Melee": + dropOff.maxDamageDropoffFromRange = 1; // No dropoff for melee + dropOff.maxDamageDropoffRange = 0; // No range for melee + dropOff.minDamageDropoffRange = 0; // No range for melee + break; + case "Rocket Launcher": + dropOff.maxDamageDropoffFromRange = 1; // No dropoff for rocket launcher + dropOff.maxDamageDropoffRange = 0; // No range for rocket launcher + dropOff.minDamageDropoffRange = 0; // No range for rocket launcher + break; + case "Special": + dropOff.maxDamageDropoffFromRange = 0.5; + dropOff.maxDamageDropoffRange = 30; + dropOff.minDamageDropoffRange = 10; + break; default: - assertNever(weapon.weaponClass); + assertNever(weapon); break; } diff --git a/packages/lib/src/objects/weapon.ts b/packages/lib/src/objects/weapon.ts index 0b0dbfa..b70037c 100644 --- a/packages/lib/src/objects/weapon.ts +++ b/packages/lib/src/objects/weapon.ts @@ -1,4 +1,4 @@ -export type WeaponType = "Primary" | "Secondary" | "Other"; +export type WeaponType = "Primary" | "Secondary" | "Melee" | "Other"; export type WeaponClass = | "Submachine Gun" @@ -7,12 +7,12 @@ export type WeaponClass = | "Sniper Rifle" | "Pistol" | "Rocket Launcher" - | "Grenade Launcher" + | "Special" // Crossbow, Riot Shield, etc. | "Melee"; export type FiringMode = "Single" | "Burst" | "Auto"; -export type DamageType = "Ballistic" | "Explosive" | "Melee"; +export type DamageType = "Ballistic" | "Explosive" | "Melee" | "Gas"; export type Recoil = { horizontal: number; // Side to side recoil @@ -45,6 +45,7 @@ export interface WeaponStats { // All weapons with their stats export const WEAPONS = { + // * ASSAULT RIFLES AK47: { adsTimeMs: 0, bulletSpread: 0, @@ -89,6 +90,167 @@ export const WEAPONS = { weaponType: "Primary", weight: 1, }, + // * SMGS + Scorpion: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 30, + bulletsPerShot: 1, + damageType: "Ballistic", + displayName: "Scorpion EVO", + fireRateMs: 30, + firingMode: "Auto", + maxDamagePerBullet: 25, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 2000, + reserveAmmo: 150, + sprintToFireTimeMs: 150, + weaponClass: "Submachine Gun", + weaponType: "Primary", + weight: 1, + }, + // * SHOTGUNS + Nova: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 6, + bulletsPerShot: 5, + damageType: "Ballistic", + displayName: "Nova", + fireRateMs: 4800, + firingMode: "Single", + maxDamagePerBullet: 25, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 3000, + reserveAmmo: 30, + sprintToFireTimeMs: 200, + weaponClass: "Shotgun", + weaponType: "Primary", + weight: 1, + }, + // SNIPER RIFLES + AWP: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 5, + bulletsPerShot: 1, + damageType: "Ballistic", + displayName: "AWP", + fireRateMs: 6000, + firingMode: "Single", + maxDamagePerBullet: 150, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 3000, + reserveAmmo: 30, + sprintToFireTimeMs: 400, + weaponClass: "Sniper Rifle", + weaponType: "Primary", + weight: 1, + }, + // PISTOLS + FiveSeven: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 12, + bulletsPerShot: 1, + damageType: "Ballistic", + displayName: "Five Seven", + fireRateMs: 680, + firingMode: "Single", + maxDamagePerBullet: 35, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 1500, + reserveAmmo: 60, + sprintToFireTimeMs: 100, + weaponClass: "Pistol", + weaponType: "Secondary", + weight: 1, + }, + // ROCKET LAUNCHERS + RPG: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 1, + bulletsPerShot: 1, + damageType: "Explosive", + displayName: "RPG-7", + fireRateMs: 680, + firingMode: "Single", + maxDamagePerBullet: 400, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 2500, + reserveAmmo: 3, + sprintToFireTimeMs: 500, + weaponClass: "Rocket Launcher", + weaponType: "Secondary", + weight: 1, + }, + // SPECIAL WEAPONS + M203: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 6, + bulletsPerShot: 1, + damageType: "Gas", + displayName: "M203 Teargas Launcher", + fireRateMs: 3000, + firingMode: "Single", + maxDamagePerBullet: 20, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 2000, + reserveAmmo: 6, + sprintToFireTimeMs: 300, + weaponClass: "Special", + weaponType: "Secondary", + weight: 1, + }, + // MELEE WEAPONS + Knife: { + adsTimeMs: 0, + bulletSpread: 0, + bulletsPerMagazine: 0, + bulletsPerShot: 0, + damageType: "Melee", + displayName: "Knife", + fireRateMs: 2000, + firingMode: "Single", + maxDamagePerBullet: 200, + recoil: { + horizontal: 0.01, + kickback: 0.1, + vertical: 0.008, + }, + reloadTimeMs: 2000, + reserveAmmo: 6, + sprintToFireTimeMs: 300, + weaponClass: "Melee", + weaponType: "Melee", + weight: 1, + }, // TODO: Remove this, its just here to get the linter to stop yelling about unnecessary checks https://app.clickup.com/t/86b5v1xmm Test: {