├── config ├── .htmlhintrc.json ├── .stylelintrc.json └── .eslintrc.js ├── public ├── img │ ├── mortar.png │ ├── target.png │ ├── weapons │ │ ├── M109.png │ │ ├── Mk19.png │ │ ├── HIMARS.png │ │ ├── Mortar.png │ │ ├── TOS-1A.png │ │ ├── UB-32.png │ │ ├── BM-21Grad.png │ │ ├── BTR4-AGS.png │ │ ├── M1064M121.png │ │ ├── default.png │ │ ├── 120mm_white.png │ │ ├── HellCannon.png │ │ ├── MTLB_FAB500.png │ │ ├── Tech.Mortar.png │ │ ├── Tech.UB-32.png │ │ └── T62.DUMP.TRUCK.png │ └── markers │ │ ├── weapons │ │ ├── M109.webp │ │ ├── Mk19.webp │ │ ├── UB-32.webp │ │ ├── test.webp │ │ ├── HIMARS.webp │ │ ├── Mortar.webp │ │ ├── TOS-1A.webp │ │ ├── BM-21Grad.webp │ │ ├── BTR4-AGS.webp │ │ ├── HellCannon.webp │ │ ├── M1064M121.webp │ │ ├── Tech.UB-32.webp │ │ ├── MTLB_FAB500.webp │ │ ├── Tech.Mortar.webp │ │ ├── T62.DUMP.TRUCK.webp │ │ ├── marker_mortar_1.webp │ │ ├── marker_mortar_2.webp │ │ └── marker_shadow.webp │ │ └── targets │ │ ├── marker_target_mini.webp │ │ ├── marker_target_disabled.webp │ │ ├── marker_target_enabled.webp │ │ ├── marker_target_disabled_mini.webp │ │ ├── marker_target_session_mini.webp │ │ ├── marker_target_disabled_backup.webp │ │ ├── marker_target_enabled_backup.webp │ │ ├── marker_target_enabled_chrismas.webp │ │ ├── marker_target_session_enabled.webp │ │ └── marker_target_session_enabled_backup.webp ├── sounds │ ├── de │ │ ├── drone.mp3 │ │ ├── map_ifv.mp3 │ │ ├── map_jeep.mp3 │ │ ├── map_tank.mp3 │ │ ├── T_map_mgs.mp3 │ │ ├── commander.mp3 │ │ ├── map_antiair.mp3 │ │ ├── map_jeep_turret.mp3 │ │ ├── map_motorcycle.mp3 │ │ ├── map_trackedapc.mp3 │ │ ├── map_trackedifv.mp3 │ │ ├── map_trackedjeep.mp3 │ │ ├── T_map_jeep_antiair.mp3 │ │ ├── T_map_trackedrecon.mp3 │ │ ├── map_jeep_antitank.mp3 │ │ ├── map_jeep_artillery.mp3 │ │ ├── map_jeep_logistics.mp3 │ │ ├── map_jeep_transport.mp3 │ │ ├── map_transporthelo.mp3 │ │ ├── map_truck_antiair.mp3 │ │ ├── T_map_boat_logistics.mp3 │ │ ├── T_map_boat_openturret.mp3 │ │ ├── T_map_trackedapc_msv.mp3 │ │ ├── T_map_truck_artillery.mp3 │ │ ├── map_truck_logistics.mp3 │ │ ├── map_truck_transport.mp3 │ │ ├── T_map_helicopter_scout.mp3 │ │ ├── T_map_trackedapc_artillery.mp3 │ │ └── T_map_trackedapc_logistics.mp3 │ ├── en │ │ ├── drone.mp3 │ │ ├── map_ifv.mp3 │ │ ├── map_jeep.mp3 │ │ ├── map_tank.mp3 │ │ ├── T_map_mgs.mp3 │ │ ├── commander.mp3 │ │ ├── map_antiair.mp3 │ │ ├── map_jeep_turret.mp3 │ │ ├── map_motorcycle.mp3 │ │ ├── map_trackedapc.mp3 │ │ ├── map_trackedifv.mp3 │ │ ├── map_trackedjeep.mp3 │ │ ├── T_map_jeep_antiair.mp3 │ │ ├── T_map_trackedrecon.mp3 │ │ ├── map_jeep_antitank.mp3 │ │ ├── map_jeep_artillery.mp3 │ │ ├── map_jeep_logistics.mp3 │ │ ├── map_jeep_transport.mp3 │ │ ├── map_transporthelo.mp3 │ │ ├── map_truck_antiair.mp3 │ │ ├── T_map_boat_logistics.mp3 │ │ ├── T_map_boat_openturret.mp3 │ │ ├── T_map_trackedapc_msv.mp3 │ │ ├── T_map_truck_artillery.mp3 │ │ ├── map_truck_logistics.mp3 │ │ ├── map_truck_transport.mp3 │ │ ├── T_map_helicopter_scout.mp3 │ │ ├── T_map_trackedapc_artillery.mp3 │ │ └── T_map_trackedapc_logistics.mp3 │ ├── fr │ │ ├── drone.mp3 │ │ ├── map_ifv.mp3 │ │ ├── map_jeep.mp3 │ │ ├── map_tank.mp3 │ │ ├── T_map_mgs.mp3 │ │ ├── commander.mp3 │ │ ├── map_antiair.mp3 │ │ ├── map_jeep_turret.mp3 │ │ ├── map_motorcycle.mp3 │ │ ├── map_trackedapc.mp3 │ │ ├── map_trackedifv.mp3 │ │ ├── map_trackedjeep.mp3 │ │ ├── T_map_jeep_antiair.mp3 │ │ ├── T_map_trackedrecon.mp3 │ │ ├── map_jeep_antitank.mp3 │ │ ├── map_jeep_artillery.mp3 │ │ ├── map_jeep_logistics.mp3 │ │ ├── map_jeep_transport.mp3 │ │ ├── map_transporthelo.mp3 │ │ ├── map_truck_antiair.mp3 │ │ ├── T_map_boat_logistics.mp3 │ │ ├── T_map_boat_openturret.mp3 │ │ ├── T_map_trackedapc_msv.mp3 │ │ ├── T_map_truck_artillery.mp3 │ │ ├── map_truck_logistics.mp3 │ │ ├── map_truck_transport.mp3 │ │ ├── T_map_helicopter_scout.mp3 │ │ ├── T_map_trackedapc_artillery.mp3 │ │ └── T_map_trackedapc_logistics.mp3 │ ├── ru │ │ ├── drone.mp3 │ │ ├── map_ifv.mp3 │ │ ├── map_jeep.mp3 │ │ ├── map_tank.mp3 │ │ ├── T_map_mgs.mp3 │ │ ├── commander.mp3 │ │ ├── map_antiair.mp3 │ │ ├── map_jeep_turret.mp3 │ │ ├── map_motorcycle.mp3 │ │ ├── map_trackedapc.mp3 │ │ ├── map_trackedifv.mp3 │ │ ├── map_trackedjeep.mp3 │ │ ├── T_map_jeep_antiair.mp3 │ │ ├── T_map_trackedrecon.mp3 │ │ ├── map_jeep_antitank.mp3 │ │ ├── map_jeep_artillery.mp3 │ │ ├── map_jeep_logistics.mp3 │ │ ├── map_jeep_transport.mp3 │ │ ├── map_transporthelo.mp3 │ │ ├── map_truck_antiair.mp3 │ │ ├── T_map_boat_logistics.mp3 │ │ ├── T_map_boat_openturret.mp3 │ │ ├── T_map_trackedapc_msv.mp3 │ │ ├── T_map_truck_artillery.mp3 │ │ ├── map_truck_logistics.mp3 │ │ ├── map_truck_transport.mp3 │ │ ├── T_map_helicopter_scout.mp3 │ │ ├── T_map_trackedapc_artillery.mp3 │ │ └── T_map_trackedapc_logistics.mp3 │ ├── uk │ │ ├── drone.mp3 │ │ ├── map_ifv.mp3 │ │ ├── map_jeep.mp3 │ │ ├── map_tank.mp3 │ │ ├── T_map_mgs.mp3 │ │ ├── commander.mp3 │ │ ├── map_antiair.mp3 │ │ ├── map_jeep_turret.mp3 │ │ ├── map_motorcycle.mp3 │ │ ├── map_trackedapc.mp3 │ │ ├── map_trackedifv.mp3 │ │ ├── map_trackedjeep.mp3 │ │ ├── T_map_jeep_antiair.mp3 │ │ ├── T_map_trackedrecon.mp3 │ │ ├── map_jeep_antitank.mp3 │ │ ├── map_jeep_artillery.mp3 │ │ ├── map_jeep_logistics.mp3 │ │ ├── map_jeep_transport.mp3 │ │ ├── map_transporthelo.mp3 │ │ ├── map_truck_antiair.mp3 │ │ ├── T_map_boat_logistics.mp3 │ │ ├── T_map_boat_openturret.mp3 │ │ ├── T_map_trackedapc_msv.mp3 │ │ ├── T_map_truck_artillery.mp3 │ │ ├── map_truck_logistics.mp3 │ │ ├── map_truck_transport.mp3 │ │ ├── T_map_helicopter_scout.mp3 │ │ ├── T_map_trackedapc_artillery.mp3 │ │ └── T_map_trackedapc_logistics.mp3 │ ├── zh │ │ ├── drone.mp3 │ │ ├── map_ifv.mp3 │ │ ├── map_jeep.mp3 │ │ ├── map_tank.mp3 │ │ ├── T_map_mgs.mp3 │ │ ├── commander.mp3 │ │ ├── map_antiair.mp3 │ │ ├── map_jeep_turret.mp3 │ │ ├── map_motorcycle.mp3 │ │ ├── map_trackedapc.mp3 │ │ ├── map_trackedifv.mp3 │ │ ├── map_trackedjeep.mp3 │ │ ├── T_map_jeep_antiair.mp3 │ │ ├── T_map_trackedrecon.mp3 │ │ ├── map_jeep_antitank.mp3 │ │ ├── map_jeep_artillery.mp3 │ │ ├── map_jeep_logistics.mp3 │ │ ├── map_jeep_transport.mp3 │ │ ├── map_transporthelo.mp3 │ │ ├── map_truck_antiair.mp3 │ │ ├── T_map_boat_logistics.mp3 │ │ ├── T_map_boat_openturret.mp3 │ │ ├── T_map_trackedapc_msv.mp3 │ │ ├── T_map_truck_artillery.mp3 │ │ ├── map_truck_logistics.mp3 │ │ ├── map_truck_transport.mp3 │ │ ├── T_map_helicopter_scout.mp3 │ │ ├── T_map_trackedapc_artillery.mp3 │ │ └── T_map_trackedapc_logistics.mp3 │ └── LICENCE.txt └── locales │ ├── zh │ ├── weapons.json │ ├── maps.json │ ├── factions.json │ ├── settings.json │ ├── common.json │ ├── tooltips.json │ └── units.json │ ├── en │ ├── weapons.json │ ├── maps.json │ ├── factions.json │ ├── settings.json │ └── common.json │ ├── fr │ ├── weapons.json │ ├── maps.json │ ├── factions.json │ ├── common.json │ └── settings.json │ ├── de │ ├── weapons.json │ ├── maps.json │ ├── factions.json │ ├── common.json │ └── settings.json │ ├── ru │ ├── weapons.json │ ├── maps.json │ ├── factions.json │ ├── common.json │ └── settings.json │ └── uk │ ├── weapons.json │ ├── maps.json │ ├── factions.json │ ├── common.json │ └── settings.json ├── src ├── img │ ├── github │ │ ├── logo.webp │ │ ├── borders.webp │ │ ├── hdmaps.webp │ │ ├── heatmap.webp │ │ ├── layers.webp │ │ ├── mains.webp │ │ ├── mobile.webp │ │ ├── servers.webp │ │ ├── spawns.gif │ │ ├── timer.webp │ │ ├── units.webp │ │ ├── capzones.webp │ │ ├── mobile_ui.webp │ │ ├── radiuses.webp │ │ ├── sessions.webp │ │ ├── settings.webp │ │ ├── autocomplete.gif │ │ ├── desktop_ui_0.webp │ │ ├── desktop_ui_1.webp │ │ ├── desktop_ui_2.webp │ │ ├── desktop_ui_3.webp │ │ ├── desktop_ui_4.webp │ │ ├── desktop_ui_5.webp │ │ ├── desktop_ui_6.webp │ │ ├── desktop_ui_7.webp │ │ ├── layer-finder.gif │ │ ├── mainCtxMenu.webp │ │ ├── simulation.webp │ │ ├── import_export.webp │ │ ├── weaponInformation.webp │ │ └── squadmortaroverlay.webp │ └── favicons │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── favicon_256x256.png │ │ ├── favicon_512x512.png │ │ └── maskable_icon_x512.png ├── js │ ├── libs │ │ ├── readme │ │ ├── leaflet-edgebuffer.js │ │ ├── leaflet-spin.js │ │ ├── leaflet-rotatedMarker.js │ │ ├── leaflet-visual-click.js │ │ ├── leaflet-smoothWheelZoom.js │ │ └── pure-snow.js │ ├── sw.js │ ├── squadHeightmaps.js │ ├── squadIcon.js │ ├── squadCameraActor.js │ └── animations.js ├── components │ ├── shared │ │ ├── snow.scss │ │ └── _tooltips.scss │ ├── dialogs │ │ ├── servers.html │ │ ├── factions.html │ │ ├── weapon.html │ │ └── target.html │ ├── map │ │ ├── mapLogo.scss │ │ └── mapObjectives.scss │ ├── header │ │ ├── header.html │ │ └── header.scss │ ├── contextMenu │ │ └── contextMenu.scss │ └── legacyui │ │ ├── legacyui.scss │ │ └── legacyui.html ├── app.js └── index.html ├── .gitignore ├── .github ├── dependabot.yml └── workflows │ ├── deploy_preprod.yml │ └── deploy_prod.yml ├── SECURITY.md ├── .env.template ├── CONTRIBUTING.md ├── LICENSE └── package.json /config/.htmlhintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "spec-char-escape": false 4 | } 5 | } -------------------------------------------------------------------------------- /public/img/mortar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/mortar.png -------------------------------------------------------------------------------- /public/img/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/target.png -------------------------------------------------------------------------------- /src/img/github/logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/logo.webp -------------------------------------------------------------------------------- /public/img/weapons/M109.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/M109.png -------------------------------------------------------------------------------- /public/img/weapons/Mk19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/Mk19.png -------------------------------------------------------------------------------- /public/sounds/de/drone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/drone.mp3 -------------------------------------------------------------------------------- /public/sounds/en/drone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/drone.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/drone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/drone.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/drone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/drone.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/drone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/drone.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/drone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/drone.mp3 -------------------------------------------------------------------------------- /src/img/github/borders.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/borders.webp -------------------------------------------------------------------------------- /src/img/github/hdmaps.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/hdmaps.webp -------------------------------------------------------------------------------- /src/img/github/heatmap.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/heatmap.webp -------------------------------------------------------------------------------- /src/img/github/layers.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/layers.webp -------------------------------------------------------------------------------- /src/img/github/mains.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/mains.webp -------------------------------------------------------------------------------- /src/img/github/mobile.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/mobile.webp -------------------------------------------------------------------------------- /src/img/github/servers.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/servers.webp -------------------------------------------------------------------------------- /src/img/github/spawns.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/spawns.gif -------------------------------------------------------------------------------- /src/img/github/timer.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/timer.webp -------------------------------------------------------------------------------- /src/img/github/units.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/units.webp -------------------------------------------------------------------------------- /public/img/weapons/HIMARS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/HIMARS.png -------------------------------------------------------------------------------- /public/img/weapons/Mortar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/Mortar.png -------------------------------------------------------------------------------- /public/img/weapons/TOS-1A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/TOS-1A.png -------------------------------------------------------------------------------- /public/img/weapons/UB-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/UB-32.png -------------------------------------------------------------------------------- /public/sounds/de/map_ifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_ifv.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_jeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_jeep.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_tank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_tank.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_ifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_ifv.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_jeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_jeep.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_tank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_tank.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_ifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_ifv.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_jeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_jeep.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_tank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_tank.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_ifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_ifv.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_jeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_jeep.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_tank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_tank.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_ifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_ifv.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_jeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_jeep.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_tank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_tank.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_ifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_ifv.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_jeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_jeep.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_tank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_tank.mp3 -------------------------------------------------------------------------------- /src/img/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/favicons/favicon.ico -------------------------------------------------------------------------------- /src/img/favicons/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/favicons/favicon.png -------------------------------------------------------------------------------- /src/img/github/capzones.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/capzones.webp -------------------------------------------------------------------------------- /src/img/github/mobile_ui.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/mobile_ui.webp -------------------------------------------------------------------------------- /src/img/github/radiuses.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/radiuses.webp -------------------------------------------------------------------------------- /src/img/github/sessions.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/sessions.webp -------------------------------------------------------------------------------- /src/img/github/settings.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/settings.webp -------------------------------------------------------------------------------- /public/img/weapons/BM-21Grad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/BM-21Grad.png -------------------------------------------------------------------------------- /public/img/weapons/BTR4-AGS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/BTR4-AGS.png -------------------------------------------------------------------------------- /public/img/weapons/M1064M121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/M1064M121.png -------------------------------------------------------------------------------- /public/img/weapons/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/default.png -------------------------------------------------------------------------------- /public/sounds/de/T_map_mgs.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_mgs.mp3 -------------------------------------------------------------------------------- /public/sounds/de/commander.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/commander.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_mgs.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_mgs.mp3 -------------------------------------------------------------------------------- /public/sounds/en/commander.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/commander.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_mgs.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_mgs.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/commander.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/commander.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_mgs.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_mgs.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/commander.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/commander.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_mgs.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_mgs.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/commander.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/commander.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_mgs.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_mgs.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/commander.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/commander.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_antiair.mp3 -------------------------------------------------------------------------------- /src/img/github/autocomplete.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/autocomplete.gif -------------------------------------------------------------------------------- /src/img/github/desktop_ui_0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_0.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_1.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_2.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_3.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_3.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_4.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_4.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_5.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_5.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_6.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_6.webp -------------------------------------------------------------------------------- /src/img/github/desktop_ui_7.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/desktop_ui_7.webp -------------------------------------------------------------------------------- /src/img/github/layer-finder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/layer-finder.gif -------------------------------------------------------------------------------- /src/img/github/mainCtxMenu.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/mainCtxMenu.webp -------------------------------------------------------------------------------- /src/img/github/simulation.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/simulation.webp -------------------------------------------------------------------------------- /public/img/weapons/120mm_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/120mm_white.png -------------------------------------------------------------------------------- /public/img/weapons/HellCannon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/HellCannon.png -------------------------------------------------------------------------------- /public/img/weapons/MTLB_FAB500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/MTLB_FAB500.png -------------------------------------------------------------------------------- /public/img/weapons/Tech.Mortar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/Tech.Mortar.png -------------------------------------------------------------------------------- /public/img/weapons/Tech.UB-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/Tech.UB-32.png -------------------------------------------------------------------------------- /src/img/github/import_export.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/import_export.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/M109.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/M109.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/Mk19.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/Mk19.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/UB-32.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/UB-32.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/test.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/test.webp -------------------------------------------------------------------------------- /public/img/weapons/T62.DUMP.TRUCK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/weapons/T62.DUMP.TRUCK.png -------------------------------------------------------------------------------- /public/sounds/de/map_jeep_turret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_jeep_turret.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_motorcycle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_motorcycle.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_trackedapc.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_trackedapc.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_trackedifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_trackedifv.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_trackedjeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_trackedjeep.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_jeep_turret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_jeep_turret.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_motorcycle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_motorcycle.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_trackedapc.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_trackedapc.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_trackedifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_trackedifv.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_trackedjeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_trackedjeep.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_jeep_turret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_jeep_turret.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_motorcycle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_motorcycle.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_trackedapc.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_trackedapc.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_trackedifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_trackedifv.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_trackedjeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_trackedjeep.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_jeep_turret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_jeep_turret.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_motorcycle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_motorcycle.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_trackedapc.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_trackedapc.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_trackedifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_trackedifv.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_trackedjeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_trackedjeep.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_jeep_turret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_jeep_turret.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_motorcycle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_motorcycle.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_trackedapc.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_trackedapc.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_trackedifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_trackedifv.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_trackedjeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_trackedjeep.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_jeep_turret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_jeep_turret.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_motorcycle.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_motorcycle.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_trackedapc.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_trackedapc.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_trackedifv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_trackedifv.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_trackedjeep.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_trackedjeep.mp3 -------------------------------------------------------------------------------- /src/img/favicons/favicon_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/favicons/favicon_256x256.png -------------------------------------------------------------------------------- /src/img/favicons/favicon_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/favicons/favicon_512x512.png -------------------------------------------------------------------------------- /src/img/github/weaponInformation.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/weaponInformation.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/HIMARS.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/HIMARS.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/Mortar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/Mortar.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/TOS-1A.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/TOS-1A.webp -------------------------------------------------------------------------------- /public/sounds/LICENCE.txt: -------------------------------------------------------------------------------- 1 | AI Voice to Text made with https://luvvoice.com/ 2 | Voice : English (United States) - Christopher (Male) -------------------------------------------------------------------------------- /public/sounds/de/T_map_jeep_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_jeep_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/de/T_map_trackedrecon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_trackedrecon.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_jeep_antitank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_jeep_antitank.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_jeep_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_jeep_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_jeep_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_jeep_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_jeep_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_jeep_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_transporthelo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_transporthelo.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_truck_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_truck_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_jeep_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_jeep_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_trackedrecon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_trackedrecon.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_jeep_antitank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_jeep_antitank.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_jeep_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_jeep_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_jeep_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_jeep_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_jeep_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_jeep_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_transporthelo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_transporthelo.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_truck_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_truck_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_jeep_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_jeep_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_trackedrecon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_trackedrecon.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_jeep_antitank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_jeep_antitank.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_jeep_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_jeep_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_jeep_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_jeep_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_jeep_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_jeep_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_transporthelo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_transporthelo.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_truck_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_truck_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_jeep_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_jeep_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_trackedrecon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_trackedrecon.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_jeep_antitank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_jeep_antitank.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_jeep_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_jeep_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_jeep_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_jeep_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_jeep_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_jeep_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_transporthelo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_transporthelo.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_truck_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_truck_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_jeep_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_jeep_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_trackedrecon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_trackedrecon.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_jeep_antitank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_jeep_antitank.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_jeep_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_jeep_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_jeep_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_jeep_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_jeep_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_jeep_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_transporthelo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_transporthelo.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_truck_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_truck_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_jeep_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_jeep_antiair.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_trackedrecon.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_trackedrecon.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_jeep_antitank.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_jeep_antitank.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_jeep_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_jeep_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_jeep_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_jeep_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_jeep_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_jeep_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_transporthelo.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_transporthelo.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_truck_antiair.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_truck_antiair.mp3 -------------------------------------------------------------------------------- /src/img/favicons/maskable_icon_x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/favicons/maskable_icon_x512.png -------------------------------------------------------------------------------- /src/img/github/squadmortaroverlay.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/src/img/github/squadmortaroverlay.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/BM-21Grad.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/BM-21Grad.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/BTR4-AGS.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/BTR4-AGS.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/HellCannon.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/HellCannon.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/M1064M121.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/M1064M121.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/Tech.UB-32.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/Tech.UB-32.webp -------------------------------------------------------------------------------- /public/sounds/de/T_map_boat_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_boat_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/de/T_map_boat_openturret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_boat_openturret.mp3 -------------------------------------------------------------------------------- /public/sounds/de/T_map_trackedapc_msv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_trackedapc_msv.mp3 -------------------------------------------------------------------------------- /public/sounds/de/T_map_truck_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_truck_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_truck_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_truck_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/de/map_truck_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/map_truck_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_boat_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_boat_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_boat_openturret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_boat_openturret.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_trackedapc_msv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_trackedapc_msv.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_truck_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_truck_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_truck_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_truck_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/en/map_truck_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/map_truck_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_boat_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_boat_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_boat_openturret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_boat_openturret.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_trackedapc_msv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_trackedapc_msv.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_truck_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_truck_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_truck_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_truck_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/map_truck_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/map_truck_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_boat_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_boat_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_boat_openturret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_boat_openturret.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_trackedapc_msv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_trackedapc_msv.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_truck_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_truck_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_truck_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_truck_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/map_truck_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/map_truck_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_boat_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_boat_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_boat_openturret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_boat_openturret.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_trackedapc_msv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_trackedapc_msv.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_truck_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_truck_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_truck_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_truck_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/map_truck_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/map_truck_transport.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_boat_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_boat_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_boat_openturret.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_boat_openturret.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_trackedapc_msv.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_trackedapc_msv.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_truck_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_truck_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_truck_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_truck_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/map_truck_transport.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/map_truck_transport.mp3 -------------------------------------------------------------------------------- /public/img/markers/weapons/MTLB_FAB500.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/MTLB_FAB500.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/Tech.Mortar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/Tech.Mortar.webp -------------------------------------------------------------------------------- /public/sounds/de/T_map_helicopter_scout.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_helicopter_scout.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_helicopter_scout.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_helicopter_scout.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_helicopter_scout.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_helicopter_scout.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_helicopter_scout.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_helicopter_scout.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_helicopter_scout.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_helicopter_scout.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_helicopter_scout.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_helicopter_scout.mp3 -------------------------------------------------------------------------------- /public/img/markers/weapons/T62.DUMP.TRUCK.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/T62.DUMP.TRUCK.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/marker_mortar_1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/marker_mortar_1.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/marker_mortar_2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/marker_mortar_2.webp -------------------------------------------------------------------------------- /public/img/markers/weapons/marker_shadow.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/weapons/marker_shadow.webp -------------------------------------------------------------------------------- /public/sounds/de/T_map_trackedapc_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_trackedapc_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/de/T_map_trackedapc_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/de/T_map_trackedapc_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_trackedapc_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_trackedapc_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/en/T_map_trackedapc_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/en/T_map_trackedapc_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_trackedapc_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_trackedapc_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/fr/T_map_trackedapc_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/fr/T_map_trackedapc_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_trackedapc_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_trackedapc_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/ru/T_map_trackedapc_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/ru/T_map_trackedapc_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_trackedapc_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_trackedapc_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/uk/T_map_trackedapc_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/uk/T_map_trackedapc_logistics.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_trackedapc_artillery.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_trackedapc_artillery.mp3 -------------------------------------------------------------------------------- /public/sounds/zh/T_map_trackedapc_logistics.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/sounds/zh/T_map_trackedapc_logistics.mp3 -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_mini.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_mini.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_disabled.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_disabled.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_enabled.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_enabled.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_disabled_mini.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_disabled_mini.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_session_mini.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_session_mini.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_disabled_backup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_disabled_backup.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_enabled_backup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_enabled_backup.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_enabled_chrismas.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_enabled_chrismas.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_session_enabled.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_session_enabled.webp -------------------------------------------------------------------------------- /public/img/markers/targets/marker_target_session_enabled_backup.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sh4rkman/SquadCalc/HEAD/public/img/markers/targets/marker_target_session_enabled_backup.webp -------------------------------------------------------------------------------- /src/js/libs/readme: -------------------------------------------------------------------------------- 1 | This folder contains external JavaScript libraries that were manually added because they were not available via package managers, or because i needed to slightly adapt/patch bugs. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | mortar.code-workspace 2 | .vscode/ 3 | .env 4 | debug.log 5 | node_modules/ 6 | dist/ 7 | public/dist/ 8 | config/test-results/ 9 | *.Identifier 10 | /.idea 11 | maintenance.enable 12 | /.fastRequest -------------------------------------------------------------------------------- /src/components/shared/snow.scss: -------------------------------------------------------------------------------- 1 | body { 2 | overflow: hidden; 3 | min-height: 100vh; 4 | color: white; 5 | } 6 | 7 | .snowflake { 8 | position: absolute; 9 | width: 10px; 10 | height: 10px; 11 | background: linear-gradient(white, white); 12 | /* Workaround for Chromium's selective color inversion */ 13 | pointer-events: none; 14 | border-radius: 50%; 15 | filter: drop-shadow(0 0 10px white); 16 | z-index: 9999; 17 | } 18 | 19 | #snow { 20 | display: none; 21 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /src/components/dialogs/servers.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 |
7 | 8 |
9 |
-------------------------------------------------------------------------------- /public/locales/zh/weapons.json: -------------------------------------------------------------------------------- 1 | { 2 | "deployables": "武器工事", 3 | "Mortar": "81毫米迫击炮", 4 | "UB-32": "UB32火箭巢", 5 | "HellCannon": "地狱加农(煤气罐)", 6 | "vehicles": "载具", 7 | "Tech.Mortar": "迫击炮皮卡", 8 | "Tech.UB-32": "火箭巢车", 9 | "BM-21Grad": "BM21-冰雹", 10 | "M1064M121": "M1064 M121", 11 | "impact": "高爆", 12 | "nearSurface": "空爆", 13 | "modded": "Mod版", 14 | "Mk19": "MK19-遥控武器站", 15 | "M109": "M109A7 Paladin", 16 | "T62.DUMP.TRUCK": "T62 Dump Truck", 17 | "MTLB_FAB500": "MTLB БЕГЕМОТ", 18 | "HIMARS": "M142 HIMARS", 19 | "TOS-1A": "TOS-1A" 20 | } -------------------------------------------------------------------------------- /public/locales/en/weapons.json: -------------------------------------------------------------------------------- 1 | { 2 | "deployables": "Deployables", 3 | "Mortar": "Mortar 81mm", 4 | "UB-32": "UB-32", 5 | "HellCannon": "Hell Cannon", 6 | "vehicles": "Vehicles", 7 | "Tech.Mortar": "Tech. Mortar", 8 | "Tech.UB-32": "Tech. UB-32", 9 | "BM-21Grad": "BM-21 Grad", 10 | "M1064M121": "M1064 M121", 11 | "impact": "Impact", 12 | "nearSurface": "Near-Surface", 13 | "Mk19": "MK19-RWS", 14 | "modded": "Modded", 15 | "M109": "M109A7 Paladin", 16 | "T62.DUMP.TRUCK": "T62 Dump Truck", 17 | "MTLB_FAB500": "MTLB БЕГЕМОТ", 18 | "HIMARS": "M142 HIMARS", 19 | "TOS-1A": "TOS-1A" 20 | } -------------------------------------------------------------------------------- /public/locales/fr/weapons.json: -------------------------------------------------------------------------------- 1 | { 2 | "deployables": "Déployables", 3 | "Mortar": "Mortier 81mm", 4 | "UB-32": "UB-32", 5 | "HellCannon": "Hell Cannon", 6 | "vehicles": "Véhicules", 7 | "Tech.Mortar": "Mortier mobile", 8 | "Tech.UB-32": "UB-32 mobile", 9 | "BM-21Grad": "BM-21 Grad", 10 | "M1064M121": "M1064 M121", 11 | "impact": "Impact", 12 | "nearSurface": "Aérienne", 13 | "modded": "Moddé", 14 | "Mk19": "MK19-RWS", 15 | "M109": "M109A7 Paladin", 16 | "T62.DUMP.TRUCK": "T62 Dump Truck", 17 | "MTLB_FAB500": "MTLB БЕГЕМОТ", 18 | "HIMARS": "M142 HIMARS", 19 | "TOS-1A": "TOS-1A" 20 | } -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting a Vulnerability 2 | 3 | If you discover a security vulnerability in this project, please report it as soon as possible. We take security seriously and will address the issue promptly. 4 | 5 | ## Methods to Report: 6 | - **GitHub**: You can privately [report a vulnerability](https://github.com/sh4rkman/SquadCalc/security/advisories/new). 7 | - **Discord**: Join the [Discord](https://discord.gg/BNPAc5kEJP) or add me directly : sh4rkm4n 8 | 9 | 10 | ## Responsible Disclosure 11 | We encourage responsible disclosure and will work to address any vulnerabilities found. 12 | Once resolved, we will give credit to the reporter in the release notes or relevant documentation (with your permission). 13 | -------------------------------------------------------------------------------- /public/locales/de/weapons.json: -------------------------------------------------------------------------------- 1 | { 2 | "deployables": "Deployables", 3 | "Mortar": "81-mm-Mörser", 4 | "UB-32": "UB-32", 5 | "HellCannon": "Höllenkanone", 6 | "vehicles": "Fahrzeuge", 7 | "Tech.Mortar": "Tech. Mortar", 8 | "Tech.UB-32": "Tech. UB-32", 9 | "BM-21Grad": "BM-21 Grad", 10 | "M1064M121": "M1064 M121", 11 | "impact": "Aufschlag", 12 | "nearSurface": "Luftdetonation", 13 | "modded": "Modded", 14 | "Mk19": "MK19-RWS", 15 | "M109": "M109A7 Paladin", 16 | "T62.DUMP.TRUCK": "T62 Dump Truck", 17 | "MTLB_FAB500": "MTLB БЕГЕМОТ", 18 | "HIMARS": "M142 HIMARS", 19 | "TOS-1A": "TOS-1A" 20 | } -------------------------------------------------------------------------------- /public/locales/ru/weapons.json: -------------------------------------------------------------------------------- 1 | { 2 | "deployables": "Размещаемые", 3 | "Mortar": "Миномёт 81 мм", 4 | "UB-32": "УБ-32", 5 | "HellCannon": "Адская пушка", 6 | "vehicles": "Транспортные средства", 7 | "Tech.Mortar": "Тех. миномёт", 8 | "Tech.UB-32": "Тех. УБ-32", 9 | "BM-21Grad": "БМ-21 Град", 10 | "M1064M121": "М1064 M121", 11 | "impact": "Удар", 12 | "nearSurface": "воздух", 13 | "modded": "Модовые", 14 | "Mk19": "МК19-RWS", 15 | "M109": "M109A7 Paladin", 16 | "T62.DUMP.TRUCK": "T62 Dump Truck", 17 | "MTLB_FAB500": "MTLB БЕГЕМОТ", 18 | "HIMARS": "M142 HIMARS", 19 | "TOS-1A": "TOS-1A" 20 | } 21 | -------------------------------------------------------------------------------- /public/locales/uk/weapons.json: -------------------------------------------------------------------------------- 1 | { 2 | "deployables": "Розгортання", 3 | "Mortar": "Міномет 81 мм", 4 | "UB-32": "УБ-32", 5 | "HellCannon": "Адський гармата", 6 | "vehicles": "Транспортні засоби", 7 | "Tech.Mortar": "Тех. міномет", 8 | "Tech.UB-32": "Тех. УБ-32", 9 | "BM-21Grad": "БМ-21 Град", 10 | "M1064M121": "М1064 М121", 11 | "impact": "Удар", 12 | "nearSurface": "антена", 13 | "modded": "Модові", 14 | "Mk19": "МК19-ДКУ", 15 | "M109": "M109A7 Paladin", 16 | "T62.DUMP.TRUCK": "T62 Dump Truck", 17 | "MTLB_FAB500": "MTLB БЕГЕМОТ", 18 | "HIMARS": "M142 HIMARS", 19 | "TOS-1A": "TOS-1A" 20 | } 21 | -------------------------------------------------------------------------------- /public/locales/zh/maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "AlBasrah": "巴士拉", 3 | "Anvil": "铁砧行动", 4 | "Belaya": "贝拉亚山口", 5 | "BlackCoast": "黑色海岸", 6 | "Chora": "乔拉", 7 | "Fallujah": "费卢杰", 8 | "FoolsRoad": "愚者之路", 9 | "GooseBay": "鹅湾", 10 | "Gorodok": "格洛多克", 11 | "Jensen": "詹森训练场", 12 | "Harju": "哈留", 13 | "Kamdesh": "卡姆德什高地", 14 | "Kohat": "科哈特", 15 | "Kokan": "科坎", 16 | "Lashkar": "拉什卡河谷", 17 | "Logar": "洛加尔山谷", 18 | "Manicouagan": "曼尼古根", 19 | "Mestia": "梅斯提亚", 20 | "Mutaha": "穆塔哈", 21 | "Narva": "纳尔瓦", 22 | "Narva_f": "水淹纳尔瓦", 23 | "Pacific": "太平洋训练场", 24 | "Sanxian": "三贤岛", 25 | "Skorpo": "斯科普", 26 | "Sumari": "苏马瑞", 27 | "Tallil": "塔利尔郊区", 28 | "Yehorivka": "叶霍里夫卡" 29 | } -------------------------------------------------------------------------------- /public/locales/de/maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "AlBasrah": "Al Basrah", 3 | "Anvil": "Anvil", 4 | "Belaya": "Belaya", 5 | "BlackCoast": "Black Coast", 6 | "Chora": "Chora", 7 | "Fallujah": "Fallujah", 8 | "FoolsRoad": "Fool's Road", 9 | "GooseBay": "Goose Bay", 10 | "Gorodok": "Gorodok", 11 | "Jensen": "Jensen", 12 | "Harju": "Harju", 13 | "Kamdesh": "Kamdesh", 14 | "Kohat": "Kohat", 15 | "Kokan": "Kokan", 16 | "Lashkar": "Lashkar", 17 | "Logar": "Logar", 18 | "Manicouagan": "Manicouagan", 19 | "Mestia": "Mestia", 20 | "Mutaha": "Mutaha", 21 | "Narva": "Narva", 22 | "Narva_f": "Narva Fl.", 23 | "Pacific": "Pacific Pr. Gr.", 24 | "Sanxian": "Sanxian", 25 | "Skorpo": "Skorpo", 26 | "Sumari": "Sumari", 27 | "Tallil": "Tallil", 28 | "Yehorivka": "Yehorivka" 29 | } -------------------------------------------------------------------------------- /public/locales/en/maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "AlBasrah": "Al Basrah", 3 | "Anvil": "Anvil", 4 | "Belaya": "Belaya", 5 | "BlackCoast": "Black Coast", 6 | "Chora": "Chora", 7 | "Fallujah": "Fallujah", 8 | "FoolsRoad": "Fool's Road", 9 | "GooseBay": "Goose Bay", 10 | "Gorodok": "Gorodok", 11 | "Jensen": "Jensen", 12 | "Harju": "Harju", 13 | "Kamdesh": "Kamdesh", 14 | "Kohat": "Kohat", 15 | "Kokan": "Kokan", 16 | "Lashkar": "Lashkar", 17 | "Logar": "Logar", 18 | "Manicouagan": "Manicouagan", 19 | "Mestia": "Mestia", 20 | "Mutaha": "Mutaha", 21 | "Narva": "Narva", 22 | "Narva_f": "Narva Fl.", 23 | "Pacific": "Pacific Pr. Gr.", 24 | "Sanxian": "Sanxian", 25 | "Skorpo": "Skorpo", 26 | "Sumari": "Sumari", 27 | "Tallil": "Tallil", 28 | "Yehorivka": "Yehorivka" 29 | } -------------------------------------------------------------------------------- /public/locales/fr/maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "AlBasrah": "Al Basrah", 3 | "Anvil": "Anvil", 4 | "Belaya": "Belaya", 5 | "BlackCoast": "Black Coast", 6 | "Chora": "Chora", 7 | "Fallujah": "Fallujah", 8 | "FoolsRoad": "Fool's Road", 9 | "GooseBay": "Goose Bay", 10 | "Gorodok": "Gorodok", 11 | "Jensen": "Jensen", 12 | "Harju": "Harju", 13 | "Kamdesh": "Kamdesh", 14 | "Kohat": "Kohat", 15 | "Kokan": "Kokan", 16 | "Lashkar": "Lashkar", 17 | "Logar": "Logar", 18 | "Manicouagan": "Manicouagan", 19 | "Mestia": "Mestia", 20 | "Mutaha": "Mutaha", 21 | "Narva": "Narva", 22 | "Narva_f": "Narva Fl.", 23 | "Pacific": "Pacific Pr. Gr.", 24 | "Sanxian": "Sanxian", 25 | "Skorpo": "Skorpo", 26 | "Sumari": "Sumari", 27 | "Tallil": "Tallil", 28 | "Yehorivka": "Yehorivka" 29 | } -------------------------------------------------------------------------------- /public/locales/ru/maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "AlBasrah": "Al Basrah", 3 | "Anvil": "Anvil", 4 | "Belaya": "Belaya", 5 | "BlackCoast": "Black Coast", 6 | "Chora": "Chora", 7 | "Fallujah": "Fallujah", 8 | "FoolsRoad": "Fool's Road", 9 | "GooseBay": "Goose Bay", 10 | "Gorodok": "Gorodok", 11 | "Jensen": "Jensen", 12 | "Harju": "Harju", 13 | "Kamdesh": "Kamdesh", 14 | "Kohat": "Kohat", 15 | "Kokan": "Kokan", 16 | "Lashkar": "Lashkar", 17 | "Logar": "Logar", 18 | "Manicouagan": "Manicouagan", 19 | "Mestia": "Mestia", 20 | "Mutaha": "Mutaha", 21 | "Narva": "Narva", 22 | "Narva_f": "Narva Fl.", 23 | "Pacific": "Pacific Pr. Gr.", 24 | "Sanxian": "Sanxian", 25 | "Skorpo": "Skorpo", 26 | "Sumari": "Sumari", 27 | "Tallil": "Tallil", 28 | "Yehorivka": "Yehorivka" 29 | } -------------------------------------------------------------------------------- /public/locales/uk/maps.json: -------------------------------------------------------------------------------- 1 | { 2 | "AlBasrah": "Al Basrah", 3 | "Anvil": "Anvil", 4 | "Belaya": "Belaya", 5 | "BlackCoast": "Black Coast", 6 | "Chora": "Chora", 7 | "Fallujah": "Fallujah", 8 | "FoolsRoad": "Fool's Road", 9 | "GooseBay": "Goose Bay", 10 | "Gorodok": "Gorodok", 11 | "Jensen": "Jensen", 12 | "Harju": "Harju", 13 | "Kamdesh": "Kamdesh", 14 | "Kohat": "Kohat", 15 | "Kokan": "Kokan", 16 | "Lashkar": "Lashkar", 17 | "Logar": "Logar", 18 | "Manicouagan": "Manicouagan", 19 | "Mestia": "Mestia", 20 | "Mutaha": "Mutaha", 21 | "Narva": "Narva", 22 | "Narva_f": "Narva Fl.", 23 | "Pacific": "Pacific Pr. Gr.", 24 | "Sanxian": "Sanxian", 25 | "Skorpo": "Skorpo", 26 | "Sumari": "Sumari", 27 | "Tallil": "Tallil", 28 | "Yehorivka": "Yehorivka" 29 | } -------------------------------------------------------------------------------- /config/.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard-scss", 3 | "rules": { 4 | "rule-empty-line-before": [ 5 | "always", 6 | { 7 | "except": ["inside-block"] 8 | } 9 | ], 10 | "comment-empty-line-before": null, 11 | "selector-class-pattern": null, 12 | "scss/at-extend-no-missing-placeholder": null, 13 | "scss/double-slash-comment-empty-line-before": [ 14 | "always", 15 | { 16 | "except": ["inside-block"] 17 | } 18 | ], 19 | "scss/dollar-variable-pattern": null, 20 | "scss/dollar-variable-colon-space-before": "never", 21 | "no-descending-specificity": null, 22 | "alpha-value-notation": "number", 23 | "property-no-vendor-prefix": null, 24 | "declaration-empty-line-before": "never", 25 | "color-function-notation": "legacy", 26 | "import-notation": "string", 27 | "selector-id-pattern": null 28 | } 29 | } -------------------------------------------------------------------------------- /public/locales/zh/factions.json: -------------------------------------------------------------------------------- 1 | { 2 | "AFU": "乌军", 3 | "ADF": "澳军", 4 | "BAF": "英军", 5 | "CAF": "加军", 6 | "CRF": "CRF", 7 | "IMF": "民兵", 8 | "MEI": "叛军", 9 | "GFI": "GFI", 10 | "MEA": "中东联军", 11 | "PLA": "解放军", 12 | "PLAAGF": "解放军陆军两栖旅", 13 | "PLANMC": "解放军海军陆战队", 14 | "RGF": "俄军", 15 | "TLF": "土军", 16 | "USA": "美军", 17 | "USMC": "马润", 18 | "VDV": "俄空降军", 19 | "WPMC": "雇佣兵", 20 | "AFU_displayName": "乌克兰武装部队", 21 | "ADF_displayName": "澳大利亚国防军", 22 | "BAF_displayName": "英国陆军", 23 | "CAF_displayName": "加拿大陆军", 24 | "CRF_displayName": "Canadian Resistance Forces", 25 | "IMF_displayName": "非正规民兵", 26 | "MEI_displayName": "叛乱军队", 27 | "GFI_displayName": "Ground Force of Iran", 28 | "PLA_displayName": "中国人民解放军", 29 | "PLAAGF_displayName": "中国人民解放军陆军两栖旅", 30 | "PLANMC_displayName": "中国人民解放军海军陆战队", 31 | "RGF_displayName": "俄罗斯陆军", 32 | "TLF_displayName": "土耳其陆军", 33 | "USA_displayName": "美国陆军", 34 | "USMC_displayName": "美国海军陆战队", 35 | "VDV_displayName": "俄罗斯空降军", 36 | "WPMC_displayName": "西方雇佣兵" 37 | } 38 | -------------------------------------------------------------------------------- /.env.template: -------------------------------------------------------------------------------- 1 | # Enable or disable WebSocket functionality for SquadMortarOverlay 2 | # If set to 'true' SquadCalc will try to open a socket with any running local instance of squadmortaroverlay.exe 3 | # see https://github.com/Devil4ngle/SquadMortarOverlay 4 | WEBSOCKET=false 5 | 6 | # Enable or disable search engine indexing 7 | # If set to 'true' a robots.txt with allow all will be created 8 | # If set to 'false' a robots.txt with disallow all will be created 9 | INDEX=false 10 | 11 | # Base URL for the API the application communicates with. 12 | # Disable or leave empty if you don't want to use API features (publishing markers, heatmaps, sessions) 13 | # Note that official API access need to be obtained first, see : https://github.com/sh4rkman/SquadCalc/wiki/API-Documentation 14 | #API_URL=https://beta.squadcalc.app/api 15 | API_URL=https://squadcalc.app/api 16 | 17 | # Enable or disable Factions and vehicles functionalities 18 | # If set to 'true' everything related to factions and vehicles will be disabled 19 | # 'False' by default, which means that the application will use the default factions and vehicles 20 | DISABLE_FACTIONS=false 21 | 22 | -------------------------------------------------------------------------------- /src/js/libs/leaflet-edgebuffer.js: -------------------------------------------------------------------------------- 1 | /* Leaflet EdgeBuffer Plugin 2 | * https://github.com/TolonUK/Leaflet.EdgeBuffer 3 | * (MIT) Copyright (c) 2015-2025 Alex Paterson 4 | * 5 | * edited by Maxime "sharkman" Boussard for lealfet v2.0 6 | */ 7 | 8 | import { GridLayer, Bounds } from "leaflet"; 9 | 10 | const originalPxBoundsToTileRange = GridLayer.prototype._pxBoundsToTileRange; 11 | 12 | GridLayer.prototype._pxBoundsToTileRange = function(bounds) { 13 | const tileRange = originalPxBoundsToTileRange.call(this, bounds); 14 | 15 | // Default is to buffer one tile beyond the pixel bounds (edgeBufferTiles = 1) 16 | let edgeBufferTiles = 1; 17 | if ((this.options.edgeBufferTiles !== undefined) && (this.options.edgeBufferTiles !== null)) { 18 | edgeBufferTiles = this.options.edgeBufferTiles; 19 | } 20 | 21 | if (edgeBufferTiles > 0) { 22 | //const pixelEdgeBuffer = this.getTileSize().multiplyBy(edgeBufferTiles); 23 | return new Bounds( 24 | tileRange.min.subtract([edgeBufferTiles, edgeBufferTiles]), 25 | tileRange.max.add([edgeBufferTiles, edgeBufferTiles]) 26 | ); 27 | } 28 | 29 | return tileRange; 30 | }; 31 | 32 | export default {}; -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for considering contributing to this project! 🙏 4 | 5 | ## 1. Open an Issue/Discussion first 6 | 7 | ⚠️ **Before creating a pull request, please open an [Issue](https://github.com/sh4rkman/SquadCalc/issues) or start a [Discussion](https://github.com/sh4rkman/SquadCalc/discussions) for new features** ⚠️ 8 | 9 | This helps me make sure that the feature aligns with the project’s goals and avoids wasted work. 10 | **Exceptions:** Simple fixes, typos, or translations do not require an issue first. 11 | 12 | ## 2. Target the Development Branch 13 | 14 | ⚠️ **All pull requests should target the development branch (`dev`), not `master`.** ⚠️ 15 | 16 | Your PR will first be tested and merged with the current under-development features before eventually making it to `master`. 17 | 18 | ### How to create a PR 19 | 1. Fork the repository (if needed) 20 | 2. Create a branch from `dev`: 21 | 22 | 23 | ```bash 24 | git checkout dev 25 | git checkout -b my-feature 26 | ``` 27 | 28 | 3. Make your changes and commit them 29 | 4. Push your branch and open a pull request targeting dev 30 | 5. Wait for review and approval before merging 31 | 6. After merging, your PR will be automatically pushed to https://beta.squadcalc.app/ -------------------------------------------------------------------------------- /src/components/map/mapLogo.scss: -------------------------------------------------------------------------------- 1 | @use "../shared/variables"; 2 | 3 | .logo { 4 | @extend .unselectable; 5 | position: fixed; 6 | height: 100vh; 7 | width: 100vw; 8 | display: table; 9 | font-family: variables.$logoFont, Times, "Times New Roman", serif; 10 | text-transform: uppercase; 11 | font-size: 6em; 12 | letter-spacing: 0; 13 | span { 14 | font-weight: bolder; 15 | line-height: 1.3em; 16 | display: table-cell; 17 | vertical-align: middle; 18 | span { 19 | display: block; 20 | } 21 | span:nth-child(1) { 22 | padding: 0 0 10px; 23 | } 24 | span:nth-child(2) { 25 | padding: 0 15px 10px; 26 | background: linear-gradient(to right, variables.$mainColor 50%, variables.$mainBGColor 50%); 27 | background-size: 200% 100%; 28 | background-position: right bottom; 29 | animation: 1s ease-out 0.3s 1 forwards loading; 30 | width: 2.6em; 31 | margin: 0 auto; 32 | } 33 | } 34 | } 35 | 36 | #background { 37 | @extend .logo; 38 | } 39 | 40 | #loader { 41 | @extend .logo; 42 | background-color: variables.$mainBGColor; 43 | z-index: 99; 44 | top: 0; 45 | } -------------------------------------------------------------------------------- /public/locales/de/factions.json: -------------------------------------------------------------------------------- 1 | { 2 | "AFU": "AFU", 3 | "ADF": "ADF", 4 | "BAF": "BAF", 5 | "CAF": "CAF", 6 | "IMF": "IMF", 7 | "INS": "INS", 8 | "MEA": "MEA", 9 | "PLA": "PLA", 10 | "PLAAGF": "PLAAGF", 11 | "PLANMC": "PLANMC", 12 | "RGF": "RGF", 13 | "TLF": "TLF", 14 | "USA": "USA", 15 | "USMC": "USMC", 16 | "VDV": "VDV", 17 | "WPMC": "WPMC", 18 | "AFU_displayName": "Armed Forces of Ukraine", 19 | "ADF_displayName": "Australian Defence Force", 20 | "BAF_displayName": "British Armed Forces", 21 | "CAF_displayName": "Canadian Armed Forces", 22 | "IMF_displayName": "Irregular Militia Forces", 23 | "INS_displayName": "Insurgents", 24 | "MEA_displayName": "Middle Eastern Alliance", 25 | "PLA_displayName": "People's Liberation Army", 26 | "PLAAGF_displayName": "People's Liberation Army Airborne Ground Forces", 27 | "PLANMC_displayName": "People's Liberation Army Navy Marine Corps", 28 | "RGF_displayName": "Russian Ground Forces", 29 | "TLF_displayName": "Turkish Land Forces", 30 | "USA_displayName": "United States Army", 31 | "USMC_displayName": "United States Marine Corps", 32 | "VDV_displayName": "Russian Airborne Forces", 33 | "WPMC_displayName": "Western Private Military Company" 34 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Maxime "sharkman" Boussard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | 1. Attribution for Reuploads: If the Software is reuploaded, credit must be given to the original project and original author. This includes maintaining any existing links to the original project’s GitHub repository, which must not be removed or altered. 8 | 9 | 2. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /public/locales/en/factions.json: -------------------------------------------------------------------------------- 1 | { 2 | "AFU": "AFU", 3 | "ADF": "ADF", 4 | "BAF": "BAF", 5 | "CAF": "CAF", 6 | "CRF": "CRF", 7 | "IMF": "IMF", 8 | "MEI": "MEI", 9 | "GFI": "GFI", 10 | "PLA": "PLA", 11 | "PLAAGF": "PLAAGF", 12 | "PLANMC": "PLANMC", 13 | "RGF": "RGF", 14 | "TLF": "TLF", 15 | "USA": "USA", 16 | "USMC": "USMC", 17 | "VDV": "VDV", 18 | "WPMC": "WPMC", 19 | "AFU_displayName": "Armed Forces of Ukraine", 20 | "ADF_displayName": "Australian Defence Force", 21 | "BAF_displayName": "British Armed Forces", 22 | "CAF_displayName": "Canadian Armed Forces", 23 | "CRF_displayName": "Canadian Resistance Forces", 24 | "IMF_displayName": "Irregular Militia Forces", 25 | "MEI_displayName": "Middle East Insurgents", 26 | "GFI_displayName": "Ground Force of Iran", 27 | "PLA_displayName": "People's Liberation Army", 28 | "PLAAGF_displayName": "People's Liberation Army Airborne Ground Forces", 29 | "PLANMC_displayName": "People's Liberation Army Navy Marine Corps", 30 | "RGF_displayName": "Russian Ground Forces", 31 | "TLF_displayName": "Turkish Land Forces", 32 | "USA_displayName": "United States Army", 33 | "USMC_displayName": "United States Marine Corps", 34 | "VDV_displayName": "Russian Airborne Forces", 35 | "WPMC_displayName": "Western Private Military Company" 36 | } -------------------------------------------------------------------------------- /public/locales/fr/factions.json: -------------------------------------------------------------------------------- 1 | { 2 | "AFU": "AFU", 3 | "ADF": "ADF", 4 | "BAF": "BAF", 5 | "CAF": "CAF", 6 | "CRF": "CRF", 7 | "IMF": "IMF", 8 | "MEI": "MEI", 9 | "GFI": "GFI", 10 | "PLA": "PLA", 11 | "PLAAGF": "PLAAGF", 12 | "PLANMC": "PLANMC", 13 | "RGF": "RGF", 14 | "TLF": "TLF", 15 | "USA": "USA", 16 | "USMC": "USMC", 17 | "VDV": "VDV", 18 | "WPMC": "WPMC", 19 | "AFU_displayName": "Armed Forces of Ukraine", 20 | "ADF_displayName": "Australian Defence Force", 21 | "BAF_displayName": "British Armed Forces", 22 | "CAF_displayName": "Canadian Armed Forces", 23 | "CRF_displayName": "Canadian Resistance Forces", 24 | "IMF_displayName": "Irregular Militia Forces", 25 | "MEI_displayName": "Middle East Insurgents", 26 | "GFI_displayName": "Ground Force of Iran", 27 | "PLA_displayName": "People's Liberation Army", 28 | "PLAAGF_displayName": "People's Liberation Army Airborne Ground Forces", 29 | "PLANMC_displayName": "People's Liberation Army Navy Marine Corps", 30 | "RGF_displayName": "Russian Ground Forces", 31 | "TLF_displayName": "Turkish Land Forces", 32 | "USA_displayName": "United States Army", 33 | "USMC_displayName": "United States Marine Corps", 34 | "VDV_displayName": "Russian Airborne Forces", 35 | "WPMC_displayName": "Western Private Military Company" 36 | } -------------------------------------------------------------------------------- /public/locales/ru/factions.json: -------------------------------------------------------------------------------- 1 | { 2 | "AFU": "AFU", 3 | "ADF": "ADF", 4 | "BAF": "BAF", 5 | "CAF": "CAF", 6 | "CRF": "CRF", 7 | "IMF": "IMF", 8 | "MEI": "MEI", 9 | "GFI": "GFI", 10 | "PLA": "PLA", 11 | "PLAAGF": "PLAAGF", 12 | "PLANMC": "PLANMC", 13 | "RGF": "RGF", 14 | "TLF": "TLF", 15 | "USA": "USA", 16 | "USMC": "USMC", 17 | "VDV": "VDV", 18 | "WPMC": "WPMC", 19 | "AFU_displayName": "Armed Forces of Ukraine", 20 | "ADF_displayName": "Australian Defence Force", 21 | "BAF_displayName": "British Armed Forces", 22 | "CAF_displayName": "Canadian Armed Forces", 23 | "CRF_displayName": "Canadian Resistance Forces", 24 | "IMF_displayName": "Irregular Militia Forces", 25 | "MEI_displayName": "Middle East Insurgents", 26 | "GFI_displayName": "Ground Force of Iran", 27 | "PLA_displayName": "People's Liberation Army", 28 | "PLAAGF_displayName": "People's Liberation Army Airborne Ground Forces", 29 | "PLANMC_displayName": "People's Liberation Army Navy Marine Corps", 30 | "RGF_displayName": "Russian Ground Forces", 31 | "TLF_displayName": "Turkish Land Forces", 32 | "USA_displayName": "United States Army", 33 | "USMC_displayName": "United States Marine Corps", 34 | "VDV_displayName": "Russian Airborne Forces", 35 | "WPMC_displayName": "Western Private Military Company" 36 | } -------------------------------------------------------------------------------- /public/locales/uk/factions.json: -------------------------------------------------------------------------------- 1 | { 2 | "AFU": "AFU", 3 | "ADF": "ADF", 4 | "BAF": "BAF", 5 | "CAF": "CAF", 6 | "CRF": "CRF", 7 | "IMF": "IMF", 8 | "MEI": "MEI", 9 | "GFI": "GFI", 10 | "PLA": "PLA", 11 | "PLAAGF": "PLAAGF", 12 | "PLANMC": "PLANMC", 13 | "RGF": "RGF", 14 | "TLF": "TLF", 15 | "USA": "USA", 16 | "USMC": "USMC", 17 | "VDV": "VDV", 18 | "WPMC": "WPMC", 19 | "AFU_displayName": "Armed Forces of Ukraine", 20 | "ADF_displayName": "Australian Defence Force", 21 | "BAF_displayName": "British Armed Forces", 22 | "CAF_displayName": "Canadian Armed Forces", 23 | "CRF_displayName": "Canadian Resistance Forces", 24 | "IMF_displayName": "Irregular Militia Forces", 25 | "MEI_displayName": "Middle East Insurgents", 26 | "GFI_displayName": "Ground Force of Iran", 27 | "PLA_displayName": "People's Liberation Army", 28 | "PLAAGF_displayName": "People's Liberation Army Airborne Ground Forces", 29 | "PLANMC_displayName": "People's Liberation Army Navy Marine Corps", 30 | "RGF_displayName": "Russian Ground Forces", 31 | "TLF_displayName": "Turkish Land Forces", 32 | "USA_displayName": "United States Army", 33 | "USMC_displayName": "United States Marine Corps", 34 | "VDV_displayName": "Russian Airborne Forces", 35 | "WPMC_displayName": "Western Private Military Company" 36 | } -------------------------------------------------------------------------------- /.github/workflows/deploy_preprod.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Beta 2 | permissions: 3 | contents: read 4 | on: 5 | push: 6 | branches: [ dev ] 7 | 8 | jobs: 9 | build: 10 | name: ssh/pull/build 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Pull code & Build 14 | uses: appleboy/ssh-action@v1.2.4 15 | with: 16 | host: ${{ secrets.HOST }} 17 | port: ${{ secrets.PORT }} 18 | username: ${{ secrets.USERNAME }} 19 | password: ${{ secrets.PASSWORD }} 20 | script: | 21 | eval `ssh-agent -s` 22 | ssh-add ~/.ssh/${{ secrets.SSH_PUBLIC_KEY_NAME }} 23 | # Enable maintenance mode 24 | touch ${{ secrets.DEV_DIST }}/maintenance.enable 25 | # Deploy 26 | cd ${{ secrets.DEV_DIST }} 27 | git pull origin dev 28 | npm ci 29 | npm run build 30 | # Disable maintenance mode 31 | rm ${{ secrets.DEV_DIST }}/maintenance.enable 32 | 33 | - name: Discord notification 34 | env: 35 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_BETA }} 36 | DISCORD_USERNAME: "Github Monitoring" 37 | DISCORD_AVATAR: "https://i.imgur.com/lPRYnJx.png" 38 | uses: Ilshidur/action-discord@master 39 | with: 40 | args: | 41 | **${{ github.repository }}** has been deployed on beta.squadcalc.app 42 | **Commit**: ${{ github.event.head_commit.message }} -------------------------------------------------------------------------------- /src/components/header/header.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 7 | 10 |
11 | 12 |
13 | 16 | 22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 | 33 |
-------------------------------------------------------------------------------- /config/.eslintrc.js: -------------------------------------------------------------------------------- 1 | import globals from "globals"; 2 | import js from "@eslint/js"; 3 | 4 | export default [ 5 | js.configs.recommended, 6 | { 7 | ignores: ["**/tests/*.js"], 8 | languageOptions: { 9 | ecmaVersion: "latest", 10 | sourceType: "module", 11 | globals: { 12 | ...globals.browser, 13 | ...globals.node, 14 | ...globals.es2021, 15 | ...globals.jquery, 16 | } 17 | }, 18 | rules: { 19 | indent: [ 20 | "error", 21 | 4 22 | ], 23 | "no-compare-neg-zero": "off", 24 | "keyword-spacing": [ 25 | "error", 26 | { "before": true } 27 | ], 28 | "linebreak-style": [ 29 | "error", 30 | "windows" 31 | ], 32 | "quotes": [ 33 | "error", 34 | "double" 35 | ], 36 | "semi": [ 37 | "error", 38 | "always" 39 | ], 40 | "semi-spacing": [ 41 | "error", 42 | {"before": false, "after": true} 43 | ], 44 | "space-unary-ops": [ 45 | "error", 46 | {"words": true, "nonwords": false} 47 | ], 48 | "vars-on-top": [ 49 | "error" 50 | ] 51 | } 52 | } 53 | ]; -------------------------------------------------------------------------------- /.github/workflows/deploy_prod.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Prod 2 | permissions: 3 | contents: read 4 | on: 5 | push: 6 | branches: [ master ] 7 | 8 | jobs: 9 | build: 10 | name: ssh/pull/build 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Pull code & Build 14 | uses: appleboy/ssh-action@v1.2.4 15 | with: 16 | host: ${{ secrets.HOST }} 17 | port: ${{ secrets.PORT }} 18 | username: ${{ secrets.USERNAME }} 19 | password: ${{ secrets.PASSWORD }} 20 | script: | 21 | eval `ssh-agent -s` 22 | ssh-add ~/.ssh/${{ secrets.SSH_PUBLIC_KEY_NAME }} 23 | # Enable maintenance mode 24 | touch ${{ secrets.DIST }}/maintenance.enable 25 | # Deploy 26 | cd ${{ secrets.DIST }} 27 | git pull origin master 28 | npm ci 29 | npm run build 30 | # Disable maintenance mode 31 | rm ${{ secrets.DIST }}/maintenance.enable 32 | 33 | - name: Discord notification 34 | env: 35 | DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} 36 | DISCORD_USERNAME: "Github bot" 37 | DISCORD_AVATAR: "https://i.imgur.com/lPRYnJx.png" 38 | uses: Ilshidur/action-discord@master 39 | with: 40 | args: | 41 | New version has been deployed on squadcalc.app ! 42 | **Full Changelog**: https://github.com/sh4rkman/SquadCalc/blob/master/CHANGELOG.md 43 | **Commit**: ${{ github.event.head_commit.message }} -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | // Node Modules 2 | import "purecss/build/pure-min.css"; 3 | import "purecss/build/grids-responsive-min.css"; 4 | import "select2/dist/css/select2.min.css"; 5 | import "select2/dist/js/select2.min.js"; 6 | import "animate.css"; 7 | import "leaflet/dist/leaflet.css"; 8 | 9 | // Local styles 10 | import "./components/header/header.scss"; 11 | import "./components/footer/footer.scss"; 12 | 13 | import "./components/map/map.scss"; 14 | import "./components/map/mapFactionCtxMenu.scss"; 15 | import "./components/map/mapObjectives.scss"; 16 | import "./components/map/mapButtons.scss"; 17 | import "./components/map/mapLogo.scss"; 18 | 19 | import "./components/legacyui/legacyui.scss"; 20 | 21 | import "./components/dialogs/dialogs.scss"; 22 | import "./components/dialogs/factions.scss"; 23 | import "./components/dialogs/settings.scss"; 24 | import "./components/dialogs/servers.scss"; 25 | 26 | import "./components/shared/_tooltips.scss"; 27 | import "./components/shared/_responsive.scss"; 28 | 29 | import "./components/contextMenu/contextMenu.scss"; 30 | 31 | import "./components/shared/snow.scss"; 32 | 33 | // JS 34 | import SquadCalc from "./js/squadCalc.js"; 35 | 36 | 37 | /***************/ 38 | // Start the App 39 | /***************/ 40 | 41 | var options = { 42 | supportedLanguages: [ 43 | ["en", "EN"], 44 | ["zh", "中文"], 45 | ["uk", "UKR"], 46 | ["ru", "РУС"], 47 | ["fr", "FR"], 48 | ["de", "DE"] 49 | ], 50 | gravity: 9.78, 51 | mapSize: 256, 52 | debug: false, 53 | }; 54 | 55 | export var App = new SquadCalc(options); 56 | App.init(); -------------------------------------------------------------------------------- /src/js/sw.js: -------------------------------------------------------------------------------- 1 | import { precacheAndRoute, cleanupOutdatedCaches } from "workbox-precaching"; 2 | import { clientsClaim } from "workbox-core"; 3 | import { registerRoute } from "workbox-routing"; 4 | import { StaleWhileRevalidate } from "workbox-strategies"; 5 | import { ExpirationPlugin } from "workbox-expiration"; 6 | 7 | self.skipWaiting(); 8 | clientsClaim(); 9 | cleanupOutdatedCaches(); 10 | 11 | precacheAndRoute(self.__WB_MANIFEST); 12 | 13 | registerRoute( 14 | ({ url }) => url.pathname.includes("/maps/") && url.pathname.endsWith(".webp"), 15 | new StaleWhileRevalidate ({ 16 | cacheName: "map-images", 17 | plugins: [ 18 | new ExpirationPlugin({ 19 | maxEntries: 30, 20 | maxAgeSeconds: 60 * 60 * 24 * 30, // 30 days 21 | purgeOnQuotaError: true, 22 | }), 23 | ], 24 | }) 25 | ); 26 | 27 | // registerRoute( 28 | // ({ url }) => url.pathname.includes("/maps/") && url.pathname.endsWith("heightmap.json"), 29 | // new StaleWhileRevalidate({ 30 | // cacheName: "map-heightmap", 31 | // plugins: [ 32 | // new ExpirationPlugin({ 33 | // maxEntries: 30, 34 | // maxAgeSeconds: 60 * 60 * 24 * 30, // 30 days 35 | // purgeOnQuotaError: true, 36 | // }), 37 | // ], 38 | // }) 39 | // ); 40 | 41 | // registerRoute( 42 | // ({ url }) => url.pathname.includes("/locales/") && url.pathname.endsWith(".json"), 43 | // new StaleWhileRevalidate({ 44 | // cacheName: "locales", 45 | // plugins: [ 46 | // new ExpirationPlugin({ 47 | // maxEntries: 30, 48 | // maxAgeSeconds: 60 * 60 * 24 * 30, // 30 days 49 | // purgeOnQuotaError: true, 50 | // }), 51 | // ], 52 | // }) 53 | // ); -------------------------------------------------------------------------------- /src/js/libs/leaflet-spin.js: -------------------------------------------------------------------------------- 1 | /* Leaflet Spin Plugin - v2.0 Compatible */ 2 | 3 | import { LeafletMap } from "leaflet"; 4 | import { Spinner } from "spin.js"; 5 | import "spin.js/spin.css"; 6 | 7 | var SpinMapMixin = { 8 | spin: function (state, options) { 9 | if (state) { 10 | // start spinning ! 11 | if (!this._spinner) { 12 | this._spinner = new Spinner(options) 13 | .spin(this._container); 14 | this._spinning = 0; 15 | } 16 | this._spinning++; 17 | } 18 | else { 19 | this._spinning--; 20 | if (this._spinning <= 0) { 21 | // end spinning ! 22 | if (this._spinner) { 23 | this._spinner.stop(); 24 | this._spinner = null; 25 | } 26 | } 27 | } 28 | } 29 | }; 30 | 31 | var SpinMapInitHook = function () { 32 | this.on("layeradd", function (e) { 33 | // If added layer is currently loading, spin ! 34 | if (e.layer.loading) this.spin(true); 35 | if (typeof e.layer.on !== "function") return; 36 | e.layer.on("data:loading", function () { 37 | this.spin(true); 38 | }, this); 39 | e.layer.on("data:loaded", function () { 40 | this.spin(false); 41 | }, this); 42 | }, this); 43 | this.on("layerremove", function (e) { 44 | // Clean-up 45 | if (e.layer.loading) this.spin(false); 46 | if (typeof e.layer.on !== "function") return; 47 | e.layer.off("data:loaded"); 48 | e.layer.off("data:loading"); 49 | }, this); 50 | }; 51 | 52 | // Apply to Map prototype (replaces L.Map.include) 53 | Object.assign(LeafletMap.prototype, SpinMapMixin); 54 | 55 | // Add init hook (replaces L.Map.addInitHook) 56 | const originalInitialize = LeafletMap.prototype.initialize; 57 | LeafletMap.prototype.initialize = function(id, options) { 58 | const result = originalInitialize.call(this, id, options); 59 | SpinMapInitHook.call(this); 60 | return result; 61 | }; 62 | 63 | export default SpinMapMixin; -------------------------------------------------------------------------------- /public/locales/zh/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SettingsTitle": "设置", 3 | "map": "地图", 4 | "mortars": "迫击炮", 5 | "layer": "地图猜点", 6 | "mapOptions": "地图选项", 7 | "showKeypad": "在光标下显示键盘", 8 | "useClassicCursor": "使用系统的鼠标样式", 9 | "mapAnimationSettings": "平移/缩放动画", 10 | "highquality": "使用高清化的地图", 11 | "contextMenu": "右键点击添加自定义标记", 12 | "gridOpacity": "网格不透明度", 13 | "zoomSensitivity": "缩放灵敏度", 14 | "fontSize": "字体大小", 15 | "brightness": "亮度", 16 | "contrast": "对比度", 17 | "weaponOptions": "武器选项", 18 | "weaponDrag": "拖动时显示网格坐标", 19 | "realMaxRange": "使用武器实际最大范围", 20 | "moddedWeapons": "启用Mod版武器", 21 | "targetOptions": "目标选项", 22 | "targetDrag": "拖动时显示网格坐标", 23 | "showSpread": "显示散布半径", 24 | "showDamage": "显示伤害半径", 25 | "targetGrid": "偏差网格", 26 | "showAnimations": "使用大图标", 27 | "copyTarget": "自动复制计算结果", 28 | "lowAndHigh": "显示低角度和高角度", 29 | "showBearing": "显示方位", 30 | "showDistance": "显示距离", 31 | "showTimeOfFlight": "显示飞行时间", 32 | "showHeightDiff": "显示高度差", 33 | "lineToTarget": "指向目标的线", 34 | "lastDigits": "精简海拔显示", 35 | "factionsOptions": "阵营选项", 36 | "defaultFactions": "自动选择阵营", 37 | "enableFactions": "启用阵营", 38 | "hideLowRespawn": "仅跟踪高重生时间的载具", 39 | "disableSounds": "禁用重生通知音效", 40 | "LaneFinderOptions": "猜点选项", 41 | "capZoneOnHover": "仅在鼠标悬停时显示可拉点区域", 42 | "revealLayerOnHover": "隐藏互斥点位", 43 | "circlesFlags": "圆形目标点标记", 44 | "copyNextFlags": "自动复制下一个点的名称", 45 | "showFlagsDistance": "显示目标点间距", 46 | "showMainZones": "显示主要目标点", 47 | "showMainAssets": "显示主要资产", 48 | "showMapBorders": "显示地图边界", 49 | "showNextFlagPercentage": "显示下一个旗帜的概率分布", 50 | "respawnCam": "显示重生摄像头位置", 51 | "shortcuts": "快捷键", 52 | "enter": "进入专注模式,隐藏所有按钮", 53 | "deleteLastTarget": "删除地图上最后放置的目标", 54 | "changelog": "更新日志", 55 | "github": "在GitHub上查看本开源项目的代码!", 56 | "discord": "官方Discord频道", 57 | "wiki": "SquadCalc wiki" 58 | } -------------------------------------------------------------------------------- /src/js/libs/leaflet-rotatedMarker.js: -------------------------------------------------------------------------------- 1 | /* Leaflet EdgeBuffer Plugin 2 | * https://github.com/bbecquet/Leaflet.RotatedMarker 3 | * (MIT) Copyright (c) 2015 Benjamin Becquet 4 | * 5 | * edited by Maxime "sharkman" Boussard for leaflet v2.0 6 | */ 7 | 8 | import { Marker } from "leaflet"; 9 | 10 | (function() { 11 | const proto_initIcon = Marker.prototype._initIcon; 12 | const proto_setPos = Marker.prototype._setPos; 13 | 14 | Marker.addInitHook(function () { 15 | const iconOptions = this.options.icon && this.options.icon.options; 16 | const iconAnchor = iconOptions && iconOptions.iconAnchor; 17 | 18 | this.options.rotationOrigin = this.options.rotationOrigin || 19 | (iconAnchor ? iconAnchor[0] + "px " + iconAnchor[1] + "px" : "center bottom"); 20 | this.options.rotationAngle = this.options.rotationAngle || 0; 21 | 22 | this.on("drag", () => this._applyRotation()); 23 | }); 24 | 25 | Marker.include({ 26 | _initIcon: function() { 27 | proto_initIcon.call(this); 28 | this._applyRotation(); 29 | }, 30 | 31 | _setPos: function (pos) { 32 | proto_setPos.call(this, pos); 33 | this._applyRotation(); 34 | }, 35 | 36 | _applyRotation: function () { 37 | if (!this._icon) return; 38 | 39 | if (this.options.rotationAngle) { 40 | this._icon.style.transformOrigin = this.options.rotationOrigin; 41 | 42 | // Keep Leaflet's translate3d and add rotation 43 | const transform = this._icon.style.transform || ""; 44 | const translate = transform.match(/translate3d\([^)]+\)/); 45 | 46 | this._icon.style.transform = 47 | (translate ? translate[0] : "") + 48 | ` rotateZ(${this.options.rotationAngle}deg)`; 49 | } 50 | }, 51 | 52 | setRotationAngle: function(angle) { 53 | this.options.rotationAngle = angle; 54 | this.update(); 55 | return this; 56 | }, 57 | 58 | setRotationOrigin: function(origin) { 59 | this.options.rotationOrigin = origin; 60 | this.update(); 61 | return this; 62 | } 63 | }); 64 | })(); -------------------------------------------------------------------------------- /public/locales/zh/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "squad": "SQUAD", 3 | "calc": "CALC", 4 | "squadcalc": "SquadCalc", 5 | "desc": "多功能SQUAD迫击炮计算器", 6 | "weaponInf": "武器信息", 7 | "name": "名称", 8 | "range": "射程", 9 | "velocity": "速度", 10 | "moa": "角分 (MOA)", 11 | "100radius": "100 伤害半径", 12 | "25radius": "25 伤害半径", 13 | "angle": "角度", 14 | "high": "高", 15 | "low": "低", 16 | "addHeight": "额外高度", 17 | "meters": "米", 18 | "km": "千米", 19 | "m": "米", 20 | "s": "秒", 21 | "°": "°", 22 | "min": "分", 23 | "targetInf": "目标信息", 24 | "weapon1": "武器 1", 25 | "weapon2": "武器 2", 26 | "bearing": "方位", 27 | "elevation": "高度", 28 | "distance": "距离", 29 | "timeOfFlight": "飞行时间", 30 | "spread": "散布", 31 | "weaponHeight": "武器高度", 32 | "targetHeight": "目标高度", 33 | "heightDiff": "高度差", 34 | "outOfRange": "目标超出射程:", 35 | "invalidMortar": "无效的武器", 36 | "invalidTarget": "无效的目标", 37 | "invalidMortarTarget": "取消武器和目标", 38 | "targetOutOfRange": "目标超出范围", 39 | "layerPlaceholder": "地图版本", 40 | "nextFlags": "下一个点", 41 | "dropTxt": "拖放存档文件到这里", 42 | "dropSubTxt": "当前地图将被清除", 43 | "faction": "阵营", 44 | "unit": "单位", 45 | "respawn": "重生", 46 | "delayed": "延迟", 47 | "team1": "队伍 1", 48 | "team2": "队伍 2", 49 | "pinToMap": "固定到地图", 50 | "pinned": "已固定", 51 | "randomSpawn": "随机出生点", 52 | "dedicactedSpawn": "固定出生点", 53 | "amphibious": "两栖", 54 | "atgm": "反坦克导弹", 55 | "value": "值", 56 | "ticket": "票", 57 | "tickets": "票", 58 | "passengers": "可用座位", 59 | "noCommander": "无指挥官资源", 60 | "spawn": "生成", 61 | "temporary": "临时生成", 62 | "disabledSpawn": "首次占领前禁用", 63 | "respawnCamera": "重生摄像头", 64 | "rightClicToRemove": "右键点击以移除标记", 65 | "loadingServers": "正在加载服务器...", 66 | "errorLoading": "加载服务器时出错。", 67 | "searchServerPlaceholder": "搜索服务器...", 68 | "serverName": "服务器名称", 69 | "currentMap": "当前地图", 70 | "players": "玩家数", 71 | "noServersFound": "未找到服务器。", 72 | "server": "服务器", 73 | "servers": "服务器", 74 | "load": "加载", 75 | "next": "下一个", 76 | "playTime": "地图时间", 77 | "mapSyncedwith": "地图已同步至" 78 | } 79 | -------------------------------------------------------------------------------- /src/components/dialogs/factions.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 |
7 | 8 |

9 | 10 |
11 |
12 |

13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |

24 |
25 |
26 | 27 |
28 |
29 | 30 |
31 |
32 |
33 |
34 | 35 |
36 | 37 | 38 |
39 | 40 | 41 |
42 |
43 |
44 |
45 | 46 |
47 |
48 |
49 |
50 | 51 | 52 |
-------------------------------------------------------------------------------- /src/components/contextMenu/contextMenu.scss: -------------------------------------------------------------------------------- 1 | @use "../shared/variables"; 2 | 3 | 4 | .contextmenu { 5 | display: flex; 6 | padding: 0; 7 | .ctxButton, .shapeButton { 8 | margin: 2px; 9 | background-color: rgba(0, 0, 0, 0.5); 10 | cursor: pointer; 11 | align-items: center; 12 | display: flex; 13 | &:hover { 14 | background-color: rgba(0, 0, 0, 0.7); 15 | } 16 | } 17 | .middleContextButton { 18 | background-color: transparent; 19 | align-content: center; 20 | &:hover { 21 | background-color: transparent; 22 | } 23 | &:active { 24 | transform: scale(0.9); 25 | } 26 | } 27 | span { 28 | width: 25px; 29 | height: 25px; 30 | } 31 | .contextmenuVert { 32 | width: 140px; 33 | height: auto; 34 | display: flex; 35 | flex-wrap: wrap; 36 | background-color: rgba(0, 0, 0, 0.6); 37 | margin: 0; 38 | padding: 0; 39 | overflow: hidden; 40 | backdrop-filter: blur(2px); 41 | .ctxButton, .shapeButton { 42 | margin: 0; 43 | padding: 2px 0.5px; 44 | background-color: transparent; 45 | transition: background-color 0.2s; 46 | span { 47 | margin: 0; 48 | padding: 0; 49 | height: 27px; 50 | width: 27px; 51 | } 52 | &:hover { 53 | background-color: rgba(0, 0, 0, 0.7); 54 | transform: scale(1.2); 55 | z-index: 1; 56 | } 57 | } 58 | } 59 | } 60 | 61 | 62 | // COMMON 63 | 64 | .middleContext { 65 | background-size: contain; 66 | } 67 | 68 | .arrow, .rectangle, .circle { 69 | background-size: contain; 70 | background-repeat: no-repeat; 71 | background-position: center center; 72 | &.blue { 73 | background-color: #00137e; 74 | &:hover { background-color: #000844; } 75 | } 76 | &.red { 77 | background-color: #bb2623; 78 | &:hover { background-color: #6b1716; } 79 | } 80 | &.green { 81 | background-color: #007f00; 82 | &:hover { background-color: #005200; } 83 | } 84 | &.black { 85 | background-color: #141414; 86 | &:hover { background-color: #000; } 87 | } 88 | } 89 | 90 | .tippy-box[data-theme~="contextmenu"] { 91 | background-color: transparent; 92 | .tippy-content { 93 | padding: 0; 94 | } 95 | } -------------------------------------------------------------------------------- /src/js/libs/leaflet-visual-click.js: -------------------------------------------------------------------------------- 1 | /* 2 | * L.VisualClick 3 | * Description: A plugin that adds visual feedback when user clicks/taps the map. Useful for when you have a delay on the clickEvents for async fetching of data, or implmentation of Leaflet.singleclick 4 | * Example: L.visualClick({map: leafletMap}); //Just works 5 | * Author: Dag Jomar Mersland (twitter: @dagjomar) 6 | * 7 | * Modified by Maxime "sharkman" Boussard for https://github.com/sh4rkman/SquadCalc 8 | * The patch change the visualClick to be manually triggered and its color to be set 9 | */ 10 | 11 | import { Map, Marker, Handler, DivIcon, Browser} from "leaflet"; 12 | 13 | Map.VisualClick = Handler.extend({ 14 | 15 | _makeVisualIcon: function(color){ 16 | var touchMode = this._map.options.visualClickMode === "touch" ? true : false; 17 | return new DivIcon({ 18 | className: "leaflet-visualclick-icon" + (touchMode ? "-touch" : "") + " " + color, 19 | iconSize: [0, 0], 20 | clickable: false 21 | }); 22 | }, 23 | 24 | _visualIcon: null, 25 | 26 | triggerVisualClick: function(latlng, color = "white") { 27 | 28 | var map = this._map; 29 | 30 | var marker = new Marker(latlng, { 31 | pane: this._map.options.visualClickPane, 32 | icon: this._makeVisualIcon(color), 33 | interactive: false 34 | }).addTo(map); 35 | 36 | window.setTimeout(function(){ 37 | if (map){ 38 | map.removeLayer(marker); 39 | } 40 | }.bind(this), map.options.visualClick.removeTimeout || 450); // Should somewhat match the css animation to prevent loops 41 | 42 | return true; 43 | }, 44 | 45 | addHooks: function () { 46 | if (this._map.options.visualClickPane === "ie10-visual-click-pane") { 47 | this._map.createPane("ie10-visual-click-pane"); 48 | } 49 | }, 50 | 51 | }); 52 | 53 | 54 | Map.mergeOptions({ 55 | visualClick: Browser.any3d ? true : false, //Can be true, desktop, touch, false. Not straight forward to use L.Browser.touch flag because true on IE10 56 | visualClickMode: Browser.touch && Browser.mobile ? "touch" : "desktop", //Not straight forward to use only L.Browser.touch flag because true on IE10 - so this is slightly better 57 | visualClickPane: (Browser.ie && document.documentMode === 10) ? 58 | "ie10-visual-click-pane" : 59 | "shadowPane" // Map pane where the pulse markers will be shown 60 | }); 61 | 62 | Map.addInitHook("addHandler", "visualClick", Map.VisualClick); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "squadcalc", 3 | "version": "41.1.0", 4 | "description": "A Complete Mortar Calculator and Map Lane Finder for Squad", 5 | "author": "Maxime 'sharkman' Boussard", 6 | "license": "MIT", 7 | "type": "module", 8 | "keywords": [ 9 | "squad", 10 | "squadcalc", 11 | "mortar", 12 | "calculator", 13 | "lane", 14 | "map" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "git:/github.com/sh4rkman/SquadCalc" 19 | }, 20 | "homepage": "https://squadcalc.app/", 21 | "bugs": { 22 | "url": "https://github.com/sh4rkman/SquadCalc/issues" 23 | }, 24 | "private": false, 25 | "jshintConfig": { 26 | "esversion": 11 27 | }, 28 | "scripts": { 29 | "start": "webpack serve -c ./config/webpack.config.js", 30 | "build": "webpack -c ./config/webpack.config.js", 31 | "lint": "stylelint -c ./config/.stylelintrc.json ./src/**/*.scss && htmlhint --config ./config/.htmlhintrc.json --nocolor ./src/ && jshint ./src/ && eslint --fix -c ./config/.eslintrc.js ./src/", 32 | "mapinfo": "node src/js/data/maps.js mapinfo" 33 | }, 34 | "devDependencies": { 35 | "@types/leaflet": "^1.9.15", 36 | "@types/node": "^22.10.3", 37 | "animate.css": "^4.1.1", 38 | "copy-webpack-plugin": "^12.0.2", 39 | "css-loader": "^7.1.2", 40 | "css-minimizer-webpack-plugin": "^7.0.0", 41 | "dotenv-webpack": "^8.1.0", 42 | "eslint": "^9.17.0", 43 | "fs-extra": "^11.2.0", 44 | "fuse.js": "^7.1.0", 45 | "html-loader": "^5.1.0", 46 | "html-webpack-plugin": "^5.6.3", 47 | "htmlhint": "^1.1.4", 48 | "i18next": "^24.2.0", 49 | "i18next-http-backend": "^3.0.1", 50 | "jquery": "^3.7.1", 51 | "jshint": "^2.13.6", 52 | "leaflet": "^2.0.0-alpha.1", 53 | "leaflet-loader": "^0.0.3", 54 | "leaflet-polylinedecorator": "^1.6.0", 55 | "mini-css-extract-plugin": "^2.9.2", 56 | "mkdirp": "^3.0.1", 57 | "path": "^0.12.7", 58 | "postcss": ">=8.4.49", 59 | "purecss": "^3.0.0", 60 | "robotstxt-webpack-plugin": "^8.0.0", 61 | "sass": "^1.83.0", 62 | "sass-loader": "^16.0.4", 63 | "select2": "^4.1.0-rc.0", 64 | "sharp": "^0.33.5", 65 | "spin.js": "^4.1.2", 66 | "style-loader": "^4.0.0", 67 | "stylelint": "^16.12.0", 68 | "stylelint-config-standard-scss": "^14.0.0", 69 | "tippy.js": "^6.3.7", 70 | "uuid": "^11.0.5", 71 | "webpack": "^5.97.1", 72 | "webpack-cli": "^6.0.1", 73 | "webpack-dev-server": "^5.2.0", 74 | "webpack-merge": "^6.0.1", 75 | "webpack-pwa-manifest": "^4.3.0", 76 | "workbox-webpack-plugin": "^7.3.0" 77 | }, 78 | "overrides": { 79 | "phin": "^3.7.1" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /public/locales/en/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SettingsTitle": "Settings", 3 | "map": "Map", 4 | "mortars": "Mortars", 5 | "layer": "Layers", 6 | "mapOptions": "Map Options", 7 | "showKeypad": "Keypads under Cursor", 8 | "useClassicCursor": "Use Classic Cursor", 9 | "mapAnimationSettings": "Pan/Zoom Animations", 10 | "highquality": "Very High quality maps", 11 | "contextMenu": "Custom markers on right click", 12 | "gridOpacity": "Grid Opacity", 13 | "zoomSensitivity": "Zoom Sensitivity", 14 | "fontSize": "Font Size", 15 | "brightness": "Brightness", 16 | "contrast": "Contrast", 17 | "weaponOptions": "Weapons Options", 18 | "weaponDrag": "Keypads while dragging", 19 | "realMaxRange": "Use Real Max Range", 20 | "moddedWeapons": "Enable modded weapons", 21 | "targetOptions": "Targets Options", 22 | "targetDrag": "Keypads while dragging", 23 | "showSpread": "Spread Radius", 24 | "showDamage": "Damage Radiuses", 25 | "targetGrid": "Deviation Grid", 26 | "lineToTarget": "Line to target", 27 | "showAnimations": "Use Large Icons", 28 | "copyTarget": "Auto-copy Target to clipboard", 29 | "lowAndHigh": "Show both Low and High angles", 30 | "lastDigits": "Compact Elevation display", 31 | "showBearing": "Bearing", 32 | "showDistance": "Distance", 33 | "showTimeOfFlight": "Time of Flight", 34 | "showHeightDiff": "Height Difference", 35 | "LaneFinderOptions": "Layers Options", 36 | "capZoneOnHover": "Only show capzones when hovering", 37 | "revealLayerOnHover" : "Reveal layer when hovering a flag", 38 | "circlesFlags": "Show Flags as circles", 39 | "copyNextFlags": "Auto-copy next flags to clipboard", 40 | "showFlagsDistance": "Show distance between flags", 41 | "showMainZones": "Show Main Zones", 42 | "showMainAssets": "Show Main Assets", 43 | "showMapBorders": "Show Layer Map Border", 44 | "showNextFlagPercentage": "Show Next Flags Probabilities", 45 | "respawnCam": "Show Respawn Camera Position", 46 | "factionsOptions": "Factions Options", 47 | "defaultFactions": "Auto-Select Layer's Default Factions", 48 | "enableFactions": "Enable Factions", 49 | "hideLowRespawn": "Only Track High Respawn Times Vehicles", 50 | "disableSounds": "Disable Respawn Notification Sounds", 51 | "shortcuts": "Shortcuts", 52 | "enter": "Enter focus mode, hiding UI buttons", 53 | "deleteLastTarget": "Delete last placed target on the map", 54 | "discord": "Official Discord", 55 | "github": "View code on Github", 56 | "changelog": "ChangeLog", 57 | "wiki": "SquadCalc Wiki" 58 | } -------------------------------------------------------------------------------- /public/locales/en/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "squad": "SQUAD", 3 | "calc": "CALC", 4 | "squadcalc": "SquadCalc", 5 | "desc": "A Complete Mortar Calculator and map lane finder for SQUAD !", 6 | "weaponInf": "Weapon Informations", 7 | "name": "Name", 8 | "range": "Range", 9 | "velocity": "Velocity", 10 | "moa": "MOA", 11 | "100radius": "100 DAMAGE RADIUS", 12 | "25radius": "25 DAMAGE RADIUS", 13 | "angle": "Angle", 14 | "high": "high", 15 | "low": "low", 16 | "addHeight": "ADDITIONAL HEIGHT", 17 | "meters": "meters", 18 | "km": "km", 19 | "m": "m", 20 | "s": "s", 21 | "°": "°", 22 | "min": "min", 23 | "targetInf": "Target Informations", 24 | "weapon1": "Weapon 1", 25 | "weapon2": "Weapon 2", 26 | "bearing": "Bearing", 27 | "elevation": "Elevation", 28 | "distance": "Distance", 29 | "timeOfFlight": "Time of Flight", 30 | "spread": "Spread", 31 | "weaponHeight": "Weapon Height", 32 | "targetHeight": "Target Height", 33 | "heightDiff": "Height Difference", 34 | "outOfRange": "Target is out of range :", 35 | "invalidMortar": "Invalid Weapon", 36 | "invalidTarget": "Invalid Target", 37 | "invalidMortarTarget": "Invalid Weapon & Target", 38 | "targetOutOfRange": "Target is out of range", 39 | "layerPlaceholder": "Layer", 40 | "nextFlags": "Next Flags", 41 | "dropTxt": "DROP A SAVE FILE HERE", 42 | "dropSubTxt": "current map will be erased", 43 | "faction": "Faction", 44 | "unit": "Unit", 45 | "respawn": "Respawn", 46 | "delayed": "Delayed", 47 | "team1": "Team 1", 48 | "team2": "Team 2", 49 | "pinToMap": "Pin to map", 50 | "pinned": "Pinned", 51 | "randomSpawn": "Random", 52 | "dedicactedSpawn": "Dedicated", 53 | "amphibious": "Water-capable", 54 | "atgm": "ATGM", 55 | "value": "Value", 56 | "ticket": "Ticket", 57 | "tickets": "Tickets", 58 | "passengers": "Available Seats", 59 | "noCommander": "No commander assets", 60 | "spawn": "Spawn", 61 | "temporary": "Temporary Spawn", 62 | "disabledSpawn": "Disabled until first cap", 63 | "respawnCamera": "Respawn Camera", 64 | "rightClicToRemove": "Right click to remove", 65 | "loadingServers": "Loading servers...", 66 | "errorLoading": "Error loading server data.", 67 | "searchServerPlaceholder": "Search by server name or map", 68 | "serverName": "Server Name", 69 | "currentMap": "Current Map", 70 | "players": "Players", 71 | "noServersFound": "No servers found.", 72 | "server": "server", 73 | "servers": "servers", 74 | "load": "Load", 75 | "next": "Next", 76 | "playTime": "Play Time", 77 | "mapSyncedwith": "Map Synced with" 78 | } -------------------------------------------------------------------------------- /public/locales/de/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "squad": "SQUAD", 3 | "calc": "CALC", 4 | "squadcalc": "SquadCalc", 5 | "desc": "Ein vollständiger Mörser-Rechner und Routen-Finder für SQUAD!", 6 | "weaponInf": "Waffeninformationen", 7 | "name": "Name", 8 | "range": "Reichweite", 9 | "velocity": "Geschwindigkeit", 10 | "moa": "MOA", 11 | "100radius": "100 SCHADENSRADIUS", 12 | "25radius": "25 SCHADENSRADIUS", 13 | "angle": "Winkel", 14 | "high": "steil", 15 | "low": "flach", 16 | "addHeight": "ZUSÄTZLICHE HÖHE", 17 | "meters": "Meter", 18 | "m": "m", 19 | "s": "s", 20 | "°": "°", 21 | "targetInf": "Zielinformationen", 22 | "weapon1": "Waffe 1", 23 | "weapon2": "Waffe 2", 24 | "bearing": "Peilung", 25 | "elevation": "Elevation", 26 | "distance": "Entfernung", 27 | "timeOfFlight": "Flugzeit", 28 | "spread": "Streuung", 29 | "weaponHeight": "Waffenhöhe", 30 | "targetHeight": "Zielhöhe", 31 | "heightDiff": "Höhenunterschied", 32 | "outOfRange": "Ziel ist außer Reichweite:", 33 | "invalidMortar": "Ungültige Waffe", 34 | "invalidTarget": "Ungültiges Ziel", 35 | "invalidMortarTarget": "Ungültige Waffe & Ziel", 36 | "targetOutOfRange": "Ziel ist außer Reichweite", 37 | "layerPlaceholder": "Layer", 38 | "nextFlags": "Nächste Flaggen", 39 | "dropTxt": "SPEICHERDATEI HIER ABLEGEN", 40 | "dropSubTxt": "aktuelle Karte wird überschrieben", 41 | "faction": "Fraktion", 42 | "unit": "Einheit", 43 | "respawn": "Wiederbelebung", 44 | "delayed": "Verzögert", 45 | "team1": "Team 1", 46 | "team2": "Team 2", 47 | "pinToMap": "An Karte anheften", 48 | "pinned": "Angeheftet", 49 | "randomSpawn": "Zufälliger", 50 | "dedicactedSpawn": "Fester", 51 | "amphibious": "Amphibisch", 52 | "atgm": "ATGM", 53 | "value": "Wert", 54 | "ticket": "Ticket", 55 | "tickets": "Tickets", 56 | "passengers": "Verfügbare Sitze", 57 | "noCommander": "Keine Kommandanten-Ressourcen", 58 | "spawn": "Erscheinen", 59 | "temporary": "Vorübergehend Erscheinen", 60 | "disabledSpawn": "Bis zur ersten Eroberung deaktiviert", 61 | "respawnCamera": "Wiederbelebungskamera", 62 | "rightClicToRemove": "Rechtsklick zum Entfernen der Markierung", 63 | "loadingServers": "Lade Server...", 64 | "errorLoading": "Fehler beim Laden der Server.", 65 | "searchServerPlaceholder": "Suche nach Servernamen oder Karte...", 66 | "serverName": "Servername", 67 | "currentMap": "Karte", 68 | "players": "Spieler", 69 | "noServersFound": "Keine Server gefunden.", 70 | "server": "Server", 71 | "servers": "Server", 72 | "load": "Laden", 73 | "next": "Nächste", 74 | "playTime": "Spielzeit", 75 | "mapSyncedwith": "Karte synchronisiert mit" 76 | } -------------------------------------------------------------------------------- /public/locales/uk/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "squad": "SQUAD", 3 | "calc": "CALC", 4 | "squadcalc": "ВигонРозрахунок", 5 | "desc": "Повний калькулятор мінометів для SQUAD!", 6 | "weaponInf": "Інформація про зброю", 7 | "name": "Назва", 8 | "range": "Дальність", 9 | "velocity": "Швидкість", 10 | "moa": "МОА", 11 | "100radius": "РАДІУС ПОШКОДЖЕННЯ 100", 12 | "25radius": "РАДІУС ПОШКОДЖЕННЯ 25", 13 | "angle": "Кут", 14 | "high": "високий", 15 | "low": "низький", 16 | "addHeight": "ДОДАТКОВА ВИСОТА", 17 | "meters": "метри", 18 | "m": "м", 19 | "s": "с", 20 | "°": "°", 21 | "targetInf": "Інформація про ціль", 22 | "weapon1": "Зброя 1", 23 | "weapon2": "Зброя 2", 24 | "bearing": "Підшипник", 25 | "elevation": "Висота", 26 | "distance": "Відстань", 27 | "timeOfFlight": "Час польоту", 28 | "spread": "Розподіл", 29 | "weaponHeight": "Висота зброї", 30 | "targetHeight": "Висота цілі", 31 | "heightDiff": "Різниця висот", 32 | "outOfRange": "Ціль знаходиться за межами дальності:", 33 | "invalidMortar": "Недійсна зброя", 34 | "invalidTarget": "Недійсна ціль", 35 | "invalidMortarTarget": "Непридатна зброя та мішень", 36 | "targetOutOfRange": "Ціль поза зоною досяжності", 37 | "layerPlaceholder": "Layer", 38 | "nextFlags": "Наступні прапори", 39 | "dropTxt": "ПЕРЕТЯГНІТЬ ФАЙЛ ЗБЕРЕЖЕННЯ СЮДИ", 40 | "dropSubTxt": "поточна карта буде стерта", 41 | "faction": "Фракція", 42 | "unit": "Підрозділ", 43 | "respawn": "Відродження", 44 | "delayed": "Затримка", 45 | "team1": "Команда 1", 46 | "team2": "Команда 2", 47 | "pinToMap": "Закріпити на мапі", 48 | "pinned": "Закріплено", 49 | "randomSpawn": "Випадкова", 50 | "dedicactedSpawn": "Фіксована", 51 | "amphibious": "Амфібія", 52 | "atgm": "ПТКР", 53 | "value": "Значення", 54 | "ticket": "Квиток", 55 | "tickets": "Квитки", 56 | "passengers": "Доступні місця", 57 | "noCommander": "Немає командирських ресурсів", 58 | "spawn": "Виникнення", 59 | "temporary": "Тимчасово Виникнення", 60 | "disabledSpawn": "Вимкнено до першого захоплення", 61 | "respawnCamera": "Камера відродження", 62 | "rightClicToRemove": "Клацніть правою кнопкою м", 63 | "loadingServers": "Завантаження серверів...", 64 | "errorLoading": "Помилка завантаження серверів.", 65 | "searchServerPlaceholder": "Пошук сервера або карти...", 66 | "serverName": "Назва сервера", 67 | "currentMap": "Поточна карта", 68 | "players": "Гравці", 69 | "noServersFound": "Сервери не знайдені.", 70 | "server": "сервер", 71 | "servers": "сервери", 72 | "load": "Завантажити", 73 | "next": "Наступна", 74 | "playTime": "Час на мапі", 75 | "mapSyncedwith": "Мапу синхронізовано з" 76 | } 77 | -------------------------------------------------------------------------------- /public/locales/ru/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "squad": "SQUAD", 3 | "calc": "CALC", 4 | "squadcalc": "SquadCalc", 5 | "desc": "Полный калькулятор минометов для SQUAD!", 6 | "weaponInf": "Информация о вооружении", 7 | "name": "Название", 8 | "range": "Дальность", 9 | "velocity": "Скорость", 10 | "moa": "УГМ", 11 | "100radius": "100 РАДИУС ПОВРЕЖДЕНИЯ", 12 | "25radius": "25 РАДИУС ПОВРЕЖДЕНИЯ", 13 | "angle": "Угол", 14 | "high": "высоко", 15 | "low": "низко", 16 | "addHeight": "Дополнительная высота", 17 | "meters": "метры", 18 | "m": "м", 19 | "s": "с", 20 | "°": "°", 21 | "targetInf": "Информация о цели", 22 | "weapon1": "Оружие 1", 23 | "weapon2": "Оружие 2", 24 | "bearing": "Пеленг", 25 | "elevation": "Возвышение", 26 | "distance": "Расстояние", 27 | "timeOfFlight": "Время полёта", 28 | "spread": "Разброс", 29 | "weaponHeight": "Высота оружия", 30 | "targetHeight": "Высота цели", 31 | "heightDiff": "Разница высот", 32 | "outOfRange": "Цель вне дальности:", 33 | "invalidMortar": "Неверное оружие", 34 | "invalidTarget": "Неверная цель", 35 | "invalidMortarTarget": "Неверные оружие и цель", 36 | "targetOutOfRange": "Цель находится вне зоны действия", 37 | "layerPlaceholder": "Layer", 38 | "nextFlags": "Следующие флаги", 39 | "dropTxt": "ПЕРЕТАЩИТЕ ФАЙЛ СОХРАНЕНИЯ СЮДА", 40 | "dropSubTxt": "текущие метки и карта будут очищены и заменены", 41 | "faction": "Фракция", 42 | "unit": "Подразделение", 43 | "respawn": "Возрождение", 44 | "delayed": "Задержка", 45 | "team1": "Команда 1", 46 | "team2": "Команда 2", 47 | "pinToMap": "Закрепить на карте", 48 | "pinned": "Закреплено", 49 | "randomSpawn": "Случайная", 50 | "dedicactedSpawn": "Фиксированная", 51 | "amphibious": "Амфибия", 52 | "atgm": "ПТУР", 53 | "value": "Значение", 54 | "ticket": "Билет", 55 | "tickets": "Билеты", 56 | "passengers": "Доступные места", 57 | "noCommander": "Нет ресурсов командира", 58 | "spawn": "Появление", 59 | "temporary": "Временное Появление", 60 | "disabledSpawn": "Отключено до первого захвата", 61 | "respawnCamera": "Камера возрождения", 62 | "rightClicToRemove": "Щелкните правой кнопкой мыши", 63 | "loadingServers": "Загрузка серверов...", 64 | "errorLoading": "Ошибка при загрузке серверов.", 65 | "searchServerPlaceholder": "Поиск сервера или карты...", 66 | "serverName": "Название сервера", 67 | "currentMap": "Текущая карта", 68 | "players": "Игроки", 69 | "noServersFound": "Серверы не найдены.", 70 | "server": "сервер", 71 | "servers": "серверы", 72 | "load": "Загрузить", 73 | "next": "Следующая", 74 | "playTime": "Время на карте", 75 | "mapSyncedwith": "Карта синхронизирована с" 76 | } -------------------------------------------------------------------------------- /public/locales/uk/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SettingsTitle": "Налаштування", 3 | "map": "Мапа", 4 | "mortars": "Міни", 5 | "layer": "Смуга", 6 | "mapOptions": "Опції карти", 7 | "showKeypad": "клавіатуру під курсором", 8 | "useClassicCursor": "классический слайдер", 9 | "mapAnimationSettings": "Анімації масштабування", 10 | "highquality": "Карта високої якості", 11 | "contextMenu": "Користувацькі мітки за правим кліком", 12 | "gridOpacity": "Прозорість сітки", 13 | "zoomSensitivity": "Чутливість масштабу", 14 | "fontSize": "Розмір шрифту", 15 | "brightness": "Яскравість", 16 | "contrast": "Контраст", 17 | "weaponOptions": "Опції зброї", 18 | "weaponDrag": "Сітка маркера", 19 | "realMaxRange": "Використовувати реальну максимальну дальність", 20 | "moddedWeapons": "Увімкнути модову зброю", 21 | "targetOptions": "Опції цілей", 22 | "targetDrag": "Сітка маркера", 23 | "showSpread": "радіус розподілу", 24 | "showDamage": "радіуси ураження", 25 | "targetGrid": "Сітка відхилень", 26 | "showAnimations": "Використовувати великі значки", 27 | "copyTarget": "Автокопіювання цілей", 28 | "lowAndHigh": "Показати низькі та високі кути", 29 | "showBearing": "підшипник", 30 | "showDistance": "відстань", 31 | "showTimeOfFlight": "час польоту", 32 | "showHeightDiff": "різницю висот", 33 | "lineToTarget": "Лінія до цілі", 34 | "lineToTargetTooltip": "Проводить лінію між зброєю та ціллю", 35 | "LaneFinderOptions": "Параметри пошуку смуг", 36 | "capZoneOnHover": "Зони при наведенні", 37 | "revealLayerOnHover": "Показати шар при наведенні на прапор", 38 | "circlesFlags": "Показати прапори у вигляді кіл", 39 | "copyNextFlags": "Автокопіювання наступних прапорів", 40 | "showFlagsDistance": "Показати відстань між прапорами", 41 | "showMainZones": "Показати основні зони", 42 | "showMainAssets": "Показати основні активи", 43 | "showMapBorders": "Показати межі карти", 44 | "showNextFlagPercentage": "Показати ймовірності наступних прапорів", 45 | "respawnCam": "Показати позицію камери відродження", 46 | "factionsOptions": "Опції фракцій", 47 | "defaultFactions": "Автовибір фракцій за замовчуванням", 48 | "enableFactions": "Увімкнути фракції", 49 | "hideLowRespawn": "Відстежувати лише транспорт з тривалим часом респауна", 50 | "disableSounds": "Вимкнути звуки сповіщення про респаун", 51 | "shortcuts": "Ярлики", 52 | "enter": "Увійти в режим фокусу, приховуючи кнопки інтерфейсу", 53 | "deleteLastTarget": "Видалити останню розміщену ціль на карті", 54 | "changelog": "Зміни", 55 | "github": "Переглянути код на Github", 56 | "discord": "Офіційний Discord", 57 | "wiki": "Вікі" 58 | } -------------------------------------------------------------------------------- /public/locales/fr/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "squad": "SQUAD", 3 | "calc": "CALC", 4 | "squadcalc": "SquadCalc", 5 | "desc": "Un calculateur de mortier et layer pour SQUAD !", 6 | "weaponInf": "Informations sur l'arme", 7 | "name": "Nom", 8 | "range": "Portée", 9 | "velocity": "Vélocité", 10 | "moa": "MOA", 11 | "100radius": "RAYON DE DOMMAGE 100", 12 | "25radius": "RAYON DE DOMMAGE 25", 13 | "angle": "Angle", 14 | "high": "haut", 15 | "low": "bas", 16 | "addHeight": "HAUTEUR SUPPLÉMENTAIRE", 17 | "meters": "mètres", 18 | "m": "m", 19 | "s": "s", 20 | "°": "°", 21 | "targetInf": "Informations sur la cible", 22 | "weapon1": "Arme 1", 23 | "weapon2": "Arme 2", 24 | "bearing": "Direction", 25 | "elevation": "Élévation", 26 | "distance": "Distance", 27 | "timeOfFlight": "Temps de vol", 28 | "spread": "Dispersion", 29 | "weaponHeight": "Hauteur de l'arme", 30 | "targetHeight": "Hauteur de la cible", 31 | "heightDiff": "Différence de hauteur", 32 | "outOfRange": "La cible est hors de portée :", 33 | "invalidMortar": "Arme invalide", 34 | "invalidTarget": "Cible invalide", 35 | "invalidMortarTarget": "Arme & Cible invalides", 36 | "targetOutOfRange": "Cible hors de portée", 37 | "layerPlaceholder": "Layer", 38 | "nextFlags": "Prochains points", 39 | "dropTxt": "DEPOSER UN FICHIER DE SAUVEGARDE ICI", 40 | "dropSubTxt": "la carte actuelle sera effacée", 41 | "faction": "Faction", 42 | "unit": "Unité", 43 | "respawn": "Réapparition", 44 | "delayed": "Retardé", 45 | "team1": "Équipe 1", 46 | "team2": "Équipe 2", 47 | "pinToMap": "Épingler sur la carte", 48 | "pinned": "Épinglé", 49 | "randomSpawn": "Aléatoire", 50 | "dedicactedSpawn": "Fixe", 51 | "amphibious": "Amphibi", 52 | "atgm": "Missile antichar", 53 | "value": "Valeur", 54 | "ticket": "Ticket", 55 | "tickets": "Tickets", 56 | "passengers": "Places disponibles", 57 | "noCommander": "Pas d'équipements de commandant", 58 | "spawn": "Spawn", 59 | "temporary": "Spawn Temporaire", 60 | "disabledSpawn": "Désactivé jusqu'à la première capture", 61 | "respawnCamera": "Caméra de respawn", 62 | "rightClicToRemove": "(Clic droit pour enlever)", 63 | "loadingServers": "Récupération des serveurs...", 64 | "errorLoading": "Erreur lors du chargement des serveurs.", 65 | "searchServerPlaceholder": "Rechercher un serveur ou une carte...", 66 | "serverName": "Nom du serveur", 67 | "currentMap": "Carte", 68 | "players": "Joueurs", 69 | "noServersFound": "Aucun serveur trouvé.", 70 | "server": "serveur", 71 | "servers": "serveurs", 72 | "next": "à suivre", 73 | "playTime": "Temps de jeu", 74 | "mapSyncedwith": "Carte synchronisée avec" 75 | } 76 | -------------------------------------------------------------------------------- /public/locales/ru/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SettingsTitle": "Настройки", 3 | "map": "Карта", 4 | "mortars": "Минометы", 5 | "layer": "Layer", 6 | "mapOptions": "Опции карты", 7 | "showKeypad": "Номер сетки под курсором", 8 | "useClassicCursor": "Классический курсор", 9 | "mapAnimationSettings": "Анимации перемещения и масштабирования", 10 | "highquality": "HD карты", 11 | "contextMenu": "Пользовательские метки по правому клику", 12 | "gridOpacity": "Прозрачность сетки", 13 | "zoomSensitivity": "Чувствительность зума", 14 | "fontSize": "Размер шрифта", 15 | "brightness": "Яркость", 16 | "contrast": "Контраст", 17 | "weaponOptions": "Опции оружия", 18 | "weaponDrag": "Номер сетки", 19 | "realMaxRange": "Использовать реальную максимальную дальность", 20 | "moddedWeapons": "Включить модовое оружие", 21 | "targetOptions": "Опции целей", 22 | "targetDrag": "Номер сетки", 23 | "showSpread": "Радиус разброса", 24 | "showDamage": "Радиусы урона", 25 | "targetGrid": "Сетка отклонений", 26 | "lineToTarget": "Линия до цели", 27 | "showAnimations": "Использовать большие значки", 28 | "copyTarget": "Автокопирование целей", 29 | "lowAndHigh": "Показать и низкие, и высокие углы", 30 | "showBearing": "Показать пеленг (азимут)", 31 | "showDistance": "Показать расстояние", 32 | "showTimeOfFlight": "Показать время полёта", 33 | "showHeightDiff": "Показать разницу высот", 34 | "lastDigits": "Компактное отображение высоты", 35 | "LaneFinderOptions": "Опции поиска полос", 36 | "capZoneOnHover": "Зоны при наведении", 37 | "revealLayerOnHover": "Показать слой при наведении на флаг", 38 | "circlesFlags": "Показать флаги в виде кругов", 39 | "copyNextFlags": "Автокопирование следующих флагов", 40 | "showFlagsDistance": "Показать расстояние между флагами", 41 | "showMainZones": "Показать основные зоны", 42 | "showMainAssets": "Показать основные активы", 43 | "showMapBorders": "Показать границы карты", 44 | "showNextFlagPercentage": "Показать вероятности следующих флагов", 45 | "respawnCam": "Показать позицию камеры возрождения", 46 | "factionsOptions": "Опции фракций", 47 | "defaultFactions": "Автовыбор фракций по умолчанию", 48 | "enableFactions": "Включить фракции", 49 | "hideLowRespawn": "Отслеживать только транспорт с долгим временем респауна", 50 | "disableSounds": "Отключить звуки уведомлений о респауне", 51 | "shortcuts": "Ярлыки", 52 | "enter": "Войти в режим фокуса, скрыв кнопки интерфейса", 53 | "deleteLastTarget": "Удалить последнюю размещённую цель на карте", 54 | "changelog": "Журнал изменений", 55 | "github": "Просмотреть код на Github", 56 | "discord": "Официальный Discord", 57 | "wiki": "Вики" 58 | } -------------------------------------------------------------------------------- /public/locales/fr/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SettingsTitle": "Paramètres", 3 | "map": "Carte", 4 | "mortars": "Mortiers", 5 | "layer": "Voie", 6 | "mapOptions": "Options de Carte", 7 | "showKeypad": "Grille sous le curseur", 8 | "useClassicCursor": "Curseur classique", 9 | "mapAnimationSettings": "Animations de zoom", 10 | "highquality": "Carte haute qualité", 11 | "contextMenu": "Marqueurs personnalisés par clic droit", 12 | "gridOpacity": "Opacité de la grille", 13 | "zoomSensitivity": "Sensibilité du zoom", 14 | "fontSize": "Taille de police", 15 | "brightness": "Luminosité", 16 | "contrast": "Contraste", 17 | "weaponOptions": "Options des armes", 18 | "weaponDrag": "Grille pendant le déplacement", 19 | "realMaxRange": "Utiliser la portée maximale réelle", 20 | "moddedWeapons": "Activer les armes moddées", 21 | "targetOptions": "Options des cibles", 22 | "targetDrag": "Grille pendant le déplacement", 23 | "showSpread": "Rayon de dispersion", 24 | "showDamage": "Rayons de dégâts", 25 | "targetGrid": "Grille de déviation", 26 | "showAnimations": "Grandes icônes", 27 | "copyTarget": "Copier automatiquement les cibles", 28 | "lowAndHigh": "Afficher les angles bas et hauts", 29 | "showBearing": "Angle d'orientation", 30 | "showDistance": "Distance", 31 | "showTimeOfFlight": "Temps de vol", 32 | "showHeightDiff": "Différence d'altitude", 33 | "lineToTarget": "Ligne vers la cible", 34 | "lastDigits": "Affichage compact de l'élévation", 35 | "LaneFinderOptions": "Options de recherche de voie", 36 | "capZoneOnHover": "Montrer les zones de capture au survol", 37 | "revealLayerOnHover": "Révéler le layer au survol des drapeaux", 38 | "circlesFlags": "Drapeaux en forme de cercles", 39 | "copyNextFlags": "Copier les prochains drapeaux", 40 | "showFlagsDistance": "Afficher la distance entre les points", 41 | "showMainZones": "Zones de main", 42 | "showMainAssets": "Déployables de main", 43 | "showMapBorders": "Bordures de la carte", 44 | "showNextFlagPercentage": "Afficher les probabilités des prochains drapeaux", 45 | "respawnCam": "Afficher la position de la caméra de respawn", 46 | "factionsOptions": "Options des Factions", 47 | "defaultFactions": "Selection automatique des factions par défaut", 48 | "enableFactions": "Activer les factions", 49 | "hideLowRespawn": "Suivre uniquement les véhicules avec un long temps de respawn", 50 | "disableSounds": "Désactiver les sons de notification de respawn", 51 | "shortcuts": "Raccourcis", 52 | "enter": "Entrer en mode focus, masquant les boutons de l'interface utilisateur", 53 | "deleteLastTarget": "Supprimer la dernière cible placée sur la carte", 54 | "changelog": "Journal des modifications", 55 | "github": "Voir le code sur Github", 56 | "bug": "Signaler un bug", 57 | "discord": "Discord Officiel", 58 | "wiki": "Wiki" 59 | } -------------------------------------------------------------------------------- /public/locales/de/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "SettingsTitle": "Einstellungen", 3 | "map": "Karte", 4 | "mortars": "Mörser", 5 | "layer": "Layer", 6 | "mapOptions": "Kartenoptionen", 7 | "showKeypad": "Rasterfeld unter Cursor anzeigen", 8 | "useClassicCursor": "Klassischen Cursor verwenden", 9 | "mapAnimationSettings": "Schwenk-/Zoom-Animationen", 10 | "highquality": "Hochauflösende Karten", 11 | "contextMenu": "Benutzerdefinierte Markierungen per Rechtsklick", 12 | "gridOpacity": "Raster-Deckkraft", 13 | "zoomSensitivity": "Zoom-Empfindlichkeit", 14 | "fontSize": "Schriftgröße", 15 | "brightness": "Helligkeit", 16 | "contrast": "Kontrast", 17 | "weaponOptions": "Waffenoptionen", 18 | "weaponDrag": "Rasterfeld beim Ziehen anzeigen", 19 | "realMaxRange": "Reale maximale Reichweite verwenden", 20 | "moddedWeapons": "Modded-Waffen aktivieren", 21 | "targetOptions": "Zieloptionen", 22 | "targetDrag": "Rasterfeld beim Ziehen anzeigen", 23 | "showSpread": "Streuung anzeigen", 24 | "showDamage": "Schadensradien anzeigen", 25 | "targetGrid": "Abweichungsraster", 26 | "showAnimations": "Große Symbole verwenden", 27 | "copyTarget": "Ziel automatisch in Zwischenablage kopieren", 28 | "lowAndHigh": "Sowohl flache als auch steile Winkel anzeigen", 29 | "showBearing": "Peilung", 30 | "showDistance": "Entfernung", 31 | "showTimeOfFlight": "Flugzeit", 32 | "showHeightDiff": "Höhenunterschied", 33 | "lineToTarget": "Linie zum Ziel", 34 | "lastDigits": "Kompakte Höhenanzeige", 35 | "LaneFinderOptions": "Routen-Finder-Optionen", 36 | "capZoneOnHover": "Eroberungszonen nur beim Überfahren anzeigen", 37 | "revealLayerOnHover" : "Layer anzeigen, wenn der Mauszeiger über einer Flagge steht", 38 | "circlesFlags": "Flaggen als Kreise anzeigen", 39 | "copyNextFlags": "Nächste Flaggen automatisch in Zwischenablage kopieren", 40 | "showFlagsDistance": "Entfernung zwischen Flaggen anzeigen", 41 | "showMainZones": "Hauptzonen anzeigen", 42 | "showMainAssets": "Hauptressourcen anzeigen", 43 | "showMapBorders": "Kartenrand der Ebene anzeigen", 44 | "showNextFlagPercentage": "Wahrscheinlichkeiten der nächsten Flaggen anzeigen", 45 | "respawnCam": "Position der Respawn-Kamera anzeigen", 46 | "factionsOptions": "Fraktionen-Optionen", 47 | "defaultFactions": "Standardfraktionen der Ebene automatisch auswählen", 48 | "enableFactions": "Fraktionen aktivieren", 49 | "hideLowRespawn": "Nur Fahrzeuge mit hoher Respawn-Zeit verfolgen", 50 | "disableSounds": "Respawn-Benachrichtigungstöne deaktivieren", 51 | "shortcuts": "Tastenkürzel", 52 | "enter": "Fokusmodus aktivieren, UI-Schaltflächen ausblenden", 53 | "deleteLastTarget": "Zuletzt platziertes Ziel auf der Karte löschen", 54 | "discord": "Offizieller Discord", 55 | "github": "Code auf Github ansehen", 56 | "changelog": "Änderungsprotokoll", 57 | "wiki": "SquadCalc Wiki" 58 | } -------------------------------------------------------------------------------- /src/js/squadHeightmaps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Squad Heightmap 3 | * Load an heightmap in memory and calculate heights for given LatLng Points 4 | * @class squadHeightmap 5 | */ 6 | export default class SquadHeightmap { 7 | 8 | /** 9 | * Load the heightmap for the given map 10 | * @param {L.map} [map] 11 | */ 12 | constructor(map) { 13 | this.map = map; 14 | this.width = 500; 15 | this.heightmapScaling = this.width / this.map.pixelSize; 16 | let heightmapPath = `${this.map.activeMap.mapURL}heightmap.json`; 17 | this.json = []; 18 | this.loadHeightmapJson(heightmapPath); 19 | } 20 | 21 | 22 | /** 23 | * Load the heightmap from a JSON file 24 | * @param {string} [url] - URL to the JSON file 25 | */ 26 | async loadHeightmapJson(url) { 27 | 28 | // If no heightmap is provided, don't look for a .json file 29 | if (!this.map.activeMap.SDK_data.heightmap) return; 30 | 31 | try { 32 | const response = await fetch(url); // Fetch the JSON file 33 | let data = await response.json(); 34 | this.json = data; 35 | } catch (error) { 36 | console.error("Failed to load heightmap:", url); 37 | console.error(" -> ", error); 38 | } 39 | 40 | $(document).trigger("heightmap:loaded"); 41 | } 42 | 43 | 44 | /** 45 | * Calculate heights for a given LatLng Point 46 | * https://github.com/sh4rkman/SquadCalc/wiki/Deducing-Altitude 47 | * @param {LatLng} [latlng] - LatLng Point 48 | * @returns {integer} - height in meters 49 | */ 50 | getHeight(latlng){ 51 | 52 | // Fallback in case heightmap isn't supplied or didn't load 53 | if (!this.json || !Array.isArray(this.json)) return 0; 54 | 55 | const row = Math.round(latlng.lat * -this.heightmapScaling); 56 | const col = Math.round(latlng.lng * this.heightmapScaling); 57 | let height = 0; // Todo: Implement a better way to handle this, like returning infinity 58 | 59 | if (this.json[row] && typeof this.json[row][col] !== "undefined") { 60 | height = this.json[row][col]; 61 | } 62 | 63 | return height; 64 | } 65 | 66 | 67 | /** 68 | * Calculate a path of heights between two points 69 | * @param {LatLng} [mortarLatlng] - LatLng Point 70 | * @param {LatLng} [targetLatlng] - LatLng Point 71 | * @returns {Array} - Array containing all the Heights between weapon and Target in meters 72 | */ 73 | getHeightPath(mortarLatlng, targetLatlng, STEP = 100) { 74 | const END = {lat: targetLatlng.lat, lng: targetLatlng.lng}; 75 | const START = {lat: mortarLatlng.lat, lng: mortarLatlng.lng}; 76 | const heightPath = []; 77 | const latDiff = END.lat - START.lat; 78 | const lngDiff = END.lng - START.lng; 79 | 80 | for (let i=0; i < STEP; i++){ 81 | heightPath.push(this.getHeight(START)); 82 | START.lat += latDiff/STEP; 83 | START.lng += lngDiff/STEP; 84 | } 85 | 86 | return heightPath; 87 | } 88 | 89 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SquadCalc 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | <%= require('html-loader!./components/header/header.html').default %> 51 | 52 | 53 | <%= require('html-loader!./components/legacyui/legacyui.html').default %> 54 | <%= require('html-loader!./components/map/map.html').default %> 55 | 56 | 57 | <%= require('html-loader!./components/dialogs/weapon.html').default %> 58 | <%= require('html-loader!./components/dialogs/target.html').default %> 59 | <%= require('html-loader!./components/dialogs/settings.html').default %> 60 | <%= require('html-loader!./components/dialogs/factions.html').default %> 61 | <%= require('html-loader!./components/dialogs/servers.html').default %> 62 | 63 | 64 | <%= require('html-loader!./components/contextMenu/contextMenu.html').default %> 65 | 66 | 67 | <%= require('html-loader!./components/footer/footer.html').default %> 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/components/dialogs/weapon.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 |
7 | 8 |

Weapon Informations

9 | 10 | weapon icon 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 |
41 | 42 |
43 | 44 | 45 | 46 | 47 | 59 | 60 | 61 |
Angle : 48 |
49 | 53 | 57 |
58 |
62 | 63 | 64 | 65 | 66 | 67 | 72 | 73 | 74 |
68 |
69 | 70 |
71 |
75 |
76 | 77 |
-------------------------------------------------------------------------------- /public/locales/zh/tooltips.json: -------------------------------------------------------------------------------- 1 | { 2 | "basemode": "基础地图", 3 | "terrainmode": "地势图", 4 | "topographicmode": "地形图", 5 | "helpmode": "显示大家都在用的武器位置", 6 | "focusMode": "专注模式", 7 | "enterToExit": "按 'Enter' 退出", 8 | "squadMortarOverlay": "检测到SquadMortarOverlay服务", 9 | "mapUpdated": "地图已更新", 10 | "connectedTo": "已连接!", 11 | "error": "错误!", 12 | "apiError": "API 未连接..", 13 | "apiError_layers": "无法从API获取地图图层!", 14 | "deleteTargets": "删除所有目标", 15 | "bearing": "角度", 16 | "whereToAim": "瞄哪里", 17 | "elevation": "密位", 18 | "howFar": "打多远", 19 | "save": "保存", 20 | "copied": "已复制到剪贴板 📋", 21 | "resultLater": "等待结果...", 22 | "spreadDesc": "由于武器的角分 (MOA) 不精确性和弹道长度,射击会在椭圆形的模式下散布。", 23 | "moaDesc": "角分 (MOA) 在炮兵中衡量武器的不精确性,表示射击的散布范围。一角分等于1/60度。", 24 | "velocityDesc": "枪口初速是指弹丸离开枪管时的即时速度,它影响射程和精准度。", 25 | "heightPaddingDesc": "当武器不是放置在海拔地面时(例如在建筑物或桥梁上),需在此输入补充高度。", 26 | "smoothMapTooltip": "在缩放或移动地图时添加平滑动画。需要重新加载页面", 27 | "moddedWeaponTooltip": "为热门模组添加武器支持(Steel Division、Global Escalation、Squad AdminTools 等)", 28 | "damageRadiusTooltip": "显示致死半径和25伤害半径", 29 | "showKeypadTooltip": "在光标下显示数字键盘", 30 | "showSpreadTooltip": "显示目标周围可能的弹着点区域", 31 | "showMaxRangeTooltip": "计算每个方向的最大范围,同时考虑高度", 32 | "useClassicCursorTooltip": "使用系统的鼠标样式", 33 | "targetAnimationTooltip": "禁用以将标记图标替换为简约的圆形", 34 | "lastDigitsTooltip": "仅显示海拔值的后三位数字(例如 193 而不是 1193)", 35 | "performanceWarning": "可能会导致性能问题", 36 | "markerDragTooltip": "拖动时显示网格坐标", 37 | "copyNextFlagsTooltip": "在点击目标点后,自动复制所有可能的下一个点的名称到剪贴板", 38 | "copyTargetTooltip": "放置/拖动目标后,自动将计算结果复制到剪贴板", 39 | "lowAndHighTooltip": "显示可以以高角度和低角度射击的武器的两种角度", 40 | "capZoneOnHoverTooltip": "(放大时)不始终显示可以拉点的区域,仅在鼠标悬停在点上时显示", 41 | "revealLayerOnHoverTooltip": "鼠标悬停在点上将隐藏互斥的其他点", 42 | "sessionCreated": "会话已创建!", 43 | "sessionClosed": "会话已关闭", 44 | "sessionJoined": "会话已加入!", 45 | "shareSession": "单击此处将链接复制到剪贴板", 46 | "someoneLeft": "有人离开了 🏃🏼‍➡️", 47 | "someoneJoined": "🏃🏼‍➡️ 有人加入了!", 48 | "youAreAlone": "此会话中只有您一人", 49 | "hostOnly": "只有会话主机才能更改地图", 50 | "createSession": "创建共享会话", 51 | "leaveSession": "离开会话", 52 | "outdatedVersion": "版本过时", 53 | "pleaseupdate": "请刷新您的页面", 54 | "sessionFull": "会话已满!", 55 | "invalidSession": "无效的 SessionID", 56 | "invalidSessionRules": "SessionID 必须由 6 到 20 个字符组成", 57 | "undo": "撤销操作", 58 | "backspace": "Backspace", 59 | "enter": "Enter", 60 | "delete": "Delete", 61 | "toggleLayer": "显示/隐藏图层", 62 | "fileNotSupported": "不支持的文件", 63 | "openIssue": "如果你认为这是一个漏洞,请在 Github 或 Discord 上报告问题", 64 | "mapSaved": "地图已保存到文件", 65 | "dragToImport": "你可以将此文件拖放到地图上以稍后加载", 66 | "importSuccess": "地图导入成功", 67 | "download": "将地图保存到文件", 68 | "factions&Vehicles": "阵营与载具", 69 | "enableFactionsTooltip": "选择图层后,启用阵营和载具功能", 70 | "defaultFactionsTooltip": "选择图层后,预设默认阵营", 71 | "hideLowRespawnTooltip": "在地图上固定阵营时,仅显示重生时间为10分钟或更长的载具", 72 | "vehicleTimerTooltip": "点击载具将其标记为已摧毁并设置重生计时器", 73 | "showMainAssetsTooltip": "在地图上显示维修站、弹药箱和其他主要资源", 74 | "showMainZonesTooltip": "显示每个主基地的保护区和禁止部署区域", 75 | "clickToCopy": "点击复制 `CreateSquad` 命令", 76 | "vehicleRespawned": "载具已重生", 77 | "lineToTargetTooltip": "在武器和目标之间绘制一条线", 78 | "targetGridTooltip": "在目标周围显示网格:垂直线显示角度偏差(2°),水平弧线显示仰角偏差(10密位或1°,取决于武器的单位系统)", 79 | "serverBrowser": "Squad 服务器浏览器" 80 | } -------------------------------------------------------------------------------- /src/js/squadIcon.js: -------------------------------------------------------------------------------- 1 | import { Icon } from "leaflet"; 2 | 3 | export const mortarIcon = new Icon({ 4 | iconUrl: "../img/markers/weapons/marker_mortar.webp", 5 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 6 | iconSize: [38, 47], 7 | shadowSize: [38, 47], 8 | iconAnchor: [19, 47], 9 | shadowAnchor: [10, 47], 10 | className: "animatedWeaponMarker" 11 | }); 12 | 13 | 14 | export const mortarIcon1 = new Icon({ 15 | iconUrl: "../img/markers/weapons/marker_mortar_1.webp", 16 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 17 | iconSize: [38, 47], 18 | shadowSize: [38, 47], 19 | iconAnchor: [19, 47], 20 | shadowAnchor: [10, 47], 21 | className: "animatedWeaponMarker" 22 | }); 23 | 24 | export const mortarIcon2 = new Icon({ 25 | iconUrl: "../img/markers/weapons/marker_mortar_2.webp", 26 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 27 | iconSize: [38, 47], 28 | shadowSize: [38, 47], 29 | iconAnchor: [19, 47], 30 | shadowAnchor: [10, 47], 31 | className: "animatedWeaponMarker" 32 | }); 33 | 34 | export const targetIconMinimal = new Icon({ 35 | iconUrl: "../img/markers/targets/marker_target_mini.webp", 36 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 37 | shadowSize: [0, 0], // hack to avoid 404 38 | iconSize: [30, 30], 39 | iconAnchor: [15, 15], 40 | }); 41 | 42 | export const targetIconSessionMinimal = new Icon({ 43 | iconUrl: "../img/markers/targets/marker_target_session_mini.webp", 44 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 45 | shadowSize: [0, 0], // hack to avoid 404 46 | iconSize: [30, 30], 47 | iconAnchor: [15, 15], 48 | }); 49 | 50 | export const targetIconMinimalDisabled = new Icon({ 51 | iconUrl: "../img/markers/targets/marker_target_disabled_mini.webp", 52 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 53 | shadowSize: [0, 0], // hack to avoid 404 54 | iconSize: [30, 30], 55 | iconAnchor: [15, 15], 56 | }); 57 | 58 | export const targetIcon1 = new Icon({ 59 | iconUrl: "../img/markers/targets/marker_target_enabled.webp", 60 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 61 | iconSize: [28, 34], 62 | shadowSize: [38, 34], 63 | iconAnchor: [14, 34], 64 | shadowAnchor: [12, 34], 65 | }); 66 | 67 | export const targetSessionIcon1 = new Icon({ 68 | iconUrl: "../img/markers/targets/marker_target_session_enabled.webp", 69 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 70 | iconSize: [28, 34], 71 | shadowSize: [38, 34], 72 | iconAnchor: [14, 34], 73 | shadowAnchor: [12, 34], 74 | }); 75 | 76 | export const targetIconDisabled = new Icon({ 77 | iconUrl: "../img/markers/targets/marker_target_disabled.webp", 78 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 79 | iconSize: [28, 34], 80 | shadowSize: [38, 34], 81 | iconAnchor: [14, 34], 82 | shadowAnchor: [12, 34], 83 | }); 84 | 85 | export const targetIconDisabledAnimated = new Icon({ 86 | iconUrl: "../img/markers/targets/marker_target_disabled.webp", 87 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 88 | iconSize: [28, 34], 89 | shadowSize: [38, 34], 90 | iconAnchor: [14, 34], 91 | shadowAnchor: [12, 34], 92 | }); 93 | 94 | export const targetIconAnimated = new Icon({ 95 | iconUrl: "../img/markers/targets/marker_target_enabled.webp", 96 | shadowUrl: "/img/markers/weapons/marker_shadow.webp", 97 | iconSize: [28, 34], 98 | shadowSize: [38, 34], 99 | iconAnchor: [14, 34], 100 | shadowAnchor: [12, 34], 101 | className: "animatedTargetMarker" 102 | }); -------------------------------------------------------------------------------- /src/components/legacyui/legacyui.scss: -------------------------------------------------------------------------------- 1 | @use "../shared/variables"; 2 | 3 | #classic_ui { 4 | height: 40vh; 5 | #settings { 6 | border-radius: 5px; 7 | border: 5px solid variables.$mainTxtColor; 8 | font-size: 1.5em; 9 | font-weight: bold; 10 | margin: 0.7em auto; 11 | padding: 1em; 12 | position: relative; 13 | i { 14 | font-size: 50%; 15 | margin: -10px; // ugly hack 16 | } 17 | svg { 18 | fill: white; 19 | height: 0.7em; 20 | width: 0.7em; 21 | 22 | } 23 | #bearing svg { 24 | transform: rotate(-45deg); 25 | padding-bottom: 5px; 26 | } 27 | #highlow { 28 | background-color: transparent; 29 | padding: 0 5px; 30 | &.active { 31 | cursor: pointer; 32 | &:active { 33 | transform: scale(0.7); 34 | } 35 | &:hover { 36 | svg { 37 | fill: variables.$mainColor; 38 | } 39 | } 40 | } 41 | path { 42 | pointer-events: none; 43 | } 44 | 45 | } 46 | #savebutton { 47 | background-color: transparent; 48 | border: none; 49 | bottom: 0; 50 | color: variables.$mainTxtColor; 51 | padding: 0 5px; 52 | position: absolute; 53 | right: 0; 54 | transition: all 0.1s ease-out; 55 | svg { 56 | cursor:pointer; 57 | font-size: 0.8em; 58 | position: relative; 59 | margin: 0; 60 | transition: all 0.3s ease-out; 61 | &:hover { 62 | fill: variables.$mainColor; 63 | } 64 | } 65 | &:active { 66 | transform: scale(0.7); 67 | } 68 | &:focus { 69 | outline: none; 70 | } 71 | } 72 | } 73 | .saved_list svg { 74 | fill: variables.$mainTxtColor; 75 | height: 1em; 76 | width: 1em; 77 | &:hover { 78 | fill: variables.$mainColor; 79 | cursor: pointer; 80 | transform: scale(1.1); 81 | } 82 | } 83 | .copy { 84 | &:hover { 85 | cursor: pointer; 86 | } 87 | } 88 | .coord { 89 | padding: 0.625em 0; 90 | img { 91 | height: 30px; 92 | } 93 | } 94 | .pure-g [class*="pure-u"] .errorMsg { 95 | cursor: default; 96 | font-size: 0.7em; 97 | line-height: 2em; 98 | color: variables.$mainColor; 99 | } 100 | .error2 { 101 | border-bottom: 3px solid variables.$mainColor; 102 | } 103 | #saved { 104 | font-size: 0.6em; 105 | .friendlyname { 106 | border-style: none; 107 | font-size: 1em; 108 | height: auto; 109 | min-width: 20px; 110 | text-align: right; 111 | text-transform: none; 112 | width: 100px; 113 | } 114 | .savespan { 115 | font-weight: bold; 116 | &:hover { 117 | cursor: pointer; 118 | } 119 | } 120 | #ruler { 121 | white-space: nowrap; 122 | visibility: hidden; 123 | font-size: 1em; 124 | font-weight: bold; 125 | } 126 | } 127 | } 128 | 129 | .leader-line { 130 | z-index: -1; 131 | } 132 | 133 | .tooltipsubtext { 134 | font-size: 0.6em; 135 | letter-spacing: 0.05rem; 136 | font-weight: normal; 137 | } -------------------------------------------------------------------------------- /src/components/shared/_tooltips.scss: -------------------------------------------------------------------------------- 1 | @use './variables'; 2 | 3 | /************************************** 4 | * Tippy.js ToolTips customization 5 | ***************************************/ 6 | 7 | .tippy-box { 8 | &[data-theme~='mapFactionMenu'] { 9 | background: rgba(30, 30, 30, 0.7); 10 | backdrop-filter: blur(6px); 11 | box-shadow: 0 4px 12px rgba(0,0,0,0.25); 12 | border-radius: 8px; 13 | padding: 8px; 14 | &[data-placement^='top']>.tippy-arrow::before { 15 | display: none; 16 | } 17 | &[data-placement^='bottom']>.tippy-arrow::before { 18 | display: none; 19 | } 20 | } 21 | &[data-theme~='spawnCards'] { 22 | background: rgba(30, 30, 30, 0.45); 23 | backdrop-filter: blur(6px); 24 | border-radius: 8px; 25 | box-shadow: 0 4px 12px rgba(0,0,0,0.25); 26 | .tippy-content { 27 | padding: 0; 28 | 29 | } 30 | &[data-placement^='top']>.tippy-arrow::before { 31 | display: none; 32 | } 33 | &[data-placement^='bottom']>.tippy-arrow::before { 34 | display: none; 35 | } 36 | } 37 | &[data-theme~='new'] { 38 | background-color: variables.$newColor; 39 | color: variables.$mainTxtColor; 40 | font-weight: bold; 41 | letter-spacing: 0.1rem; 42 | &[data-placement^='top']>.tippy-arrow::before { 43 | border-top-color: variables.$newColor; 44 | } 45 | &[data-placement^='bottom']>.tippy-arrow::before { 46 | border-bottom-color: variables.$newColor; 47 | } 48 | &[data-placement^='left']>.tippy-arrow::before { 49 | border-left-color: variables.$newColor; 50 | } 51 | &[data-placement^='right']>.tippy-arrow::before { 52 | border-right-color: variables.$newColor; 53 | } 54 | } 55 | &[data-theme~="results"] .tippy-content { 56 | font-size: 1.4em; 57 | padding: 0.5em; 58 | line-height: 0.9em; 59 | font-weight: bold; 60 | } 61 | &[data-theme~='menu'] { 62 | background-color: variables.$mainTxtColor; 63 | color: variables.$mainBGColor; 64 | font-size: 13px; 65 | font-weight: 600; 66 | letter-spacing: .05em; 67 | line-height: 1.2em; 68 | padding: 10px 14px; 69 | border-radius: 5px; 70 | box-shadow: 0 2px 15px rgba(0,0,0,0.1); 71 | &[data-placement^='top']>.tippy-arrow::before { 72 | border-top-color: variables.$mainTxtColor; 73 | } 74 | &[data-placement^='bottom']>.tippy-arrow::before { 75 | border-bottom-color: variables.$mainTxtColor; 76 | } 77 | &[data-placement^='left']>.tippy-arrow::before { 78 | border-left-color: variables.$mainTxtColor; 79 | } 80 | &[data-placement^='right']>.tippy-arrow::before { 81 | border-right-color: variables.$mainTxtColor; 82 | } 83 | .tooltipsubtext { 84 | padding: 0; 85 | margin: 0; 86 | font-size: 0.85em; 87 | color: rgb(90, 90, 90); 88 | } 89 | &:has(.tooltipsubtext) { 90 | padding: 6px 12px 0; 91 | } 92 | } 93 | &[data-theme='infTooltips'] { 94 | font-size: 1em; 95 | text-align: center; 96 | box-shadow: 0 4px 12px rgba(0,0,0,0.4); 97 | border-radius: 8px; 98 | padding: 8px; 99 | } 100 | &[data-theme~='settingsTooltips'] { 101 | margin-top: 2px; 102 | font-size: 0.9em; 103 | text-align: center; 104 | padding: 5px; 105 | box-shadow: 0 2px 15px rgba(0,0,0,0.1); 106 | } 107 | } 108 | 109 | .tippy-arrow { 110 | transform: scale(1.5); 111 | } -------------------------------------------------------------------------------- /src/components/dialogs/target.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 6 |
7 | 8 |

Target Informations

9 | 10 |
11 | 12 | 13 |
14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | 50 |
51 | 52 |
53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
86 | 87 |
88 | 89 |
-------------------------------------------------------------------------------- /src/js/squadCameraActor.js: -------------------------------------------------------------------------------- 1 | import { Marker, Icon, Browser, DomEvent } from "leaflet"; 2 | import tippy from "tippy.js"; 3 | import i18next from "i18next"; 4 | import "./libs/leaflet-rotatedMarker.js"; 5 | 6 | 7 | export const squadCameraActor = Marker.extend({ 8 | 9 | options: { 10 | draggable: false, 11 | riseOnHover: false, 12 | keyboard: false, 13 | animate: true, 14 | zIndexOffset: -900 15 | }, 16 | 17 | // Constructor 18 | initialize: function (latlng, camera, layer, options) { 19 | 20 | Marker.prototype.initialize.call(this, latlng, options); 21 | 22 | this.data = camera; 23 | this.layer = layer; 24 | this.tippy = ""; 25 | 26 | this.setIcon( 27 | new Icon({ 28 | iconUrl: `${process.env.API_URL}/img/icons/shared/camera.webp`, 29 | iconSize: [30, 30], 30 | iconAnchor: [15, 15], 31 | className: "vehSpawnIcon" 32 | }) 33 | ); 34 | 35 | this.setRotationAngle(camera.rotation_z); 36 | 37 | if (!Browser.mobile) { 38 | this.on("pointerover", this._handleOver, this); 39 | this.on("pointerout", this._handleOut, this); 40 | } else { 41 | this.on("click", this._handleOver, this); 42 | } 43 | 44 | // Catch this events and disable propagation 45 | this.on("contextmenu", this._handleContextMenu, this); 46 | this.on("dblclick", this._handleUnwantedActions, this); 47 | 48 | }, 49 | 50 | 51 | open(event) { 52 | 53 | const el = event.target._icon; 54 | 55 | if (el._tippy) el._tippy.destroy(); 56 | 57 | this.tippy = tippy(el, { 58 | delay: 200, 59 | placement: "top", 60 | sticky: true, 61 | duration: 0, 62 | allowHTML: true, 63 | interactive: true, 64 | theme: "spawnCards", 65 | appendTo: document.body, 66 | onHidden: (tip) => this._cleanup(tip), 67 | onShow: (tip) => this._onShow(tip), 68 | }); 69 | 70 | 71 | // On mobile manually trigger without delay 72 | if (Browser.mobile) el._tippy.show(); 73 | 74 | }, 75 | 76 | hide() { 77 | this.removeFrom(this.layer.activeLayerMarkers); 78 | }, 79 | 80 | show() { 81 | this.addTo(this.layer.activeLayerMarkers); 82 | }, 83 | 84 | _onShow(tip) { 85 | this.tip = tip; 86 | 87 | // Disable System context menu on the tippy 88 | tip.popper.addEventListener("contextmenu", e => e.preventDefault()); 89 | 90 | let html = ` 91 |
92 |
${i18next.t("common:respawnCamera")}
93 |
94 |
95 | ${i18next.t("common:rightClicToRemove")} 96 |
97 |
98 | 99 |
100 | `; 101 | 102 | this.tip.setContent(html); 103 | }, 104 | 105 | 106 | 107 | _cleanup(tip) { 108 | if (tip._cleanup) tip._cleanup(); 109 | tip.destroy(); 110 | }, 111 | 112 | 113 | _handleOver: function(event){ 114 | this.open(event); 115 | }, 116 | 117 | 118 | _handleOut(event) { 119 | const el = event.target._icon; 120 | if (el._tippy) el._tippy.hide(); 121 | }, 122 | 123 | _handleContextMenu(event) { 124 | DomEvent.preventDefault(event); 125 | 126 | // clean up tooltip if needed 127 | if (this.tippy && this.tippy.destroy) { 128 | this.tippy.destroy(); 129 | } 130 | 131 | // remove marker from map 132 | this.remove(); 133 | this.layer.cameraActor = null; 134 | }, 135 | 136 | 137 | _handleUnwantedActions(event) { 138 | DomEvent.preventDefault(event); 139 | DomEvent.stopPropagation(event); 140 | return false; 141 | } 142 | 143 | }); -------------------------------------------------------------------------------- /src/js/libs/leaflet-smoothWheelZoom.js: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2018 mutsuyuki 4 | * https://github.com/mutsuyuki/Leaflet.SmoothWheelZoom 5 | * patched by sharkman for squadcalc (https://github.com/sh4rkman/SquadCalc) 6 | */ 7 | 8 | import { Map, Handler, DomEvent } from "leaflet"; 9 | 10 | Map.mergeOptions({ 11 | // @section Mousewheel options 12 | // @option smoothWheelZoom: Boolean|String = true 13 | // Whether the map can be zoomed by using the mouse wheel. If passed `'center'`, 14 | // it will zoom to the center of the view regardless of where the mouse was. 15 | smoothWheelZoom: true, 16 | 17 | // @option smoothWheelZoom: number = 1 18 | // setting zoom speed 19 | smoothSensitivity:1 20 | }); 21 | 22 | 23 | Map.SmoothWheelZoom = Handler.extend({ 24 | 25 | addHooks: function () { 26 | DomEvent.on(this._map._container, "wheel", this._onWheelScroll, this); 27 | }, 28 | 29 | removeHooks: function () { 30 | DomEvent.off(this._map._container, "wheel", this._onWheelScroll, this); 31 | }, 32 | 33 | _onWheelScroll: function (e) { 34 | if (!this._isWheeling) { 35 | this._onWheelStart(e); 36 | } 37 | this._onWheeling(e); 38 | }, 39 | 40 | _onWheelStart: function (e) { 41 | var map = this._map; 42 | this._isWheeling = true; 43 | this._wheelMousePosition = map.pointerEventToContainerPoint(e); 44 | this._centerPoint = map.getSize()._divideBy(2); 45 | this._startLatLng = map.containerPointToLatLng(this._centerPoint); 46 | //this._wheelStartLatLng = map.containerPointToLatLng(this._wheelMousePosition); 47 | this._wheelMouseLatLng = map.containerPointToLatLng(this._wheelMousePosition); // patch 48 | this._startZoom = map.getZoom(); 49 | this._moved = false; 50 | this._zooming = true; 51 | 52 | map._stop(); 53 | if (map._panAnim) map._panAnim.stop(); 54 | 55 | this._goalZoom = map.getZoom(); 56 | this._prevCenter = map.getCenter(); 57 | this._prevZoom = map.getZoom(); 58 | 59 | this._zoomAnimationId = requestAnimationFrame(this._updateWheelZoom.bind(this)); 60 | }, 61 | 62 | _onWheeling: function (e) { 63 | var map = this._map; 64 | 65 | this._goalZoom = this._goalZoom + DomEvent.getWheelDelta(e) * 0.003 * map.options.smoothSensitivity; 66 | if (this._goalZoom < map.getMinZoom() || this._goalZoom > map.getMaxZoom()) { 67 | this._goalZoom = map._limitZoom(this._goalZoom); 68 | } 69 | this._wheelMousePosition = this._map.pointerEventToContainerPoint(e); 70 | this._wheelMouseLatLng = map.containerPointToLatLng(this._wheelMousePosition); // patch 71 | 72 | clearTimeout(this._timeoutId); 73 | this._timeoutId = setTimeout(this._onWheelEnd.bind(this), 200); 74 | 75 | DomEvent.preventDefault(e); 76 | DomEvent.stopPropagation(e); 77 | }, 78 | 79 | _onWheelEnd: function () { 80 | this._isWheeling = false; 81 | cancelAnimationFrame(this._zoomAnimationId); 82 | this._map._moveEnd(true); 83 | }, 84 | 85 | _updateWheelZoom: function () { 86 | var map = this._map; 87 | var delta = this._wheelMousePosition.subtract(this._centerPoint); 88 | 89 | if ((!map.getCenter().equals(this._prevCenter)) || map.getZoom() != this._prevZoom) 90 | return; 91 | 92 | this._zoom = map.getZoom() + (this._goalZoom - map.getZoom()) * 0.3; 93 | this._zoom = Math.floor(this._zoom * 100) / 100; 94 | 95 | 96 | if (delta.x === 0 && delta.y === 0) 97 | return; 98 | 99 | if (map.options.smoothWheelZoom === "center") { 100 | this._center = this._startLatLng; 101 | } else { 102 | //this._center = map.unproject(map.project(this._wheelStartLatLng, this._zoom).subtract(delta), this._zoom); 103 | this._center = map.unproject(map.project(this._wheelMouseLatLng, this._zoom).subtract(delta), this._zoom); //Patch 104 | } 105 | 106 | if (!this._moved) { 107 | map._moveStart(true, false); 108 | this._moved = true; 109 | } 110 | 111 | map._move(this._center, this._zoom); 112 | this._prevCenter = map.getCenter(); 113 | this._prevZoom = map.getZoom(); 114 | 115 | this._zoomAnimationId = requestAnimationFrame(this._updateWheelZoom.bind(this)); 116 | } 117 | 118 | }); 119 | 120 | Map.addInitHook("addHandler", "smoothWheelZoom", Map.SmoothWheelZoom ); -------------------------------------------------------------------------------- /src/components/header/header.scss: -------------------------------------------------------------------------------- 1 | @use "../shared/variables"; 2 | 3 | /*************************************** 4 | ************ HEADER *************** 5 | **************************************/ 6 | 7 | /**************** 8 | * Weapon Selector 9 | *****************/ 10 | 11 | header { 12 | position: relative; 13 | width: 100%; 14 | z-index: 2; 15 | top: 0; 16 | pointer-events: none; 17 | &.ui { 18 | position: fixed; 19 | } 20 | .weaponSelector { 21 | z-index: 4; 22 | padding-top: 1em; 23 | pointer-events: none; 24 | .select2-results__options { 25 | font-weight: 600; 26 | line-height: 1.1em; 27 | font-size: 0.9em; 28 | } 29 | #weaponSelector { 30 | .select2-results__options { 31 | max-height: 350px; 32 | } 33 | } 34 | .select2-results__group { 35 | color: rgba(255, 255, 255, .7); 36 | padding-top: 10px; 37 | font-weight: 900; 38 | text-align: left; 39 | padding-left: 15px; 40 | font-size: 1.1em; 41 | } 42 | #ammoSelector { 43 | padding-top: 1em; 44 | } 45 | } 46 | .mapSelector { 47 | padding-top: 1em; 48 | z-index: 5; 49 | pointer-events: none; 50 | position: relative; 51 | .select2-container--disabled { 52 | background-color: transparent; 53 | .select2-selection__rendered { 54 | background-color: transparent; 55 | } 56 | } 57 | #mapSelector { 58 | z-index: 3; 59 | position: relative; 60 | .select2-results__options { 61 | line-height: 0.7em; 62 | font-size: 0.9em; 63 | max-height: 400px; 64 | } 65 | } 66 | #layerSelector { 67 | z-index: 2; 68 | padding-top: 1em; 69 | position: relative; 70 | .select2-results__options { 71 | line-height: 0.7em; 72 | font-size: 0.9em; 73 | max-height: 400px; 74 | } 75 | } 76 | } 77 | .selectbox { 78 | padding: 0; 79 | } 80 | .dropbtn, 81 | .dropbtn2, 82 | .dropbtn3, 83 | .dropbtn5 { 84 | color: #fff; 85 | font-weight: bold; 86 | line-height: 2.188em; 87 | text-transform: uppercase; 88 | background-color: var(--themecolor, variables.$mainBGColor); 89 | select { 90 | -moz-appearance: none; 91 | -webkit-appearance: none; 92 | appearance: none; 93 | background-color: transparent; 94 | background-image: none; 95 | border: none; 96 | box-shadow: none; 97 | } 98 | &:focus { 99 | outline: none; 100 | } 101 | } 102 | .select2 { 103 | background-color: transparent; 104 | } 105 | .select2-container { 106 | @include variables.text-outline; 107 | font-size: 0.8em; 108 | pointer-events: all; 109 | background-color: transparent; 110 | border-bottom: 1px solid variables.$mainTxtColor; 111 | // line-height: 2.188em; 112 | min-width: 200px; 113 | padding-bottom: 0; 114 | text-transform: uppercase; 115 | } 116 | .select2-container--default { 117 | .select2-results__option--highlighted[aria-selected] { 118 | background-color: variables.$mainColor; 119 | } 120 | .select2-results__option--selected { 121 | background-color: variables.$mainColor; 122 | opacity: 0.5; 123 | } 124 | .select2-selection--single .select2-selection__rendered { 125 | color: #fff; 126 | } 127 | .select2-selection--single { 128 | background-color: transparent; 129 | border: none; 130 | color: variables.$mainTxtColor; 131 | } 132 | } 133 | span.select2-selection.select2-selection--single { 134 | outline: none; 135 | } 136 | } 137 | 138 | .select2-container--default.select2-container--disabled .select2-selection--single { 139 | background-color: transparent; 140 | cursor: not-allowed; 141 | .select2-selection__rendered { 142 | color: lightgray; 143 | font-style: italic; 144 | } 145 | } 146 | 147 | .select2-container--default .select2-selection--single .select2-selection__clear { 148 | float: left; 149 | margin-right: 0; 150 | } -------------------------------------------------------------------------------- /src/js/libs/pure-snow.js: -------------------------------------------------------------------------------- 1 | export default class Snow { 2 | constructor(selector = "#snow") { 3 | this.selector = selector; 4 | this.wrapper = document.querySelector(selector); 5 | this.snowflakesCount = Number(this.wrapper?.dataset?.count || 50); 6 | 7 | this.bodyHeightPx = 0; 8 | this.pageHeightVh = 0; 9 | this.baseCSS = ""; 10 | 11 | this.cssElement = null; 12 | 13 | this.handleResize = this.create.bind(this); 14 | window.addEventListener("resize", this.handleResize); 15 | } 16 | 17 | // ---------------------------------------------------------- 18 | // Helpers 19 | // ---------------------------------------------------------- 20 | 21 | setHeightVariables() { 22 | this.bodyHeightPx = document.body.offsetHeight; 23 | this.pageHeightVh = (100 * this.bodyHeightPx / window.innerHeight); 24 | } 25 | 26 | getCSSContainer() { 27 | if (this.cssElement) return this.cssElement; 28 | 29 | this.cssElement = document.createElement("style"); 30 | this.cssElement.id = "psjs-css"; 31 | document.head.appendChild(this.cssElement); 32 | 33 | return this.cssElement; 34 | } 35 | 36 | addCSS(rule) { 37 | const el = this.getCSSContainer(); 38 | el.innerHTML = rule; 39 | } 40 | 41 | randomInt(value = 100) { 42 | return Math.floor(Math.random() * value) + 1; 43 | } 44 | 45 | randomIntRange(min, max) { 46 | min = Math.ceil(min); 47 | max = Math.floor(max); 48 | return Math.floor(Math.random() * (max - min + 1)) + min; 49 | } 50 | 51 | getRandomArbitrary(min, max) { 52 | return Math.random() * (max - min) + min; 53 | } 54 | 55 | // ---------------------------------------------------------- 56 | // Core snow functionality 57 | // ---------------------------------------------------------- 58 | 59 | generateSnowflakes(count) { 60 | this.wrapper.innerHTML = ""; 61 | 62 | for (let i = 0; i < count; i++) { 63 | const div = document.createElement("div"); 64 | div.className = "snowflake"; 65 | this.wrapper.appendChild(div); 66 | } 67 | } 68 | 69 | generateSnowCSS(count) { 70 | let rule = this.baseCSS; 71 | 72 | for (let i = 0; i < count; i++) { 73 | const nth = i + 1; 74 | 75 | let randomX = Math.random() * 100; 76 | let randomOffset = Math.random() * 10; 77 | let randomXEnd = randomX + randomOffset; 78 | let randomXEndYoyo = randomX + randomOffset / 2; 79 | 80 | let randomYoyoTime = this.getRandomArbitrary(0.3, 0.8); 81 | let randomYoyoY = randomYoyoTime * this.pageHeightVh; 82 | 83 | let randomScale = Math.random(); 84 | let fallDuration = this.randomIntRange(10, this.pageHeightVh / 10 * 3); 85 | let fallDelay = this.randomInt(this.pageHeightVh / 10 * 3) * -1; 86 | let opacity = Math.random(); 87 | 88 | rule += ` 89 | .snowflake:nth-child(${nth}) { 90 | opacity: ${opacity}; 91 | transform: translate(${randomX}vw, -10px) scale(${randomScale}); 92 | animation: fall-${nth} ${fallDuration}s ${fallDelay}s linear infinite; 93 | } 94 | @keyframes fall-${nth} { 95 | ${randomYoyoTime * 100}% { 96 | transform: translate(${randomXEnd}vw, ${randomYoyoY}vh) scale(${randomScale}); 97 | } 98 | to { 99 | transform: translate(${randomXEndYoyo}vw, ${this.pageHeightVh}vh) scale(${randomScale}); 100 | } 101 | } 102 | `; 103 | } 104 | 105 | this.addCSS(rule); 106 | } 107 | 108 | // ---------------------------------------------------------- 109 | // Public API 110 | // ---------------------------------------------------------- 111 | 112 | create() { 113 | this.setHeightVariables(); 114 | 115 | // Reload dataset count each time 116 | this.snowflakesCount = Number( 117 | this.wrapper?.dataset?.count || this.snowflakesCount 118 | ); 119 | 120 | this.generateSnowCSS(this.snowflakesCount); 121 | this.generateSnowflakes(this.snowflakesCount); 122 | } 123 | 124 | show() { 125 | this.wrapper.style.display = "block"; 126 | } 127 | 128 | hide() { 129 | this.wrapper.style.display = "none"; 130 | } 131 | 132 | destroy() { 133 | window.removeEventListener("resize", this.handleResize); 134 | this.wrapper.innerHTML = ""; 135 | if (this.cssElement) this.cssElement.remove(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/js/animations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Give a animate.css class to a given element (https://animate.style/) 3 | * @param {text} [element] - jQuery Object to animate 4 | * @param {text} [animation] - animation name to apply 5 | */ 6 | export function animateCSS($element, animation, prefix = "animate__") { 7 | return new Promise((resolve) => { 8 | const animationName = `${prefix}${animation}`; 9 | const hasAnimationClass = $element.hasClass(`${prefix}animated`); 10 | 11 | $element.addClass(`${prefix}animated ${animationName}`); 12 | 13 | function handleAnimationEnd(event) { 14 | // Remove the classes from the jQuery object 15 | event.stopPropagation(); 16 | $element.removeClass(`${animationName}`); 17 | if (!hasAnimationClass) $element.removeClass(`${prefix}animated`); 18 | resolve("Animation ended"); 19 | } 20 | 21 | // Use the on() method to attach the event handler 22 | $element.on("animationend", handleAnimationEnd); 23 | }); 24 | } 25 | 26 | /** 27 | * Draw an explosion at given coordinated 28 | * @param {number} [x] - horizontal coordinates in pixel 29 | * @param {number} [y] - vertical coordinates in pixel 30 | */ 31 | export function explode(x, y, startAngle, endAngle) { 32 | const colors = ["rgba(255, 255, 255, 0.3)"]; 33 | const bubbles = 30; 34 | const r = (a, b, c) => parseFloat((Math.random() * ((a || 1) - (b || 0)) + (b || 0)).toFixed(c || 0)); 35 | let particles = []; 36 | let ratio = window.devicePixelRatio; 37 | let c = document.createElement("canvas"); 38 | let ctx = c.getContext("2d"); 39 | 40 | c.style.position = "absolute"; 41 | c.style.left = `${x - 100}px`; 42 | c.style.top = `${y - 100}px`; 43 | c.style.pointerEvents = "none"; 44 | c.style.width = `${200}px`; 45 | c.style.height = `${200}px`; 46 | c.style.zIndex = 100; 47 | c.width = 200 * ratio; 48 | c.height = 200 * ratio; 49 | document.body.appendChild(c); 50 | 51 | for (let i = 0; i < bubbles; i++) { 52 | particles.push({ 53 | x: c.width / 2, 54 | y: c.height / 2, 55 | radius: r(5, 20), 56 | color: colors[Math.floor(Math.random() * colors.length)], 57 | rotation: r(startAngle, endAngle, true), 58 | speed: r(0.5,1.5), 59 | friction: 0.98, 60 | opacity: r(0.9, 0.9, true), 61 | yVel: 0, 62 | gravity: 0 63 | }); 64 | } 65 | 66 | render(particles, ctx, c.width, c.height); 67 | setTimeout(() => document.body.removeChild(c), 200); 68 | } 69 | 70 | 71 | /** 72 | * Draw an explosion at given coordinated 73 | * @param {number} [particles] - Array of particles generated via explode() 74 | * @param {number} [ctx] - canvas 75 | * @param {number} [width] - canvas width 76 | * @param {number} [height] - canvas height 77 | * @returns {object} canvas 78 | */ 79 | function render(particles, ctx, width, height) { 80 | requestAnimationFrame(() => render(particles, ctx, width, height)); 81 | ctx.clearRect(0, 0, width, height); 82 | 83 | particles.forEach((p) => { 84 | p.x += p.speed * Math.cos(p.rotation * Math.PI / 180); 85 | p.y += p.speed * Math.sin(p.rotation * Math.PI / 180); 86 | 87 | p.opacity -= 0.01; 88 | p.speed *= p.friction; 89 | p.radius *= p.friction; 90 | p.yVel += p.gravity; 91 | p.y += p.yVel; 92 | 93 | if (p.opacity < 0 || p.radius < 0) return; 94 | 95 | ctx.beginPath(); 96 | ctx.globalAlpha = p.opacity; 97 | ctx.fillStyle = p.color; 98 | ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, false); 99 | ctx.fill(); 100 | }); 101 | 102 | return ctx; 103 | } 104 | 105 | 106 | export function animateCalc(goal, duration, destination) { 107 | // Ensure target is a number 108 | const element = $(`#${destination}`); 109 | let target = element.html(); 110 | target = isNaN(element.html()) ? 0 : Number(element.html()); 111 | 112 | const increment = Math.abs(goal - target) / (duration / 16); 113 | 114 | // If goal is an integer, intermediate values will be integers too 115 | const decimalPlaces = Number.isInteger(Number(goal)) ? 0 : 1; 116 | 117 | function updateCount(current) { 118 | element.text(current.toFixed(decimalPlaces)); 119 | 120 | // Determine the animation direction 121 | if ((target < goal && current < goal) || (target > goal && current > goal)) { 122 | requestAnimationFrame(() => updateCount(target < goal ? current + increment : current - increment)); 123 | } else { 124 | element.text(goal); 125 | } 126 | } 127 | 128 | updateCount(target); 129 | } -------------------------------------------------------------------------------- /src/components/map/mapObjectives.scss: -------------------------------------------------------------------------------- 1 | @use "../shared/variables"; 2 | 3 | // Global variables 4 | $flag-opacity: 0.8; 5 | $flag-circle-opacity: 0.2; 6 | 7 | // Mixins for repeated styles 8 | @mixin flag-color($bg-color, $outline-color) { 9 | background-color: rgba($bg-color, $flag-opacity); 10 | &.circleFlag { 11 | outline: solid $outline-color 3px; 12 | background-color: rgba($bg-color, $flag-circle-opacity); 13 | } 14 | } 15 | 16 | .objText { 17 | @include variables.light-text-outline; 18 | font-size: var(--font-size-objtext); 19 | font-family: roboto, Verdana, Geneva, Tahoma, sans-serif; 20 | letter-spacing: 0.02em; 21 | align-content: center; 22 | display: grid; 23 | // &.main { 24 | // //text-transform: uppercase; 25 | // //border: solid red 1px; 26 | // } 27 | } 28 | 29 | #map_ui #map .leaflet-pane .leaflet-marker-pane .flag { 30 | @include variables.light-text-outline; 31 | background-color: rgba(255, 255, 255, 0.4); 32 | font-size: 1.3em; 33 | border: solid rgba(0, 0, 0, 0.5) 1px; 34 | box-shadow: 0 8px 12px rgba(0, 0, 0, 0.75); 35 | transition: opacity 0.25s ease-in-out; 36 | font-family: variables.$mainFont, Verdana, Geneva, Tahoma, sans-serif; 37 | border-radius: 2px; 38 | cursor: inherit; 39 | align-content: center; 40 | display: grid; 41 | &.circleFlag { 42 | border-radius: 15px; 43 | margin-left: -15px!important; 44 | margin-top: -15px!important; 45 | width: 30px!important; 46 | height: 30px!important; 47 | align-content: center; 48 | display: grid; 49 | letter-spacing: 0; 50 | outline: solid 3px rgb(104, 104, 104); 51 | &.selected { 52 | background-color: rgba(0, 128, 0, 1); 53 | outline-color: rgb(0, 90, 0); 54 | } 55 | } 56 | &:active { 57 | cursor: inherit; 58 | } 59 | &.flag2 { @include flag-color(rgb(0, 255, 0), rgb(68, 255, 68)); } 60 | &.flag3 { @include flag-color(rgb(0, 0, 255), rgb(0, 0, 255)); } 61 | &.flag4 { @include flag-color(rgb(255, 255, 0), rgb(255, 255, 0)); } 62 | &.flag5 { @include flag-color(rgb(43, 255, 255), rgb(43, 255, 255)); } 63 | &.flag6 { @include flag-color(rgb(200, 48, 102), rgb(200, 48, 102)); } 64 | &.flag7 { @include flag-color(rgb(255, 105, 0), rgb(255, 105, 0)); } 65 | &.selected { 66 | font-size: 1.3em; 67 | background-color: rgba(0, 128, 0, 0.9); 68 | overflow: hidden; 69 | display: block; 70 | &::before { 71 | content: "✔"; 72 | color: rgb(255, 255, 255); 73 | position: relative; 74 | font-size: 2em; 75 | top: 0.2em; 76 | right: 0.2em; 77 | line-height: 0%; 78 | } 79 | &.circleFlag { 80 | display: grid; 81 | &::before { 82 | content: ""; 83 | } 84 | &.main { 85 | background-color: rgba(0, 128, 0, 1); 86 | } 87 | &:hover { 88 | box-shadow: 0 2px 12px rgba(0, 0, 0, 1); 89 | } 90 | } 91 | } 92 | &.main { 93 | overflow: hidden; 94 | background-size: contain; 95 | background-position: center center; 96 | background-repeat: no-repeat; 97 | border: none; 98 | outline: 2px rgb(58, 58, 58) solid; 99 | &.circleFlag { 100 | background-size: cover; 101 | } 102 | } 103 | &.main.selectable { 104 | background-color: rgb(197, 0, 0); 105 | outline: 3px rgb(143, 0, 0) solid!important; 106 | &:focus { 107 | outline: 3px rgb(143, 0, 0) solid!important; 108 | } 109 | } 110 | &.main.unselectable { 111 | background-color: rgba(255, 255, 255, 0.4); 112 | outline: solid 3px rgb(104, 104, 104)!important; 113 | &:focus { 114 | outline: solid 3px rgb(104, 104, 104)!important; 115 | } 116 | } 117 | &.main.selected { 118 | background-color: rgba(0, 128, 0, 0.9); 119 | outline: 3px rgb(0, 90, 0) solid !important; 120 | &::before { 121 | content: ""; 122 | } 123 | } 124 | &.selected, &.next, &.main { 125 | cursor: pointer; 126 | pointer-events: all; 127 | box-shadow: 0 8px 12px rgba(0, 0, 0, 0.7); 128 | &:hover { 129 | outline-width: 3px; 130 | box-shadow: 0 2px 12px rgba(0, 0, 0, 1); 131 | } 132 | } 133 | &.next { 134 | background-color: rgba(197, 0, 0); 135 | &.circleFlag { 136 | background-color: rgba(197, 0, 0); 137 | outline-color: rgb(143, 0, 0); 138 | outline-width: 3px; 139 | letter-spacing: 0; 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/components/legacyui/legacyui.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 |
8 |
9 |
10 |
11 | mortar 12 | 13 |
14 |
15 |
16 |
17 |
18 | 19 |
20 | 21 |
22 |
23 |
24 |
25 |
26 | target 27 | 28 |
29 |
30 |
31 |
32 |
33 |
34 | 35 |
36 |
37 |
38 |
39 |
40 |
41 | xxx 42 | 43 |
44 |
-
45 |
46 | xxxx 47 | 50 |
51 |
52 |
55 |
56 |
57 |
58 | 59 | 65 | 66 |
67 | 68 |
69 | 70 |
-------------------------------------------------------------------------------- /public/locales/zh/units.json: -------------------------------------------------------------------------------- 1 | { 2 | "Air Assault": "空中突击", 3 | "Amphibious Assault": "两栖突击", 4 | "Armored": "装甲旅", 5 | "Combined Arms": "合成旅", 6 | "Light Infantry": "轻步兵", 7 | "Mechanized": "机械化", 8 | "Motorized": "摩托化", 9 | "Support": "支援营", 10 | "Australian Defence Force": "澳大利亚国防军", 11 | "3rd Brigade Battle Group": "第三旅战斗群", 12 | "1st Battalion, Royal Australian Regiment": "皇家军团第一营", 13 | "3rd Battalion, Royal Australian Regiment": "皇家军团第三营", 14 | "British Armed Forces": "英国陆军", 15 | "Queen's Royal Hussars Battle Group": "女王皇家骠骑兵战斗群", 16 | "3rd Division Battle Group": "第三师战斗群", 17 | "1 Yorks Battle Group": "第一约克郡战斗群", 18 | "Royal Logistics Corps Battle Group": "皇家后勤支援战斗群", 19 | "2nd Battalion, Parachute Regiment": "第二空降团", 20 | "Canadian Armed Forces": "加拿大陆军", 21 | "Lord Strathcona's Horse Regiment": "斯特拉斯科纳勋爵骑兵团", 22 | "1 Canadian Mechanized Brigade Group": "第一机械化旅群", 23 | "1st Battalion, Royal 22e Régiment": "皇家第22军团第1营", 24 | "12e Régiment Blindé du Canada": "第12装甲团", 25 | "6 Canadian Combat Support Brigade": "第6战斗支援旅", 26 | "3rd Battalion, Royal Canadian Regiment": "皇家军团第3营", 27 | "Russian Ground Forces": "俄罗斯陆军", 28 | "United States Army": "美国陆军", 29 | "Irregular Militia Forces": "非正规民兵", 30 | "Irregular Armored Squadron": "非正规装甲中队", 31 | "Irregular Battle Group": "非正规战斗群", 32 | "Irregular Light Infantry": "非正规轻步兵", 33 | "Irregular Mechanized Platoon": "非正规机械化排", 34 | "Irregular Motorized Platoon": "非正摩托化排", 35 | "Irregular Fire Support Group": "非正规火力支援群", 36 | "Insurgents": "叛军", 37 | "Middle Eastern Alliance": "中东联军", 38 | "60th Prince Assur Armored Brigade": "阿苏尔亲王第六十装甲旅", 39 | "1st Battalion, Legion of Babylon": "巴比伦军团第一营", 40 | "4th Border Guards Group": "第四边防卫队", 41 | "3rd King Qadesh Mechanized Infantry Brigade": "国王卡德什第三机械化步兵旅", 42 | "Vizir Hussein 2nd Support Battalion": "维齐尔·侯赛因第二支援营", 43 | "91st Air Assault Battalion": "第九十一空中突击营", 44 | "People's Liberation Army": "中国人民解放军", 45 | "195th Heavy Combined Arms Brigade": "第195重型合成旅", 46 | "118th Combined Arms Brigade": "'暴风雨部队'-第118合成旅", 47 | "149th Mountain Infantry Brigade": "'两不怕'-第149山地步兵旅", 48 | "112th Medium Combined Arms Brigade": "'英勇胜利'-第112中型合成旅", 49 | "80th Combined Arms Brigade": "第80合成旅", 50 | "161st Air Assault Brigade": "'空突利刃'-第161空中突击旅", 51 | "80th Support Brigade": "第80勤务支援旅", 52 | "9th Heavy Combined Arms Battalion": "第9重型合成旅", 53 | "14th Amphibious Combined Arms Brigade": "第14两栖合成旅", 54 | "4th Medium Combined Arms Battalion": "第4中型合成旅", 55 | "PLA Navy Marine Corps": "中国人民解放军海军陆战队", 56 | "3rd Marine Heavy Battalion": "第3重型旅", 57 | "5th Marine Brigade": "第5合成旅", 58 | "4th Marine Special Combat Battalion": "第4特种作战旅", 59 | "7th Marine Medium Battalion": "第7中型旅", 60 | "17th Marine Support Battalion": "第17勤务支援营", 61 | "6th Separate Tank Brigade": "第6独立坦克旅", 62 | "49th Combined Arms Army": "第49合成军", 63 | "1398th Separate Reconnaissance Battalion": "第1398独立侦察营", 64 | "205th Separate Motor Rifle Brigade": "第205独立摩托化步枪旅", 65 | "3rd Motor Rifle Brigade": "第3摩托化步枪旅", 66 | "78th Detached Logistics Brigade": "第78独立补给旅", 67 | "336th Guards Naval Infantry Brigade": "第336近卫海军步兵旅", 68 | "Turkish Land Forces": "土耳其陆军", 69 | "4th Armored Brigade Battle Group": "第4装甲旅战斗群", 70 | "1st Army Battle Group": "第1集团军战斗群", 71 | "66th Mechanized Infantry Brigade Battle Group": "第66机械化步兵旅战斗群", 72 | "51st Motorized Infantry Brigade Battle Group": "第51摩托化步兵旅战斗群", 73 | "Land Forces Logistics Command Battle Group": "陆军后勤指挥战斗群", 74 | "1st Commando Brigade Battle Group": "第1突击旅战斗群", 75 | "US Brigade Combat Team Training": "美军旅战斗队训练", 76 | "37th Armored Regiment, 1st Armored Division": "第1装甲师第37装甲团", 77 | "3rd Brigade Combat Team, 1st Infantry Division": "第1步兵师第3旅战斗队", 78 | "1st Brigade Combat Team, 10th Mountain Division": "第10山地师第1旅战斗队", 79 | "1st Cavalry Regiment": "第1骑兵团", 80 | "2nd Cavalry Stryker Brigade Combat Team": "第2骑兵史崔克旅战斗队", 81 | "497th Combat Sustainment Support Battalion": "第497战斗保障支援营", 82 | "1st Brigade Combat Team, 82nd Airborne Division": "第82空降师第1旅战斗队", 83 | "United States Marine Corps": "美国海军陆战队", 84 | "1st Tank Battalion, 1st Marines": "第1海军陆战队第1坦克营", 85 | "31st Marine Expeditionary Unit": "第31海军陆战队远征部队", 86 | "1st Marines Regimental Combat Team": "海军陆战队第1团战斗队", 87 | "3rd Light Armored Recon Battalion": "第3轻装甲侦察营", 88 | "2nd Marine Logistics Group": "第2海军陆战队补给群", 89 | "4th Marines Amphibious Ready Group": "第4海军陆战队两栖攻击待命大队", 90 | "Russian Airbourne Forces": "俄罗斯空降军", 91 | "104th Tank Battalion": "第104坦克营", 92 | "7th Guards Mountain Air Assault Division": "第7近卫山地空中突击师", 93 | "108th Guards Air Assault Regiment": "第108近卫空中突击团", 94 | "150th Support Battalion": "第150支援营", 95 | "217th Guards Airborne Regiment": "第217近卫空降团", 96 | "Manticore Security Task Force": "曼提科尔安保特遣队", 97 | "Overwatch 6 Patrol Group": "守望6号巡逻组", 98 | "Murk Water Air Wing": "暗水航空联队" 99 | } --------------------------------------------------------------------------------