Compare commits

...
10 Commits
Author SHA1 Message Date
Nathan Rashleigh 90b9faf31a maplists and theme 2026-02-11 18:26:00 +11:00
Nathan Rashleigh 81cfced965 admin 2026-02-10 14:06:39 +11:00
Nathan Rashleigh 737207f3dd rcon pass 2026-02-10 13:20:19 +11:00
Nathan Rashleigh 0d2260f983 peace on earth 2026-02-10 13:11:31 +11:00
Nathan Rashleigh 1528f0a2b0 mapcycle and all 2026-02-10 11:36:02 +11:00
Nathan Rashleigh bcf798a5f9 fastdl 2026-02-10 10:46:45 +11:00
Nathan Rashleigh 31a2ac82d0 mapsdl common 2026-02-10 10:07:09 +11:00
Nathan Rashleigh f66c505082 mapsdl 2026-02-09 23:21:40 +11:00
Nathan Rashleigh cf65959148 mapsdl 2026-02-09 22:34:25 +11:00
Nathan Rashleigh 43883f3841 YUH 2026-02-09 18:15:01 +11:00
34 changed files with 11222 additions and 668 deletions

No files matched your search

+9 -3
View File
@@ -1,11 +1,11 @@
STEAMAPPID=232330
STEAMAPP=css
SRCDS_TOKEN=C02633B3395EA6BEF7D8DFBA440ABB7F
SRCDS_RCONPW="lol"
SRCDS_TOKEN=3C403551712E10420F08F5CA337F9B21
SRCDS_RCONPW="reebok"
SRCDS_PW="6"
SRCDS_STARTMAP="surf_boreas"
SRCDS_STARTMAP="surf_anzchamps"
SRCDS_HOSTNAME="megastructure surf"
SRCDS_MAXPLAYERS=16
@@ -28,6 +28,11 @@ SRCDS_WORKSHOP_AUTHKEY=""
SRCDS_CFG="server.cfg"
SRCDS_MAPCYCLE="mapcycle.txt"
SRCDS_ADMINS=[U:1:1589252886],[U:1:12270329]
# ----------
# fastdl
FASTDL_URL=https://fastdl.megastructure.surf
# ----------
# mariadb
@@ -35,3 +40,4 @@ MARIADB_ROOT_PASSWORD="surfsup"
MARIADB_DATABASE="influx"
MARIADB_USER="influx"
MARIADB_PASSWORD="righteous"
+3
View File
@@ -2,8 +2,11 @@
*.sql.gz
*.tar.gz
.env/
data/
src/mapsdl/credentials
surf.sublime-workspace
+34 -11
View File
@@ -1,17 +1,40 @@
build-css:
docker build -f css/css.dockerfile css/ -t megastructure/css
# Map downloader commands
mapsdl-dry:
cd src/mapsdl && deno run -A mapsdl.ts --dry-run
up:
docker compose up --remove-orphans
mapsdl:
cd src/mapsdl && deno run -A mapsdl.ts
down:
docker compose down -v --remove-orphans
mapsdl-all-dry:
cd src/mapsdl && deno run -A mapsdl-all.ts --dry-run
mapsdl-all:
cd src/mapsdl && deno run -A mapsdl-all.ts --dry-run
# k8s
build:
docker compose build
docker build -t megastructure-surf-cssds:local -t registry.ntwl.xyz/megastructure-surf-cssds src/cssds
docker build -t megastructure-surf-mapsdl:local -t registry.ntwl.xyz/megastructure-surf-mapsdl src/mapsdl
docker build -t megastructure-surf-fastdl:local -t registry.ntwl.xyz/megastructure-surf-fastdl src/fastdl
cssds-run:
docker compose run -u root -it cssds bash
push:
docker push registry.ntwl.xyz/megastructure-surf-cssds
docker push registry.ntwl.xyz/megastructure-surf-mapsdl
docker push registry.ntwl.xyz/megastructure-surf-fastdl
cssds-exec:
docker compose exec -u root -it cssds bash
build-cssds:
docker build -t megastructure-surf-cssds:local -t registry.ntwl.xyz/megastructure-surf-cssds src/cssds
build-mapsdl:
docker build -t megastructure-surf-mapsdl:local -t registry.ntwl.xyz/megastructure-surf-mapsdl src/mapsdl
build-fastdl:
docker build -t megastructure-surf-fastdl:local -t registry.ntwl.xyz/megastructure-surf-fastdl src/fastdl
apply:
kubectl delete pod mapsdl -n surf --ignore-not-found
kubectl apply -f k8s.yaml
env:
kubectl delete secret surf -n surf --ignore-not-found
kubectl create secret generic surf --from-env-file=.env -n surf
+225 -187
View File
@@ -1,36 +1,30 @@
# megastructure.surf
A Docker-based Counter-Strike: Source surf server with Shavit BHopTimer and community physics fix plugins.
A Docker-based Counter-Strike: Source surf server with Shavit Surf Timer and community physics fix plugins.
## Overview
This repository contains a complete CSS surf server setup using Docker containers. The setup includes:
- **CSS Dedicated Server (CSSDS)** - Running on 64-bit binaries for improved performance
- **Shavit BHopTimer** - Actively maintained timer system (v4.0.1) with MySQL support
- **MariaDB** - Database backend for timer records and player data
- **CSS Dedicated Server (CSSDS)** - Running in 32-bit mode for compatibility
- **Shavit Surf Timer** - Surf-specific fork (v1.0.6) with JSON zone support and SQLite
- **MetaMod:Source** - Plugin loader framework
- **SourceMod** - Server administration and plugin platform
- **Community Physics Plugins** - Essential surf/bhop fixes and enhancements
- **Community Physics Plugins** - Essential surf fixes and enhancements
- **JSON Zone Loading** - Automatic zone loading from surf-zones repository
## Architecture
### Docker Services
### Docker Service
#### `cssds` (CSS Dedicated Server)
- Based on Debian Bookworm
- Runs SteamCMD to download/update CSS DS and TF2 DS (for 64-bit binaries)
- Runs SteamCMD to download/update CSS DS
- Installs MetaMod:Source and SourceMod
- Installs surf-specific plugins and timer system
- Uses 64-bit server binaries for better performance
- Runs in 32-bit mode for plugin compatibility
- Port: 27015 (configurable via `SRCDS_PORT`)
#### `mariadb` (Database)
- MariaDB 10.11 for timer data persistence
- Stores player records, map times, rankings
- Port: 3306 (internal)
- Data persisted in `./sql:/var/lib/mysql`
### Key Files
```
@@ -38,30 +32,46 @@ This repository contains a complete CSS surf server setup using Docker container
├── docker-compose.yaml # Service orchestration
├── etc/
│ ├── cssds.dockerfile # CSS DS container definition
│ ├── mariadb.dockerfile # MariaDB container definition
│ ├── run.sh # Main setup and launch script
│ ├── update_cssds.txt # SteamCMD script for CSS DS
│ ├── update_tf2ds.txt # SteamCMD script for TF2 DS (64-bit libs)
│ └── cfg/
│ └── server.cfg # Server configuration
└── sql/ # MariaDB data directory (volume mount)
└── data/ # Persistent data (volume mount)
└── cssds/ # CSS server files and database
```
## Installed Plugins
## Installed Plugins & Extensions
### Timer System
**Shavit BHopTimer v4.0.1** ([GitHub](https://github.com/shavitush/bhoptimer))
- Actively maintained (last update: February 2026)
- Full surf/bhop timer with MySQL backend
**Shavit Surf Timer v1.0.6** ([GitHub](https://github.com/bhopppp/Shavit-Surf-Timer))
- Surf-specific fork with enhanced features
- Full surf timer with SQLite backend (no separate database needed)
- Replays, rankings, zone system, statistics
- Better SQL schema design than archived alternatives
- Config location: `addons/sourcemod/configs/shavit/`
- **Configured to use JSON zones** from [surf-zones](https://github.com/wrldspawn/surf-zones) repository
- **JSON zone support** from [surf-zones](https://github.com/wrldspawn/surf-zones) repository
- Zones loaded from `https://wrldspawn.github.io/surf-zones/z/{map}.json`
- Includes stripper configurations and mapfixes
- Matches KSF (Kreedz Surf Federation) server behavior
- Use `!setmaxvel` in-game to configure max velocity per map
- Config location: `addons/sourcemod/configs/shavit/`
### Required Extensions
**sm-json v5.0.1** ([GitHub](https://github.com/clugg/sm-json))
- Pure SourcePawn JSON library for zone loading
- Provides `JSONArray.FromFile()` for loading JSON zones
**sm_closestpos v1.1.1** ([GitHub](https://github.com/rtldg/sm_closestpos))
- Required for ghost/replay functionality
- Enables replay bot positioning
**sm-ripext v1.3.2** ([GitHub](https://github.com/ErikMinekus/sm-ripext))
- HTTP/REST extension for Shavit
- Required for shavit-wrsh plugin
- Alternative JSON/HTTP support
**DHooks v2.2.0** ([GitHub](https://github.com/peace-maker/DHooks2))
- Included with SourceMod
- Required by most modern plugins
### Physics Fix Plugins
@@ -69,10 +79,6 @@ This repository contains a complete CSS surf server setup using Docker container
- Fixes Source engine surf physics to match Momentum Mod behavior
- Essential for proper surf mechanics
**PushFix Definitive Edition v1.0.0** ([GitHub](https://github.com/GAMMACASE/PushFixDE))
- Fixes player collision and push mechanics
- Prevents physics exploits
**EventQueue Fix v1.3.2** ([GitHub](https://github.com/hermansimensen/eventqueue-fix))
- Fixes map entity timing issues
- Ensures triggers and outputs work correctly
@@ -81,13 +87,15 @@ This repository contains a complete CSS surf server setup using Docker container
- Fixes Source engine RNG determinism issues
- Ensures consistent physics behavior
**Note:** PushFix Definitive Edition is NOT installed as it's CS:GO only and not compatible with CSS.
### Base Plugins
SourceMod includes built-in plugins for server administration:
- Admin Menu, Basic Commands, Player Commands
- Rock The Vote, Map Nominations, MapChooser
- Reserved Slots, Basic Bans
- And more (see `etc/run.sh` comments for full list)
- And more (see `etc/run.sh` for full list)
## Setup & Usage
@@ -99,173 +107,218 @@ SourceMod includes built-in plugins for server administration:
### Environment Variables
Configure in `docker-compose.yaml`:
Configure in `docker-compose.yaml` or `.env` file:
```yaml
METAMOD_VERSION: "1.11" # MetaMod:Source version
SOURCEMOD_VERSION: "1.11" # SourceMod version
# Server Settings
METAMOD_VERSION: "1.12" # MetaMod:Source version
SOURCEMOD_VERSION: "1.12" # SourceMod version
SRCDS_PORT: 27015 # Server port
SRCDS_MAXPLAYERS: 32 # Max player slots
SRCDS_STARTMAP: "surf_ski_2" # Starting map
SRCDS_IP: "0.0.0.0" # Bind IP address
# Admin Configuration (comma-separated Steam IDs)
SRCDS_ADMINS: "STEAM_1:0:12345678,STEAM_1:1:87654321"
```
**Admin Steam ID Format:**
- Use `STEAM_1:Y:XXXXXX` format (recommended)
- Or `[U:1:XXXXXX]` format (modern SteamID3)
- Find your Steam ID in-game with `status` command
- Or use https://steamid.io/
### Building & Running
```bash
# Build the containers
# Build the container
docker-compose build
# Start the services
# Start the server
docker-compose up -d
# View logs
docker-compose logs -f cssds
# Stop the services
# Restart the server
docker-compose restart cssds
# Stop the server
docker-compose down
```
### First-Time Database Configuration
### Update Server Files
After the first build, configure Shavit to use MariaDB:
The server installation is persistent - game files are only downloaded on first run. To force an update:
1. Edit `addons/sourcemod/configs/databases.cfg`:
```
"Databases"
{
"shavit"
{
"driver" "mysql"
"host" "mariadb"
"database" "shavit"
"user" "root"
"pass" "your_password"
}
}
```bash
# Update CSS game files
docker-compose run cssds bash ./etc/run.sh --update-cssds
```
2. Shavit will automatically create tables on first connection
Or modify the environment to skip updates by default (already configured):
- Default: Updates are **skipped** for faster restarts
- Use `--update-cssds` flag to force updates
### Database Configuration
The server uses **SQLite by default** (no separate database needed):
- Database file: `addons/sourcemod/data/sqlite/shavit-local.sq3`
- Automatically created on first run
- Stores player times, rankings, and replay data
**To switch to MariaDB later** (optional):
1. Edit `addons/sourcemod/configs/databases.cfg`
2. Change driver from `sqlite` to `mysql`
3. Configure host, database, user, password
4. Restart server
### JSON Zones Configuration
The server is **automatically configured** to use JSON zones instead of SQL-based zones. This provides several advantages:
The server is **automatically configured** to use JSON zones instead of SQL-based zones:
**Automatic Setup:**
- Zones are loaded from the community-maintained [surf-zones](https://github.com/wrldspawn/surf-zones) repository
- Includes 400+ maps with pre-configured zones, stripper configs, and mapfixes
- Zones loaded from [surf-zones](https://github.com/wrldspawn/surf-zones) repository
- Includes 400+ maps with pre-configured zones
- No manual zone creation needed for supported maps
- Automatically downloads: `https://wrldspawn.github.io/surf-zones/z/{map}.json`
- URL: `https://wrldspawn.github.io/surf-zones/z/{map}.json`
**Configuration Files Created:**
- `cfg/sourcemod/plugin.shavit-zones.cfg` - Disables SQL zones (`shavit_zones_usesql "0"`)
- `cfg/sourcemod/plugin.shavit-zones.cfg` - Disables SQL zones
- `cfg/sourcemod/plugin.shavit-zones-json.cfg` - Sets JSON URL
- `addons/stripper/` - Map entity fixes and modifications
- `addons/sourcemod/configs/shavit-mapfixes.cfg` - Map-specific settings
- `addons/stripper/` - Map entity fixes
- `addons/sourcemod/configs/shavit-mapfixes.cfg` - Map settings
- `addons/sourcemod/configs/shavit-styles.cfg` - KSF-style configurations
**Benefits:**
- ✅ No manual zone editing required for popular maps
- ✅ Community-maintained and regularly updated
- ✅ Includes map fixes for common issues
- ✅ Matches KSF server behavior and standards
- ✅ Faster deployment (no SQL import needed)
**Important Note:** The `sv_maxvelocity` settings in mapfixes won't auto-apply. After loading a map, use the in-game command:
```
!setmaxvel <value>
```
For most surf maps, use `!setmaxvel 3500`. Some maps may require different values (check surf-zones repo for specific maps).
- ✅ No manual zone editing for popular maps
- ✅ Community-maintained and updated
- ✅ Includes map fixes
- ✅ Matches KSF server standards
- ✅ Faster deployment
### Server Configuration
Edit `etc/cfg/server.cfg` for server settings:
- Hostname, rcon password
- Game settings (gravity, air accelerate, etc.)
- SourceMod configurations
- Hostname, RCON password (change default!)
- Surf physics (gravity, air accelerate, max velocity)
- HUD settings (minimal by default)
- Network rates
- Player settings
**Important:** Change the default RCON password:
```cfg
rcon_password "changeme" // CHANGE THIS!
```
## In-Game Commands
### Admin Commands
```
rcon_password <password> // Authenticate RCON
rcon sm_admin // Open admin menu
sm_map <mapname> // Change map
sm_kick <player> // Kick player
sm_ban <player> <time> // Ban player
```
### Player Commands
```
!wr // World records
!top // Top players
!profile // Your profile
!rank // Your rank
!recent // Recent records
!nominate // Nominate map
!rtv // Rock the vote
!stage <number> // Teleport to stage
!r / !restart // Restart timer
!pause // Pause timer
!cp / !checkpoint // Save checkpoint
!tp / !teleport // Teleport to checkpoint
!hide // Hide players
!hideweapon // Hide weapon
!hud // HUD settings
!zones // Show/edit zones
```
### Console Commands
```
sm plugins list // List loaded plugins
sm exts list // List loaded extensions
sm cmds // List all commands
status // Show players and Steam IDs
```
## Development Notes
### 32-bit Mode
The server runs in **32-bit mode** for maximum plugin compatibility:
- Most SourceMod plugins and extensions are 32-bit only
- DHooks and other critical extensions lack 64-bit versions
- 32-bit provides better compatibility with the plugin ecosystem
### Plugin Installation Pattern
All plugins follow an idempotent installation pattern in `etc/run.sh`:
```bash
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/plugin.smx" ]; then
cd /tmp
wget "https://github.com/author/repo/releases/download/version/plugin.zip"
unzip "plugin.zip"
rm "plugin.zip"
unzip -o "plugin.zip"
cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
rm -rf "plugin.zip" addons/
echo "Installed Plugin vX.Y.Z"
fi
```
This allows safe re-runs without reinstalling existing plugins.
### Version Strategy
**Fixed versions are used** (not dynamic `latest` detection) for:
- **Stability** - Known working versions prevent unexpected breaks
- **Reproducibility** - Docker builds are deterministic
- **No API dependencies** - Avoids GitHub API rate limits
- **Easy rollback** - Can revert to specific versions if issues arise
### 64-bit Binary Support
The server uses 64-bit binaries for improved performance:
1. TF2 DS is downloaded for its 64-bit libraries
2. `libsteam_api.so` and `srcds_linux64` are copied from TF2 to CSS
3. `_srv.so` binaries are symlinked to regular `.so` names
4. `steamclient.so` is located and symlinked to expected paths
### Run Script Flow
The `etc/run.sh` script executes in this order:
1. **update_cssds()** - Download/update CSS DS via SteamCMD
2. **update_tf2ds()** - Download/update TF2 DS for 64-bit binaries
3. **copy_64bit()** - Copy 64-bit libraries from TF2 to CSS
4. **symlink_binaries()** - Create symlinks for server binaries
5. **steamclient_binary()** - Locate and symlink steamclient.so
6. **install_metamod()** - Install MetaMod:Source if missing
7. **install_sourcemod()** - Install SourceMod if missing
8. **install_surf()** - Install timer and physics plugins
9. **configure_shavit_zones()** - Download and configure JSON zones, stripper configs, and mapfixes
10. **cfg()** - Copy server configuration
11. **run_cssds()** - Launch the dedicated server
1. **update_cssds()** - Download/update CSS DS via SteamCMD (skipped by default)
2. **steamclient_binary()** - Locate and symlink steamclient.so (32-bit)
3. **install_surf()** - Install timer, extensions, and physics plugins
- Install MetaMod:Source if missing
- Install SourceMod if missing
- Install sm-json (JSON library)
- Install sm_closestpos (replay positioning)
- Install sm-ripext (HTTP/REST)
- Install Shavit Surf Timer with sounds/materials
- Install shavit-zones-json from original bhoptimer
- Install MomSurfFix, EventQueue Fix, RNGFix
4. **configure_shavit_zones()** - Download JSON zones, stripper configs, mapfixes
5. **configure_shavit_database()** - Create SQLite database config
6. **configure_admins()** - Create admins from SRCDS_ADMINS env var
7. **cfg()** - Copy server.cfg
8. **run_cssds()** - Launch the dedicated server
### Version Strategy
**Fixed versions are used** for:
- **Stability** - Known working versions
- **Reproducibility** - Deterministic builds
- **No API dependencies** - Avoids rate limits
- **Easy rollback** - Specific version control
## Verification
### Check Installed Plugins
```bash
docker exec -it surf_megastructure-cssds-1 \
docker exec -it $(docker ps -qf "name=cssds") \
ls -la /home/steam/cssds/cstrike/addons/sourcemod/plugins/*.smx
```
### Check Shavit Configuration
### Check Extensions
```bash
docker exec -it surf_megastructure-cssds-1 \
ls -la /home/steam/cssds/cstrike/addons/sourcemod/configs/shavit/
```
### Check JSON Zones Configuration
```bash
# Check zone configuration files
docker exec -it surf_megastructure-cssds-1 \
cat /home/steam/cssds/cstrike/cfg/sourcemod/plugin.shavit-zones.cfg
# Check JSON URL configuration
docker exec -it surf_megastructure-cssds-1 \
cat /home/steam/cssds/cstrike/cfg/sourcemod/plugin.shavit-zones-json.cfg
# Check stripper configs installed
docker exec -it surf_megastructure-cssds-1 \
ls -la /home/steam/cssds/cstrike/addons/stripper/
# Check mapfixes
docker exec -it surf_megastructure-cssds-1 \
cat /home/steam/cssds/cstrike/addons/sourcemod/configs/shavit-mapfixes.cfg
docker exec -it $(docker ps -qf "name=cssds") \
ls -la /home/steam/cssds/cstrike/addons/sourcemod/extensions/*.so
```
### In-Game Verification
@@ -273,104 +326,89 @@ docker exec -it surf_megastructure-cssds-1 \
Connect to the server and run:
```
sm plugins list
sm exts list
```
You should see:
- Shavit BHopTimer (multiple modules)
- momsurffix2
- pushfix_de
- eventqueuefix
- rngfix
- Standard SourceMod plugins
- **Plugins:** Shavit (multiple modules), momsurffix2, eventqueuefix, rngfix
- **Extensions:** sm-json, closestpos, ripext, dhooks, sdkhooks
## Troubleshooting
### Plugins Not Loading
1. Check MetaMod is loaded: `meta list`
2. Check SourceMod is loaded: `sm version`
3. Check plugin errors: `sm plugins list` and look for "Failed" or "Error"
1. Check MetaMod: `meta list`
2. Check SourceMod: `sm version`
3. Check errors: `sm plugins list`
4. Check logs: `addons/sourcemod/logs/`
### Database Connection Issues
**Common Issues:**
- Missing extension dependencies (install sm-json, closestpos, ripext)
- Wrong architecture (use 32-bit plugins/extensions)
- File permissions (ensure steam user owns files)
1. Verify MariaDB container is running: `docker ps`
2. Check database credentials in `databases.cfg`
3. Check Shavit logs: `addons/sourcemod/logs/shavit/`
4. Test connection: `sm_sql_query shavit "SELECT 1"`
### Zones Not Loading
### Zones Not Loading / Map Has No Zones
**Symptoms:** Map loads but no start/end zones, timer doesn't work
**Symptoms:** Map loads but no start/end zones
**Solutions:**
1. **Check if map is in surf-zones repository:**
1. **Check if map exists in surf-zones:**
- Visit: https://github.com/wrldspawn/surf-zones/tree/main/z
- Search for your map name (e.g., `surf_ski_2.json`)
- Not all maps have pre-made zones
- Search for `surf_<mapname>.json`
2. **Verify JSON zones are enabled:**
2. **Verify JSON zones enabled:**
```
// In console
sm_cvar shavit_zones_usesql
// Should show: "shavit_zones_usesql" = "0"
// Should be "0"
```
3. **Check zone loading errors:**
- Check `addons/sourcemod/logs/shavit/`
- Look for HTTP errors or JSON parsing failures
4. **Create zones manually (if map not in repo):**
3. **Check sm-json loaded:**
```
// In-game
!zones // Open zone editor
!start // Create start zone
!end // Create end zone
sm exts list
// Look for sm-json or json.inc in includes
```
- Zones created in-game are saved to the database (not JSON)
5. **Network connectivity:**
- Verify container can reach GitHub: `docker exec -it surf_megastructure-cssds-1 curl -I https://wrldspawn.github.io/`
- Check firewall/proxy settings
4. **Check logs:**
- `addons/sourcemod/logs/shavit/`
- Look for HTTP/JSON errors
**Note:** If a map doesn't exist in the surf-zones repository, you'll need to create zones manually using the in-game zone editor (`!zones`). These will be saved to your MariaDB database.
5. **Create zones manually:**
```
!zones // Zone editor
!edit // Admin zone editor
```
### Missing Sounds/Materials
**Symptoms:** Missing finish sounds, zone decals
**Solution:** Reinstall Shavit to get sound/material files:
```bash
rm /path/to/data/cssds/cstrike/addons/sourcemod/plugins/shavit-core.smx
docker-compose restart cssds
```
### Server Won't Start
1. Check logs: `docker-compose logs cssds`
2. Verify port 27015 is available
3. Check disk space for server files
4. Verify SteamCMD downloaded files successfully
## Future Enhancements
### Potential Additions
- **FastDL** - Fast map download server (HTTP/Web server for map downloads)
- **SourceBans** - Web-based ban management system
- **Map rotation** - Automated map cycling configuration
- **GOTV** - Source TV for spectating/recording matches
- **Workshop maps** - Steam Workshop integration for map downloads
- **Backup system** - Automated database and config backups
### Maintenance
- Update plugin versions periodically
- Monitor Shavit GitHub for new releases
- Check for MetaMod/SourceMod updates
- Review server logs for errors or exploits
2. Verify port 27015 available
3. Check disk space
4. Verify SteamCMD succeeded
## Credits
- **Shavit BHopTimer** - [shavitush](https://github.com/shavitush/bhoptimer)
- **Shavit Surf Timer** - [bhopppp](https://github.com/bhopppp/Shavit-Surf-Timer)
- **sm-json** - [clugg](https://github.com/clugg/sm-json)
- **sm_closestpos** - [rtldg](https://github.com/rtldg/sm_closestpos)
- **sm-ripext** - [ErikMinekus](https://github.com/ErikMinekus/sm-ripext)
- **MomSurfFix** - [GAMMACASE](https://github.com/GAMMACASE/MomSurfFix)
- **PushFix DE** - [GAMMACASE](https://github.com/GAMMACASE/PushFixDE)
- **EventQueue Fix** - [hermansimensen](https://github.com/hermansimensen/eventqueue-fix)
- **RNGFix** - [jason-e](https://github.com/jason-e/rngfix)
- **Surf Zones** - [wrldspawn](https://github.com/wrldspawn/surf-zones)
- **MetaMod:Source** - [AlliedModders](https://www.metamodsource.net/)
- **SourceMod** - [AlliedModders](https://www.sourcemod.net/)
## License
This setup configuration is provided as-is. Individual components (Shavit, SourceMod, etc.) retain their original licenses.
This setup configuration is provided as-is. Individual components retain their original licenses.
-40
View File
@@ -1,40 +0,0 @@
services:
cssds:
image: registry.ntwl.xyz/megastructure-surf
build:
dockerfile: cssds.dockerfile
context: ./etc
user: "1000:1000"
env_file:
- .env
# command: sleep 5000000
network_mode: host
ports:
- "27015:27015"
- "27015:27015/udp"
- "27020:27020"
volumes:
- ./etc:/home/steam/etc
- ./data/cssds:/home/steam/cssds
- tf2ds:/home/steam/tf2ds
db:
image: mariadb:12
restart: always
ports:
- "3306:3306"
env_file:
- .env
volumes:
- ./etc/mariadb/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
volumes:
tf2ds:
-41
View File
@@ -1,41 +0,0 @@
FROM cm2network/steamcmd AS build
LABEL maintainer="ntr@megastructure.games"
EXPOSE 27015/tcp \
27015/udp \
27020/udp
USER root
RUN apt-get update
RUN apt-get install -y \
wget \
ca-certificates \
zlib1g \
lib32gcc-s1 \
libncurses5 \
libbz2-1.0 \
libtinfo5 \
libcurl3-gnutls \
unzip \
rcon
ENV CSSDS="/home/steam/cssds"
ENV TF2DS="/home/steam/tf2ds"
ENV STEAMCMD="/home/steam/steamcmd"
ENV ETC="/home/steam/etc"
ENV METAMOD_VERSION=1.12
ENV SOURCEMOD_VERSION=1.12
# ensure gamedirs exist and have been chowned to steam
# before they potentially get setup as docker volumes
# which would otherwise cause them to be owned by root
RUN mkdir -p "$CSSDS" "$TF2DS" "$STEAMCMD" "$ETC"
RUN chown -R steam:steam /home/steam
FROM build AS steam
USER steam
WORKDIR /home/steam
COPY . /home/steam/etc
CMD ["bash", "./etc/run.sh"]
-375
View File
@@ -1,375 +0,0 @@
#! /bin/bash
set -uxe
CSTRIKE="$CSSDS/cstrike"
update_cssds() {
cd $STEAMCMD
./steamcmd.sh +runscript "$HOME/etc/update_cssds.txt"
echo "--------------------------------------------------------------"
echo "CSS DS is up to date"
echo "--------------------------------------------------------------"
}
update_tf2ds() {
cd $STEAMCMD
./steamcmd.sh +runscript "$HOME/etc/update_tf2ds.txt"
echo "--------------------------------------------------------------"
echo "TF2 DS is up to date"
echo "--------------------------------------------------------------"
}
install_metamod() {
# is the metamod folder missing?
if [ ! -d "$CSTRIKE/addons/metamod" ]; then
LATESTMM=$(wget -qO- https://mms.alliedmods.net/mmsdrop/"${METAMOD_VERSION}"/mmsource-latest-linux)
wget -qO- https://mms.alliedmods.net/mmsdrop/"${METAMOD_VERSION}"/"${LATESTMM}" | tar xvzf - -C "$CSTRIKE"
echo "--------------------------------------------------------------"
echo "Installed MetaMod $METAMOD_VERSION"
echo "--------------------------------------------------------------"
fi
}
install_sourcemod() {
# Are we in a sourcemod container and is the sourcemod folder missing?
if [ ! -d "$CSTRIKE/addons/sourcemod" ]; then
LATESTSM=$(wget -qO- https://sm.alliedmods.net/smdrop/"${SOURCEMOD_VERSION}"/sourcemod-latest-linux)
wget -qO- https://sm.alliedmods.net/smdrop/"${SOURCEMOD_VERSION}"/"${LATESTSM}" | tar xvzf - -C "$CSTRIKE"
echo "--------------------------------------------------------------"
echo "Installed SourceMod $SOURCEMOD_VERSION"
echo "--------------------------------------------------------------"
fi
}
install_surf() {
cd $CSTRIKE
# Install Shavit BHopTimer (replaces InfluxTimer)
if [ ! -d "$CSTRIKE/addons/sourcemod/configs/shavit" ]; then
wget "https://github.com/shavitush/bhoptimer/releases/download/v4.0.1/bhoptimer-v4.0.1.zip"
unzip "bhoptimer-v4.0.1.zip"
rm "bhoptimer-v4.0.1.zip"
echo "--------------------------------------------------------------"
echo "Installed Shavit BHopTimer v4.0.1"
echo "--------------------------------------------------------------"
fi
# Install MomSurfFix
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/momsurffix2.smx" ]; then
wget "https://github.com/GAMMACASE/MomSurfFix/releases/download/1.1.5/MomSurfFix2v1.1.5.zip"
unzip "MomSurfFix2v1.1.5.zip"
rm "MomSurfFix2v1.1.5.zip"
echo "--------------------------------------------------------------"
echo "Installed MomSurfFix v1.1.5"
echo "--------------------------------------------------------------"
fi
# Install PushFix Definitive Edition
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/pushfix_de.smx" ]; then
wget "https://github.com/GAMMACASE/PushFixDE/releases/download/1.0.0/pushfix_de_1.0.0.zip"
unzip "pushfix_de_1.0.0.zip"
rm "pushfix_de_1.0.0.zip"
echo "--------------------------------------------------------------"
echo "Installed PushFix Definitive Edition v1.0.0"
echo "--------------------------------------------------------------"
fi
# Install EventQueue Fix
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/eventqueuefix.smx" ]; then
wget "https://github.com/hermansimensen/eventqueue-fix/releases/download/1.3.2/eventqueuefix-1.3.2.zip"
unzip "eventqueuefix-1.3.2.zip"
rm "eventqueuefix-1.3.2.zip"
echo "--------------------------------------------------------------"
echo "Installed EventQueue Fix v1.3.2"
echo "--------------------------------------------------------------"
fi
# Install RNGFix
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/rngfix.smx" ]; then
wget "https://github.com/jason-e/rngfix/releases/download/v1.1.3/rngfix_1.1.3.zip"
unzip "rngfix_1.1.3.zip"
rm "rngfix_1.1.3.zip"
echo "--------------------------------------------------------------"
echo "Installed RNGFix v1.1.3"
echo "--------------------------------------------------------------"
fi
}
configure_shavit_zones() {
cd $CSTRIKE
# Check if already configured
if [ -f "$CSTRIKE/addons/sourcemod/configs/shavit-mapfixes.cfg" ]; then
echo "--------------------------------------------------------------"
echo "Shavit zones already configured"
echo "--------------------------------------------------------------"
return
fi
echo "--------------------------------------------------------------"
echo "Configuring Shavit to use JSON zones from surf-zones repo"
echo "--------------------------------------------------------------"
# Download surf-zones repository
cd /tmp
wget "https://github.com/wrldspawn/surf-zones/archive/refs/heads/main.zip" -O surf-zones.zip
unzip -q surf-zones.zip
# Copy stripper directory
if [ -d "surf-zones-main/addons/stripper" ]; then
mkdir -p "$CSTRIKE/addons/stripper"
cp -r surf-zones-main/addons/stripper/* "$CSTRIKE/addons/stripper/"
echo "Copied stripper configurations"
fi
# Copy mapfixes configuration
if [ -f "surf-zones-main/addons/sourcemod/configs/shavit-mapfixes.cfg" ]; then
mkdir -p "$CSTRIKE/addons/sourcemod/configs"
cp surf-zones-main/addons/sourcemod/configs/shavit-mapfixes.cfg "$CSTRIKE/addons/sourcemod/configs/"
echo "Copied shavit-mapfixes.cfg"
fi
# Copy styles configuration (optional - removes irrelevant styles, matches KSF behavior)
if [ -f "surf-zones-main/addons/sourcemod/configs/shavit-styles.cfg" ]; then
cp surf-zones-main/addons/sourcemod/configs/shavit-styles.cfg "$CSTRIKE/addons/sourcemod/configs/"
echo "Copied shavit-styles.cfg"
fi
# Cleanup
rm -rf surf-zones-main surf-zones.zip
# Create cfg directory for plugin configs if it doesn't exist
mkdir -p "$CSTRIKE/cfg/sourcemod"
# Configure zones plugin to use JSON instead of SQL
cat > "$CSTRIKE/cfg/sourcemod/plugin.shavit-zones.cfg" <<'EOF'
// Shavit Zones Plugin Configuration
// Set to 0 to use JSON zones instead of SQL database
shavit_zones_usesql "0"
EOF
# Configure JSON zones URL
cat > "$CSTRIKE/cfg/sourcemod/plugin.shavit-zones-json.cfg" <<'EOF'
// Shavit JSON Zones Configuration
// URL template for loading zone data - {map} will be replaced with map name
shavit_zones_json_url "https://wrldspawn.github.io/surf-zones/z/{map}.json"
EOF
echo "--------------------------------------------------------------"
echo "Configured Shavit to use JSON zones"
echo "JSON URL: https://wrldspawn.github.io/surf-zones/z/{map}.json"
echo "Note: Use !setmaxvel in-game to set max velocity per map"
echo "--------------------------------------------------------------"
}
configure_shavit_database() {
cd $CSTRIKE
# Check if database config already exists
if [ -f "$CSTRIKE/addons/sourcemod/configs/databases.cfg" ]; then
# Check if shavit database entry already exists
if grep -q '"shavit"' "$CSTRIKE/addons/sourcemod/configs/databases.cfg"; then
echo "--------------------------------------------------------------"
echo "Shavit database already configured"
echo "--------------------------------------------------------------"
return
fi
fi
echo "--------------------------------------------------------------"
echo "Configuring Shavit database connection"
echo "--------------------------------------------------------------"
# Set defaults if environment variables are not set
DB_HOST="${MYSQL_HOST:-mariadb}"
DB_PORT="${MYSQL_PORT:-3306}"
DB_NAME="${MYSQL_DATABASE:-shavit}"
DB_USER="${MYSQL_USER:-root}"
DB_PASS="${MYSQL_ROOT_PASSWORD:-changeme}"
# Create or append to databases.cfg
mkdir -p "$CSTRIKE/addons/sourcemod/configs"
# If databases.cfg doesn't exist, create it with full structure
if [ ! -f "$CSTRIKE/addons/sourcemod/configs/databases.cfg" ]; then
cat > "$CSTRIKE/addons/sourcemod/configs/databases.cfg" <<EOF
"Databases"
{
"driver_default" "mysql"
// Shavit BHopTimer Database
"shavit"
{
"driver" "mysql"
"host" "$DB_HOST"
"port" "$DB_PORT"
"database" "$DB_NAME"
"user" "$DB_USER"
"pass" "$DB_PASS"
}
// Default SourceMod database (local SQLite)
"default"
{
"driver" "sqlite"
"database" "sourcemod-local"
}
// Storage database (can also use MySQL if desired)
"storage-local"
{
"driver" "sqlite"
"database" "sourcemod-local"
}
}
EOF
else
# Append shavit config to existing databases.cfg (before closing brace)
# Remove the last closing brace, add shavit config, then add closing brace back
sed -i '$ d' "$CSTRIKE/addons/sourcemod/configs/databases.cfg"
cat >> "$CSTRIKE/addons/sourcemod/configs/databases.cfg" <<EOF
// Shavit BHopTimer Database
"shavit"
{
"driver" "mysql"
"host" "$DB_HOST"
"port" "$DB_PORT"
"database" "$DB_NAME"
"user" "$DB_USER"
"pass" "$DB_PASS"
}
}
EOF
fi
echo "--------------------------------------------------------------"
echo "Configured Shavit database connection"
echo "Host: $DB_HOST:$DB_PORT"
echo "Database: $DB_NAME"
echo "User: $DB_USER"
echo "--------------------------------------------------------------"
}
copy_64bit() {
cp -a "$TF2DS/bin/linux64/libsteam_api.so" \
"$CSSDS/bin/linux64/."
cp -a "$TF2DS/srcds_linux64" "$TF2DS/srcds_run_64" \
"$CSSDS/."
}
symlink_binaries() {
cd "$CSSDS/bin/linux64"
for file in *_srv.so; do
echo "Symlinking \"$file\" to \"${file/_srv/}"
ln -nfs "$file" "${file/_srv/}"
done
}
steamclient_binary() {
echo "Looking for steamclient.so and symlinking it..."
local _steamclient64bit=$(find "$HOME" -type f -name 'steamclient.so' | grep "linux64" | head -n 1)
if [ ! -n $_steamclient64bit ]; then
echo "Could not locate 64-bit steamclient.so binary. Exiting..."
exit 1
fi
mkdir -p "$HOME/.steam/sdk64/" # srcds_linux64 looks for steamclient.so in this directory
ln -nfs "$_steamclient64bit" "$HOME/.steam/sdk64/steamclient.so"
ln -nfs "$_steamclient64bit" "$CSSDS/bin/linux64/steamclient.so"
}
cfg() {
cd
cp etc/cfg/server.cfg cssds/cstrike/cfg/
}
run_cssds() {
echo "ready to run"
cd "$CSSDS"
./srcds_run_64 -game cstrike \
-port "${SRCDS_PORT}" \
+maxplayers "${SRCDS_MAXPLAYERS}" \
+map "${SRCDS_STARTMAP}"
# -ip "${SRCDS_IP}"
}
main() {
update_cssds
update_tf2ds
copy_64bit
symlink_binaries
steamclient_binary
install_metamod
install_sourcemod
install_surf
configure_shavit_zones
configure_shavit_database
cfg
run_cssds
}
main
# sm plugins
# "vipmodel.smx" vipmodel.smx
# "Reserved Slots" (1.7.2) by AlliedModders LLC
# "ColoredText" (2.0) by unt0uch4bl3 for KSF use ONLY
# "Basic Ban Commands" (1.7.2) by AlliedModders LLC
# "Server Hop" (0.8.1) by [GRAVE] rig0r
# "PlayerTransmit" (1.0) by unt0uch
# "strippermodels.smx" strippermodels.smx
# "Whitelist" (1.0.0) by unt0uch4bl3
# "SMAC Anti-Speedhack" (0.8.0.9) by GoD-Tony
# "Player Commands" (1.4.0-dev) by AlliedModders LLC
# "sm_super_cmds_unt0uch.smx" sm_super_cmds_unt0uch.smx
# "Basic Chat" (1.7.2) by AlliedModders LLC
# "Admin File Reader" (1.7.2) by AlliedModders LLC
# "Name Change Punisher" (1.1) by Powerlord
# "Map Nominations" (1.7.2) by AlliedModders LLC
# "Stipper" (1.0) by unt0uch4bl3
# "No Block" (1.0.0.0) by sslice
# "Basic Votes" (1.7.2) by AlliedModders LLC
# "CMD Logger" (1.0.0) by unt0uch4bl3
# "Momentum surf fix '2" (1.1.5) by GAMMA CASE
# "Fun Commands" (1.4.0-dev) by AlliedModders LLC
# "Custom Votes" (0.5.6) by chundo
# "SurfTimer" (7.8.0) by unt0uch4bl3
# "Anti-Flood" (1.7.2) by AlliedModders LLC
# "EventQueue fix" (1.3.3) by carnifex
# "antibhop.smx" antibhop.smx
# "Basic Info Triggers" (1.4.2) by AlliedModders LLC
# "MapChooser" (1.7.2) by AlliedModders LLC
# "Admin Help" (1.4.0-dev) by AlliedModders LLC
# "Basic Respawn Plugin" (0.05) by Spyder
# "Rock The Vote" (1.7.2) by AlliedModders LLC
# "UrlOpen" (1.0) by unt0uch4bl3
# "Message Admin" by evolv
# "RandomCycle" (1.7.2) by AlliedModders LLC
# "PushFix - Definitive Edition" (1.1.0) by Original idea xutaxkamay | Implementation GAMMACASE
# "No-Jump Boost Fix" (1.0.0) by rio
# "Admin Menu" (1.7.2) by AlliedModders LLC
# "Client Preferences" (1.7.2) by AlliedModders LLC
# "Map configs" (1.1.1) by Berni
# "Nextmap" (1.5.1) by AlliedModders LLC
# "draw.smx" draw.smx
# "Player Trails" (3.0.2) by Twisted|Panda
# "Fun Votes" (1.7.2) by AlliedModders LLC
# "RNGFix" (1.1.3) by rio
# "SQL Admins (Threaded)" (1.7.2) by AlliedModders LLC
# "Surftimer Announcer" (1.0) by unt0uch4bl3
# "Basic Commands" (1.7.2) by AlliedModders LLC
# "DEMO Uploader" (1.0) by unt0uch4bl3
# "Players Votes" (1.5.0) by The Resident, pZv!
# "SMAC Command Monitor" (0.8.0.9) by GoD-Tony, psychonic, Kigen
# "Dissolve" (1.0.0.2) by L. Duke
# "SourceMod Anti-Cheat" (0.8.0.9) by GoD-Tony, psychonic
+268
View File
@@ -0,0 +1,268 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: surf
# -----------------------------------------------------------------------
# VOLUMES
# -----------------------------------------------------------------------
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cssds-data
namespace: surf
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: fastdl-maps
namespace: surf
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
# -----------------------------------------------------------------------
# ENV (create/update with: just env)
# -----------------------------------------------------------------------
# -----------------------------------------------------------------------
# CSSDS
# -----------------------------------------------------------------------
---
apiVersion: v1
kind: ConfigMap
metadata:
name: cfg
namespace: surf
data:
mapcycle.txt: |
surf_anzchamps
surf_boreas
surf_deathstar
surf_ebony
surf_fornax
surf_garden
surf_in_space
surf_kepler
surf_kitsune
surf_kitsune2
surf_lt_omnific
surf_pantheon
surf_utopia_njv
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: cssds
namespace: surf
spec:
replicas: 1
selector:
matchLabels:
app: cssds
template:
metadata:
labels:
app: cssds
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
initContainers:
- name: fix-permissions
image: busybox
securityContext:
runAsUser: 0
command: ['sh', '-c', 'chown -R 1000:1000 /home/steam/cssds']
volumeMounts:
- name: cssds-data
mountPath: /home/steam/cssds
containers:
- name: cssds
image: megastructure-surf-cssds:local
imagePullPolicy: Never
ports:
- containerPort: 27015
protocol: TCP
- containerPort: 27015
protocol: UDP
- containerPort: 27020
protocol: UDP
envFrom:
- secretRef:
name: surf
volumeMounts:
- name: src
mountPath: /home/steam/src
- name: cssds-data
mountPath: /home/steam/cssds
- name: fastdl-maps
mountPath: /fastdl/maps
readOnly: true
- name: cfg
mountPath: /home/steam/cfg
readOnly: true
volumes:
- name: src
hostPath:
path: /run/desktop/mnt/host/c/Users/ntr/code/surf_megastructure/src/cssds
- name: cssds-data
persistentVolumeClaim:
claimName: cssds-data
- name: fastdl-maps
persistentVolumeClaim:
claimName: fastdl-maps
- name: cfg
configMap:
name: cfg
---
apiVersion: v1
kind: Service
metadata:
name: cssds
namespace: surf
spec:
type: LoadBalancer
selector:
app: cssds
ports:
- name: game-tcp
protocol: TCP
port: 27015
targetPort: 27015
- name: game-udp
protocol: UDP
port: 27015
targetPort: 27015
- name: tv
protocol: UDP
port: 27020
targetPort: 27020
# -----------------------------------------------------------------------
# FASTDL
# -----------------------------------------------------------------------
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: fastdl
namespace: surf
spec:
replicas: 1
selector:
matchLabels:
app: fastdl
template:
metadata:
labels:
app: fastdl
spec:
containers:
- name: fastdl
image: megastructure-surf-fastdl:local
imagePullPolicy: Never
ports:
- containerPort: 80
volumeMounts:
- name: fastdl-maps
mountPath: /srv/maps
readOnly: true
volumes:
- name: fastdl-maps
persistentVolumeClaim:
claimName: fastdl-maps
---
apiVersion: v1
kind: Service
metadata:
name: fastdl
namespace: surf
spec:
type: LoadBalancer
selector:
app: fastdl
ports:
- name: http
port: 8080
targetPort: 80
# -----------------------------------------------------------------------
# MAP DOWNLOADER (run manually: kubectl apply, then delete when done)
# -----------------------------------------------------------------------
---
apiVersion: v1
kind: Pod
metadata:
name: mapsdl
namespace: surf
spec:
restartPolicy: Never
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: mapsdl
image: megastructure-surf-mapsdl:local
imagePullPolicy: Never
command: ["deno", "run", "-A", "mapsdl.ts"]
env:
- name: MAPS_DIR
value: "/maps"
- name: TEMP_DIR
value: "/tmp/mapsdl"
- name: GOOGLE_APPLICATION_CREDENTIALS
value: "/app/credentials/service-account.json"
- name: MAPS_LIST_FILE
value: "/cfg/mapcycle.txt"
volumeMounts:
- name: fastdl-maps
mountPath: /maps
- name: credentials
mountPath: /app/credentials
readOnly: true
- name: cfg
mountPath: /cfg
readOnly: true
volumes:
- name: fastdl-maps
persistentVolumeClaim:
claimName: fastdl-maps
- name: credentials
hostPath:
path: /run/desktop/mnt/host/c/Users/ntr/code/surf_megastructure/src/mapsdl/credentials
- name: cfg
configMap:
name: cfg
---
+14 -8
View File
@@ -6,30 +6,36 @@ EXPOSE 27015/tcp \
27020/udp
USER root
RUN apt-get update
RUN apt-get install -y \
RUN apt-get update && apt-get install -y \
wget \
ca-certificates \
zlib1g \
lib32z1 \
lib32gcc-s1 \
libncurses5 \
libbz2-1.0 \
libtinfo5 \
libcurl3-gnutls \
unzip \
rcon
bzip2 \
rcon \
neovim \
tmux \
less \
procps \
sqlite3 \
&& rm -rf /var/lib/apt/lists/*
ENV CSSDS="/home/steam/cssds"
ENV TF2DS="/home/steam/tf2ds"
ENV STEAMCMD="/home/steam/steamcmd"
ENV ETC="/home/steam/etc"
ENV SRC="/home/steam/src"
ENV METAMOD_VERSION=1.12
ENV SOURCEMOD_VERSION=1.12
# ensure gamedirs exist and have been chowned to steam
# before they potentially get setup as docker volumes
# which would otherwise cause them to be owned by root
RUN mkdir -p "$CSSDS" "$TF2DS" "$STEAMCMD" "$ETC"
RUN mkdir -p "$CSSDS" "$STEAMCMD" "$SRC"
RUN chown -R steam:steam /home/steam
FROM build AS steam
@@ -37,5 +43,5 @@ FROM build AS steam
USER steam
WORKDIR /home/steam
COPY . /home/steam/etc
CMD ["bash", "./etc/run.sh"]
COPY . /home/steam/src
CMD ["bash", "./src/run.sh"]
+2
View File
@@ -0,0 +1,2 @@
surf_fornax
surf_boreas
+32
View File
@@ -0,0 +1,32 @@
"MapLists"
{
"default"
{
"target" "mapcyclefile"
}
"sm_map menu"
{
"target" "mapcyclefile"
}
"sm_votemap menu"
{
"target" "mapcyclefile"
}
"randomcycle"
{
"target" "mapcyclefile"
}
"mapchooser"
{
"target" "mapcyclefile"
}
"nominations"
{
"target" "mapcyclefile"
}
}
+18
View File
@@ -0,0 +1,18 @@
<html>
<body style="background:#0a0a0a;color:#00ff88;font-family:monospace;padding:20px;">
<pre style="font-size:6px;line-height:1.1;">
███╗ ███╗███████╗ ██████╗ █████╗ ███████╗████████╗██████╗ ██╗ ██╗ ██████╗████████╗██╗ ██╗██████╗ ███████╗
████╗ ████║██╔════╝██╔════╝ ██╔══██╗██╔════╝╚══██╔══╝██╔══██╗██║ ██║██╔════╝╚══██╔══╝██║ ██║██╔══██╗██╔════╝
██╔████╔██║█████╗ ██║ ███╗███████║███████╗ ██║ ██████╔╝██║ ██║██║ ██║ ██║ ██║██████╔╝█████╗
██║╚██╔╝██║██╔══╝ ██║ ██║██╔══██║╚════██║ ██║ ██╔══██╗██║ ██║██║ ██║ ██║ ██║██╔══██╗██╔══╝
██║ ╚═╝ ██║███████╗╚██████╔╝██║ ██║███████║ ██║ ██║ ██║╚██████╔╝╚██████╗ ██║ ╚██████╔╝██║ ██║███████╗
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
███████╗██╗ ██╗██████╗ ███████╗
██╔════╝██║ ██║██╔══██╗██╔════╝
███████╗██║ ██║██████╔╝█████╗
╚════██║██║ ██║██╔══██╗██╔══╝
███████║╚██████╔╝██║ ██║██║
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝
</pre>
</body>
</html>
@@ -27,6 +27,8 @@ sv_accelerate_use_weapon_speed 0 // Weapon weight doesn't affect accelera
// Fall damage and movement
mp_falldamage 0 // No fall damage
sv_falldamage_to_velocity_scale 0 // Disable view punch/head knock from falls
sv_turbophysics 1 // Disable some physics effects (smoother movement)
phys_pushscale 1000 // Push force multiplier
// ================================================================
@@ -69,6 +71,11 @@ mp_idlemaxtime 0 // No idle kick (let Shavit handle this)
mp_idledealmethod 0 // Don't deal with idle players
sv_timeout 900 // 15 minute timeout
// HUD Settings (minimal HUD for clean surf experience)
sv_hudhint_sound 0 // Disable hint sounds
mp_radar_showall 0 // Hide radar
sv_showimpacts 0 // Hide bullet impacts
// ================================================================
// RCON SETTINGS
// ================================================================
+596
View File
@@ -0,0 +1,596 @@
#! /bin/bash
set -ue
# Parse command-line flags
# By default, skip updates (set to 1)
SKIP_CSSDS_UPDATE=1
while [[ $# -gt 0 ]]; do
case $1 in
--update-cssds)
SKIP_CSSDS_UPDATE=0
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--update-cssds]"
exit 1
;;
esac
done
CSTRIKE="$CSSDS/cstrike"
update_cssds() {
# Check if CSS DS is already populated with game files
if [ -f "$CSSDS/srcds_run" ]; then
# Game files exist, respect the skip flag
if [ $SKIP_CSSDS_UPDATE -eq 1 ]; then
echo "--------------------------------------------------------------"
echo "Skipping CSS DS update (use --update-cssds to enable)"
echo "--------------------------------------------------------------"
return
fi
else
echo "--------------------------------------------------------------"
echo "CSS DS not populated, performing initial installation"
echo "--------------------------------------------------------------"
fi
cd $STEAMCMD
./steamcmd.sh +runscript "$HOME/src/update_cssds.txt"
echo "--------------------------------------------------------------"
echo "CSS DS is up to date"
echo "--------------------------------------------------------------"
}
# TF2 DS no longer needed - running in 32-bit mode
# update_tf2ds() function removed
install_surf() {
cd $CSTRIKE
# is the metamod folder missing?
if [ ! -d "$CSTRIKE/addons/metamod" ]; then
LATESTMM=$(wget -qO- https://mms.alliedmods.net/mmsdrop/"${METAMOD_VERSION}"/mmsource-latest-linux)
wget -qO- https://mms.alliedmods.net/mmsdrop/"${METAMOD_VERSION}"/"${LATESTMM}" | tar xvzf - -C "$CSTRIKE"
echo "--------------------------------------------------------------"
echo "Installed MetaMod $METAMOD_VERSION"
echo "--------------------------------------------------------------"
fi
# Are we in a sourcemod container and is the sourcemod folder missing?
if [ ! -d "$CSTRIKE/addons/sourcemod" ]; then
LATESTSM=$(wget -qO- https://sm.alliedmods.net/smdrop/"${SOURCEMOD_VERSION}"/sourcemod-latest-linux)
wget -qO- https://sm.alliedmods.net/smdrop/"${SOURCEMOD_VERSION}"/"${LATESTSM}" | tar xvzf - -C "$CSTRIKE"
echo "--------------------------------------------------------------"
echo "Installed SourceMod $SOURCEMOD_VERSION"
echo "--------------------------------------------------------------"
fi
# Install sm_closestpos (required for ghost/replay functionality)
if [ ! -f "$CSTRIKE/addons/sourcemod/extensions/closestpos.ext.so" ]; then
cd /tmp
wget "https://github.com/rtldg/sm_closestpos/releases/download/v1.1.1/sm_closestpos-sm1.10-ubuntu-20.04-b0a9b88.zip"
unzip -o "sm_closestpos-sm1.10-ubuntu-20.04-b0a9b88.zip"
cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
rm -rf "sm_closestpos-sm1.10-ubuntu-20.04-b0a9b88.zip" addons/
echo "--------------------------------------------------------------"
echo "Installed sm_closestpos v1.1.1"
echo "--------------------------------------------------------------"
else
echo "--------------------------------------------------------------"
echo "sm_closestpos already installed"
echo "--------------------------------------------------------------"
fi
# Install sm-ripext (required for shavit-wrsh plugin)
if [ ! -f "$CSTRIKE/addons/sourcemod/extensions/rip.ext.so" ]; then
cd /tmp
wget "https://github.com/ErikMinekus/sm-ripext/releases/download/1.3.2/sm-ripext-1.3.2-linux.zip"
unzip -o "sm-ripext-1.3.2-linux.zip"
cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
rm -rf "sm-ripext-1.3.2-linux.zip" addons/
echo "--------------------------------------------------------------"
echo "Installed sm-ripext v1.3.2"
echo "--------------------------------------------------------------"
else
echo "--------------------------------------------------------------"
echo "sm-ripext already installed"
echo "--------------------------------------------------------------"
fi
# Install Shavit Surf Timer (surf-specific fork)
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/shavit-core.smx" ]; then
cd /tmp
wget "https://github.com/bhopppp/Shavit-Surf-Timer/releases/download/v1.0.6/Shavit-SurfTimer-v1.0.6.zip"
unzip -o "Shavit-SurfTimer-v1.0.6.zip"
# Copy addons, sounds, and materials
cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
cp -r sound/* "$CSTRIKE/sound/" 2>/dev/null || true
cp -r materials/* "$CSTRIKE/materials/" 2>/dev/null || true
rm -rf "Shavit-SurfTimer-v1.0.6.zip" addons/ sound/ materials/
echo "--------------------------------------------------------------"
echo "Installed Shavit Surf Timer v1.0.6 (with sounds & materials)"
echo "--------------------------------------------------------------"
else
echo "--------------------------------------------------------------"
echo "Shavit Surf Timer already installed"
echo "--------------------------------------------------------------"
fi
# Temporarily disabled - testing SQL zones instead of JSON
# Install shavit-zones-json from original bhoptimer (missing in Surf Timer release)
# if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/shavit-zones-json.smx" ]; then
# cd /tmp
# wget "https://github.com/shavitush/bhoptimer/releases/download/v4.0.1/bhoptimer-v4.0.1.zip"
# unzip -o "bhoptimer-v4.0.1.zip" "addons/sourcemod/plugins/shavit-zones-json.smx"
# cp addons/sourcemod/plugins/shavit-zones-json.smx "$CSTRIKE/addons/sourcemod/plugins/"
# rm -rf "bhoptimer-v4.0.1.zip" addons/
# echo "--------------------------------------------------------------"
# echo "Installed shavit-zones-json.smx from bhoptimer v4.0.1"
# echo "--------------------------------------------------------------"
# else
# echo "--------------------------------------------------------------"
# echo "shavit-zones-json already installed"
# echo "--------------------------------------------------------------"
# fi
# Disable zones-json plugin if it exists
if [ -f "$CSTRIKE/addons/sourcemod/plugins/shavit-zones-json.smx" ]; then
mkdir -p "$CSTRIKE/addons/sourcemod/plugins/disabled"
mv "$CSTRIKE/addons/sourcemod/plugins/shavit-zones-json.smx" \
"$CSTRIKE/addons/sourcemod/plugins/disabled/" 2>/dev/null || true
echo "--------------------------------------------------------------"
echo "Disabled shavit-zones-json (using SQL zones instead)"
echo "--------------------------------------------------------------"
fi
# Disable shavit-sounds plugin
if [ -f "$CSTRIKE/addons/sourcemod/plugins/shavit-sounds.smx" ]; then
mkdir -p "$CSTRIKE/addons/sourcemod/plugins/disabled"
mv "$CSTRIKE/addons/sourcemod/plugins/shavit-sounds.smx" \
"$CSTRIKE/addons/sourcemod/plugins/disabled/" 2>/dev/null || true
echo "--------------------------------------------------------------"
echo "Disabled shavit-sounds"
echo "--------------------------------------------------------------"
fi
# Install MomSurfFix
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/momsurffix2.smx" ]; then
cd /tmp
wget "https://github.com/GAMMACASE/MomSurfFix/releases/download/1.1.5/MomSurfFix2v1.1.5.zip"
unzip -o "MomSurfFix2v1.1.5.zip"
cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
rm -rf "MomSurfFix2v1.1.5.zip" addons/
echo "--------------------------------------------------------------"
echo "Installed MomSurfFix v1.1.5"
echo "--------------------------------------------------------------"
else
echo "--------------------------------------------------------------"
echo "MomSurfFix already installed"
echo "--------------------------------------------------------------"
fi
# PushFix Definitive Edition - appears in KSF plugin list but fails on CSS
# The DE version is CS:GO only and will fail with "g_SendTableCRC" error on CSS
# Disabled by default - if KSF uses a different version, it's not publicly available
# if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/pushfix_de.smx" ]; then
# cd /tmp
# wget "https://github.com/GAMMACASE/PushFixDE/releases/download/1.0.0/pushfix_de_1.0.0.zip"
# unzip -o "pushfix_de_1.0.0.zip"
# cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
# rm -rf "pushfix_de_1.0.0.zip" addons/
# fi
# Install EventQueue Fix
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/eventqueuefix.smx" ]; then
cd /tmp
wget "https://github.com/hermansimensen/eventqueue-fix/releases/download/1.3.2/eventqueuefix-1.3.2.zip"
unzip -o "eventqueuefix-1.3.2.zip"
cp -r addons/* "$CSTRIKE/addons/" 2>/dev/null || true
rm -rf "eventqueuefix-1.3.2.zip" addons/
echo "--------------------------------------------------------------"
echo "Installed EventQueue Fix v1.3.2"
echo "--------------------------------------------------------------"
else
echo "--------------------------------------------------------------"
echo "EventQueue Fix already installed"
echo "--------------------------------------------------------------"
fi
# Install RNGFix
if [ ! -f "$CSTRIKE/addons/sourcemod/plugins/rngfix.smx" ]; then
cd /tmp
wget "https://github.com/jason-e/rngfix/releases/download/v1.1.3/rngfix_1.1.3.zip"
unzip -o "rngfix_1.1.3.zip"
cp -r rngfix_1.1.3/* "$CSTRIKE/addons/sourcemod/" 2>/dev/null || true
rm -rf "rngfix_1.1.3.zip" rngfix_1.1.3/
echo "--------------------------------------------------------------"
echo "Installed RNGFix v1.1.3"
echo "--------------------------------------------------------------"
else
echo "--------------------------------------------------------------"
echo "RNGFix already installed"
echo "--------------------------------------------------------------"
fi
}
configure_shavit_zones() {
cd $CSTRIKE
# Check if already configured
if [ -f "$CSTRIKE/addons/sourcemod/configs/shavit-mapfixes.cfg" ]; then
echo "--------------------------------------------------------------"
echo "Shavit zones already configured"
echo "--------------------------------------------------------------"
return
fi
echo "--------------------------------------------------------------"
echo "Configuring Shavit to use JSON zones from surf-zones repo"
echo "--------------------------------------------------------------"
# Download surf-zones repository
cd /tmp
wget "https://github.com/wrldspawn/surf-zones/archive/refs/heads/main.zip" -O surf-zones.zip
unzip -o surf-zones.zip
# Copy stripper directory
if [ -d "surf-zones-main/addons/stripper" ]; then
mkdir -p "$CSTRIKE/addons/stripper"
cp -r surf-zones-main/addons/stripper/* "$CSTRIKE/addons/stripper/"
echo "Copied stripper configurations"
fi
# Copy mapfixes configuration
if [ -f "surf-zones-main/addons/sourcemod/configs/shavit-mapfixes.cfg" ]; then
mkdir -p "$CSTRIKE/addons/sourcemod/configs"
cp surf-zones-main/addons/sourcemod/configs/shavit-mapfixes.cfg "$CSTRIKE/addons/sourcemod/configs/"
echo "Copied shavit-mapfixes.cfg"
fi
# Copy styles configuration (optional - removes irrelevant styles, matches KSF behavior)
if [ -f "surf-zones-main/addons/sourcemod/configs/shavit-styles.cfg" ]; then
cp surf-zones-main/addons/sourcemod/configs/shavit-styles.cfg "$CSTRIKE/addons/sourcemod/configs/"
echo "Copied shavit-styles.cfg"
fi
# Cleanup
rm -rf surf-zones-main surf-zones.zip
# Create cfg directory for plugin configs if it doesn't exist
mkdir -p "$CSTRIKE/cfg/sourcemod"
# Configure zones plugin to use SQL database
cat > "$CSTRIKE/cfg/sourcemod/plugin.shavit-zones.cfg" <<'EOF'
// Shavit Zones Plugin Configuration
// Set to 1 to use SQL zones (default for Surf Timer fork)
shavit_zones_usesql "1"
EOF
# Configure mapchooser to allow all maps from disk
cat > "$CSTRIKE/cfg/sourcemod/plugin.shavit-mapchooser.cfg" <<'EOF'
// 0 = zoned maps from database, 1 = maplist.txt, 2 = maps folder
smc_maplist_type "2"
EOF
# JSON zones temporarily disabled for testing
# cat > "$CSTRIKE/cfg/sourcemod/plugin.shavit-zones-json.cfg" <<'EOF'
# // Shavit JSON Zones Configuration
# // URL template for loading zone data - {map} will be replaced with map name
# shavit_zones_json_url "https://wrldspawn.github.io/surf-zones/z/{map}.json"
# EOF
echo "--------------------------------------------------------------"
echo "Configured Shavit to use SQL zones"
echo "Use !zones in-game to create start/end zones for maps"
echo "--------------------------------------------------------------"
}
configure_shavit_database() {
cd $CSTRIKE
echo "--------------------------------------------------------------"
echo "Writing Shavit database configuration (SQLite)"
echo "--------------------------------------------------------------"
# Always recreate databases.cfg
mkdir -p "$CSTRIKE/addons/sourcemod/configs"
cat > "$CSTRIKE/addons/sourcemod/configs/databases.cfg" <<'EOF'
"Databases"
{
"driver_default" "sqlite"
// Shavit BHopTimer Database (using local SQLite)
"shavit"
{
"driver" "sqlite"
"database" "shavit-local"
}
// Default SourceMod database (local SQLite)
"default"
{
"driver" "sqlite"
"database" "sourcemod-local"
}
// Storage database (local SQLite)
"storage-local"
{
"driver" "sqlite"
"database" "sourcemod-local"
}
}
EOF
echo "--------------------------------------------------------------"
echo "Configured Shavit to use local SQLite database"
echo "Database: shavit-local.sq3"
echo "--------------------------------------------------------------"
}
import_zone_data() {
echo "--------------------------------------------------------------"
echo "Importing zone data from Surf Timer repository"
echo "--------------------------------------------------------------"
local DB_FILE="$CSTRIKE/addons/sourcemod/data/sqlite/shavit-local.sq3"
# Check if database file exists
if [ ! -f "$DB_FILE" ]; then
echo "Database file not created yet - skipping zone import"
echo "Zones will be imported on next restart after Shavit creates tables"
echo "--------------------------------------------------------------"
return
fi
# Check if Shavit migrations have run (mapzones table must exist)
local table_exists=$(sqlite3 "$DB_FILE" "SELECT name FROM sqlite_master WHERE type='table' AND name='mapzones';" 2>/dev/null)
if [ -z "$table_exists" ]; then
echo "Shavit has not created tables yet - skipping zone import"
echo "Zones will be imported on next restart after Shavit runs migrations"
echo "--------------------------------------------------------------"
return
fi
# Check if zones already imported
local zone_count=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM mapzones;" 2>/dev/null || echo "0")
if [ "$zone_count" -gt "0" ]; then
echo "Zone data already imported ($zone_count zones)"
echo "--------------------------------------------------------------"
return
fi
# Download and import surfzones.sql
cd /tmp
wget -q "https://raw.githubusercontent.com/bhopppp/Shavit-Surf-Timer/master/sql/surfzones.sql" -O surfzones.sql
sqlite3 "$DB_FILE" < surfzones.sql 2>/dev/null
local imported_count=$(sqlite3 "$DB_FILE" "SELECT COUNT(*) FROM mapzones;" 2>/dev/null || echo "unknown")
echo "Imported $imported_count zones from surfzones.sql"
rm -f surfzones.sql
echo "--------------------------------------------------------------"
}
copy_64bit() {
cp -a "$TF2DS/bin/linux64/libsteam_api.so" \
"$CSSDS/bin/linux64/"
cp -a "$TF2DS/srcds_linux64" "$TF2DS/srcds_run_64" \
"$CSSDS/"
}
symlink_binaries() {
cd "$CSSDS/bin/linux64"
for file in *_srv.so; do
echo "Symlinking \"$file\" to \"${file/_srv/}"
ln -nfs "$file" "${file/_srv/}"
done
}
steamclient_binary() {
echo "Looking for steamclient.so and symlinking it..."
# For 32-bit mode, look for 32-bit steamclient (linux32 or default)
local _steamclient32bit=$(find "$HOME" -type f -name 'steamclient.so' | grep -E "linux32|steamcmd/linux32" | head -n 1)
if [ ! -n "$_steamclient32bit" ]; then
# Fallback to any steamclient.so if linux32 not found
_steamclient32bit=$(find "$HOME" -type f -name 'steamclient.so' | head -n 1)
fi
if [ ! -n "$_steamclient32bit" ]; then
echo "Could not locate steamclient.so binary. Exiting..."
exit 1
fi
mkdir -p "$HOME/.steam/sdk32/" # srcds_run looks for steamclient.so in this directory
ln -nfs "$_steamclient32bit" "$HOME/.steam/sdk32/steamclient.so"
ln -nfs "$_steamclient32bit" "$CSSDS/steamclient.so"
}
configure_admins() {
echo "--------------------------------------------------------------"
echo "Configuring SourceMod admins"
echo "--------------------------------------------------------------"
local ADMINS_INI="$CSTRIKE/addons/sourcemod/configs/admins_simple.ini"
if [ -z "${SRCDS_ADMINS:-}" ]; then
echo "No admins configured (set SRCDS_ADMINS env var)"
echo "--------------------------------------------------------------"
return
fi
: > "$ADMINS_INI"
IFS=',' read -ra ADMIN_IDS <<< "$SRCDS_ADMINS"
for steamid in "${ADMIN_IDS[@]}"; do
steamid=$(echo "$steamid" | tr -d '"' | tr -d "'" | tr -d ' ')
if [ -n "$steamid" ]; then
echo "\"$steamid\" \"99:z\"" >> "$ADMINS_INI"
echo "Added admin: $steamid"
fi
done
echo "--------------------------------------------------------------"
echo "Configured ${#ADMIN_IDS[@]} admin(s)"
echo "--------------------------------------------------------------"
}
cfg() {
cd
cp src/cfg/server.cfg cssds/cstrike/cfg/
cp src/cfg/motd.txt cssds/cstrike/
cp src/cfg/maplists.cfg cssds/cstrike/addons/sourcemod/configs/maplists.cfg
cp cfg/mapcycle.txt cssds/cstrike/cfg/
cp cfg/mapcycle.txt cssds/cstrike/addons/sourcemod/configs/adminmenu_maplist.ini
sed -i "s|sv_downloadurl .*|sv_downloadurl \"${FASTDL_URL:-}/cstrike/\"|" "$CSTRIKE/cfg/server.cfg"
sed -i "s|rcon_password .*|rcon_password \"${SRCDS_RCONPW:-changeme}\"|" "$CSTRIKE/cfg/server.cfg"
}
populate_maps() {
local BZ2_DIR="/fastdl/maps"
local MAPS_DIR="$CSTRIKE/maps"
local MAPCYCLE="$CSTRIKE/cfg/mapcycle.txt"
echo "--------------------------------------------------------------"
echo "Populating maps from compressed archive"
echo "--------------------------------------------------------------"
if [ ! -f "$MAPCYCLE" ]; then
echo "No mapcycle.txt found, skipping map population"
echo "--------------------------------------------------------------"
return
fi
mkdir -p "$MAPS_DIR"
local total=0 skipped=0 extracted=0 missing=0
while IFS= read -r line || [ -n "$line" ]; do
# skip empty lines and comments
line=$(echo "$line" | sed 's|//.*||' | xargs)
[ -z "$line" ] && continue
total=$((total + 1))
local bz2="$BZ2_DIR/${line}.bsp.bz2"
local bsp="$MAPS_DIR/${line}.bsp"
if [ -f "$bsp" ]; then
skipped=$((skipped + 1))
continue
fi
if [ ! -f "$bz2" ]; then
missing=$((missing + 1))
echo " [!] ${line}: not in fastdl volume"
continue
fi
bunzip2 -c "$bz2" > "$bsp"
extracted=$((extracted + 1))
done < "$MAPCYCLE"
echo "Maps: $total in mapcycle, $extracted extracted, $skipped already present, $missing not available"
echo "--------------------------------------------------------------"
}
run_cssds() {
cd "$CSSDS"
local startmap="${SRCDS_STARTMAP:-}"
if [ -z "$startmap" ]; then
startmap=$(grep -v '^\s*\/\/' "$CSTRIKE/cfg/mapcycle.txt" | grep -m1 '\S')
fi
./srcds_run -game cstrike \
-port "${SRCDS_PORT}" \
+sv_setsteamaccount "${SRCDS_TOKEN}" \
+maxplayers "${SRCDS_MAXPLAYERS}" \
+map "$startmap" \
-ip "${SRCDS_IP}"
}
main() {
update_cssds
# TF2 DS not needed - running in 32-bit mode
steamclient_binary
install_surf
configure_shavit_zones
configure_shavit_database
configure_admins
cfg
# Import zone data after server config is ready
# Note: Database might not exist yet on first run
# Zones will be available after server starts and creates tables
import_zone_data
populate_maps
run_cssds
}
main
# sm plugins
# "vipmodel.smx" vipmodel.smx
# "Reserved Slots" (1.7.2) by AlliedModders LLC
# "ColoredText" (2.0) by unt0uch4bl3 for KSF use ONLY
# "Basic Ban Commands" (1.7.2) by AlliedModders LLC
# "Server Hop" (0.8.1) by [GRAVE] rig0r
# "PlayerTransmit" (1.0) by unt0uch
# "strippermodels.smx" strippermodels.smx
# "Whitelist" (1.0.0) by unt0uch4bl3
# "SMAC Anti-Speedhack" (0.8.0.9) by GoD-Tony
# "Player Commands" (1.4.0-dev) by AlliedModders LLC
# "sm_super_cmds_unt0uch.smx" sm_super_cmds_unt0uch.smx
# "Basic Chat" (1.7.2) by AlliedModders LLC
# "Admin File Reader" (1.7.2) by AlliedModders LLC
# "Name Change Punisher" (1.1) by Powerlord
# "Map Nominations" (1.7.2) by AlliedModders LLC
# "Stipper" (1.0) by unt0uch4bl3
# "No Block" (1.0.0.0) by sslice
# "Basic Votes" (1.7.2) by AlliedModders LLC
# "CMD Logger" (1.0.0) by unt0uch4bl3
# "Momentum surf fix '2" (1.1.5) by GAMMA CASE
# "Fun Commands" (1.4.0-dev) by AlliedModders LLC
# "Custom Votes" (0.5.6) by chundo
# "SurfTimer" (7.8.0) by unt0uch4bl3
# "Anti-Flood" (1.7.2) by AlliedModders LLC
# "EventQueue fix" (1.3.3) by carnifex
# "antibhop.smx" antibhop.smx
# "Basic Info Triggers" (1.4.2) by AlliedModders LLC
# "MapChooser" (1.7.2) by AlliedModders LLC
# "Admin Help" (1.4.0-dev) by AlliedModders LLC
# "Basic Respawn Plugin" (0.05) by Spyder
# "Rock The Vote" (1.7.2) by AlliedModders LLC
# "UrlOpen" (1.0) by unt0uch4bl3
# "Message Admin" by evolv
# "RandomCycle" (1.7.2) by AlliedModders LLC
# "PushFix - Definitive Edition" (1.1.0) by Original idea xutaxkamay | Implementation GAMMACASE
# "No-Jump Boost Fix" (1.0.0) by rio
# "Admin Menu" (1.7.2) by AlliedModders LLC
# "Client Preferences" (1.7.2) by AlliedModders LLC
# "Map configs" (1.1.1) by Berni
# "Nextmap" (1.5.1) by AlliedModders LLC
# "draw.smx" draw.smx
# "Player Trails" (3.0.2) by Twisted|Panda
# "Fun Votes" (1.7.2) by AlliedModders LLC
# "RNGFix" (1.1.3) by rio
# "SQL Admins (Threaded)" (1.7.2) by AlliedModders LLC
# "Surftimer Announcer" (1.0) by unt0uch4bl3
# "Basic Commands" (1.7.2) by AlliedModders LLC
# "DEMO Uploader" (1.0) by unt0uch4bl3
# "Players Votes" (1.5.0) by The Resident, pZv!
# "SMAC Command Monitor" (0.8.0.9) by GoD-Tony, psychonic, Kigen
# "Dissolve" (1.0.0.2) by L. Duke
# "SourceMod Anti-Cheat" (0.8.0.9) by GoD-Tony, psychonic
File renamed without changes.
File renamed without changes.
+2
View File
@@ -0,0 +1,2 @@
FROM nginx:alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
+8
View File
@@ -0,0 +1,8 @@
server {
listen 80;
root /srv;
location /cstrike/maps/ {
alias /srv/maps/;
autoindex off;
}
}
+812
View File
@@ -0,0 +1,812 @@
// ______________________
//___________.( h0lmGUI™v4.1 by h0lm ).___________
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
///////////////////////////////////////////////////////////
// Object Control Panel scheme resource file
//
// sections:
// Colors - all the colors used by the scheme
// BaseSettings - contains settings for app to use to draw controls
// Fonts - list of all the fonts used by app
// Borders - description of all the borders
//
// hit ctrl-alt-shift-R in the app to reload this file
//
///////////////////////////////////////////////////////////
Scheme
{
//////////////////////// COLORS ///////////////////////////
// color details
// this is a list of all the colors used by the scheme
Colors
{
// base colors
//"BaseText" "48 192 192 255" // used in text windows, lists
//"BrightBaseText" "155 255 255 255" // brightest text
"BaseText" "220 30 30 255"
"BrightBaseText" "255 0 0 255"
"DimBaseText" "220 30 30 255" // dim base text
"LabelDimText" "220 30 30 255" // slight modification on above, used for info text
// could be just removed and use DimBaseText?
"ControlText" "48 192 192 255" // used in all text controls
"BrightControlText" "64 224 224 255" // use for selected controls
"DisabledText1" "32 128 128 255" // disabled text
"DisabledText2" "30 30 30 255" // overlay color for disabled text (to give that inset look)
// background colors
"ControlBG" "76 88 68 255" // background color of controls
"ControlDarkBG" "90 106 80 255" // darker background color; used for background of scrollbars
"WindowBG" "62 70 55 255" // background color of text edit panes (chat, text entries, etc.)
"SelectionBG" "76 88 68 255" // background color of any selected text or menu item
// title colors
"TitleText" "255 255 255 255"
"TitleDimText" "120 132 114 255"
"TitleBG" "76 88 68 0"
"TitleDimBG" "76 88 68 0"
// border colors
"BorderBright" "136 145 128 255" // the lit side of a control
"BorderDark" "45 49 40 255" // the dark/unlit side of a control
"BorderSelection" "0 0 0 255" // the additional border color for displaying the default/selected button
"C4Panel_Armed" "0 128 255 200"
"C4Panel_Defused" "0 255 0 200"
}
///////////////////// BASE SETTINGS ////////////////////////
//
// default settings for all panels
// controls use these to determine their settings
BaseSettings
{
Panel.FgColor "48 192 192 255"
Panel.BgColor "0 0 0 0" //Important! - makes the panels transparent
"FgColor" "ControlText"
"BgColor" "ControlBG"
"LabelBgColor" "ControlBG"
"SubPanelBgColor" "ControlBG"
"DisabledFgColor1" "DisabledText1"
"DisabledFgColor2" "DisabledText2" // set this to the BgColor if you don't want it to draw
"TitleBarFgColor" "TitleText"
"TitleBarDisabledFgColor" "TitleDimText"
"TitleBarBgColor" "TitleBG"
"TitleBarDisabledBgColor" "TitleDimBG"
// "TitleBarIcon" "resource/icon_steam"
// "TitleBarDisabledIcon" "resource/icon_steam_disabled"
"TitleBarIcon" "resource/icon_hlicon1"
"TitleBarDisabledIcon" "resource/icon_hlicon2"
"TitleButtonFgColor" "BorderBright"
"TitleButtonBgColor" "ControlBG"
"TitleButtonDisabledFgColor" "TitleDimText"
"TitleButtonDisabledBgColor" "TitleDimBG"
"TextCursorColor" "BaseText" // color of the blinking text cursor in text entries
"URLTextColor" "BrightBaseText" // color that URL's show up in chat window
Menu
{
"FgColor" "DimBaseText"
"BgColor" "ControlBG"
"ArmedFgColor" "BrightBaseText"
"ArmedBgColor" "SelectionBG"
"DividerColor" "BorderDark"
"TextInset" "6"
}
MenuButton // the little arrow on the side of boxes that triggers drop down menus
{
"ButtonArrowColor" "DimBaseText" // color of arrows
"ButtonBgColor" "WindowBG" // bg color of button. same as background color of text edit panes
"ArmedArrowColor" "BrightBaseText" // color of arrow when mouse is over button
"ArmedBgColor" "DimBaseText" // bg color of button when mouse is over button
}
Slider
{
"SliderFgColor" "ControlText" // handle with which the slider is grabbed
"SliderBgColor" "ControlDarkBG" // area behind handle
"SliderTickColor" "ControlText" // slider tick's color
"SliderTickLabelColor" "ControlText" // color of labels at the ends of the slider tick
}
ScrollBarSlider
{
"BgColor" "ControlBG" // this isn't really used
"ScrollBarSliderFgColor" "ControlBG" // handle with which the slider is grabbed
"ScrollBarSliderBgColor" "ControlDarkBG" // area behind handle
"ButtonFgColor" "DimBaseText" // color of arrows
}
// text edit windows
"WindowFgColor" "BaseText" // off-white
"WindowBgColor" "WindowBG"
"WindowDisabledFgColor" "DimBaseText"
"WindowDisabledBgColor" "66 80 60 255" // background of chat conversation
"SelectionFgColor" "255 255 255 255" // fg color of selected text
"SelectionBgColor" "SelectionBG"
"ListSelectionFgColor" "255 255 255 255" //
"ListBgColor" "62 70 55 255" // background of server browser control, etc
"BuddyListBgColor" "62 70 55 255" // background of buddy list pane
// App-specific stuff
"ChatBgColor" "WindowBgColor"
// status selection
"StatusSelectFgColor" "BrightBaseText"
"StatusSelectFgColor2" "BrightControlText" // this is the color of the friends status
// checkboxes
"CheckButtonBorder1" "BorderDark" // the left checkbutton border
"CheckButtonBorder2" "BorderBright" // the right checkbutton border
"CheckButtonCheck" "0 0 0 255" // color of the check itself
"CheckBgColor" "158 168 150 255"
// buttons (default fg/bg colors are used if these are not set)
// "ButtonArmedFgColor"
// "ButtonArmedBgColor"
// "ButtonDepressedFgColor" "BrightControlText"
// "ButtonDepressedBgColor"
// buddy buttons
BuddyButton
{
"FgColor1" "ControlText"
"FgColor2" "117 134 102 255"
"ArmedFgColor1" "BrightBaseText"
"ArmedFgColor2" "BrightBaseText"
"ArmedBgColor" "SelectionBG"
}
Chat
{
"TextColor" "BrightControlText"
"SelfTextColor" "BaseText"
"SeperatorTextColor" "DimBaseText"
}
"SectionTextColor" "BrightControlText" // text color for IN-GAME, ONLINE, OFFLINE sections of buddy list
"SectionDividerColor" "BorderDark" // color of line that runs under section name in buddy list
}
//
//////////////////////// FONTS /////////////////////////////
//
// describes all the fonts
Fonts
{
// fonts are used in order that they are listed
// fonts listed later in the order will only be used if they fulfill a range not already filled
// if a font fails to load then the subsequent fonts will replace
"Default"
{
"1"
{
"name" "Dead Kansas"
"tall" "45" //45
"weight" "600" //900
"range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
"antialias" "1"
}
}
"DefaultUnderline"
{
"1"
{
"name" "Impact"
"tall" "32"
"weight" "900"
"underline" "1"
"range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
}
}
"DefaultSmall"
{
"1"
{
"name" "Impact"
"tall" "24"
"weight" "900"
"range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
}
}
"DefaultVerySmall"
{
"1"
{
"name" "Impact"
"tall" "18"
"weight" "900"
"range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
}
}
"DefaultLarge"
{
"1"
{
"name" "Impact"
"tall" "48"
"weight" "0"
"range" "0x0000 0x017F" // Basic Latin, Latin-1 Supplement, Latin Extended-A
}
}
// this is the symbol font
"Marlett"
{
"1"
{
"name" "Marlett"
"tall" "14"
"weight" "0"
"symbol" "1"
"range" "0x0000 0x007F" // Basic Latin
}
}
}
//
//////////////////// BORDERS //////////////////////////////
//
// describes all the border types
Borders
{
BaseBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BorderDark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderBright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
}
TitleButtonBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Top
{
"4"
{
"color" "BorderBright"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
}
TitleButtonDisabledBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BgColor"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BgColor"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BgColor"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BgColor"
"offset" "0 0"
}
}
}
TitleButtonDepressedBorder
{
"inset" "1 1 1 1"
Left
{
"1"
{
"color" "BorderDark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderBright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
}
ScrollBarButtonBorder
{
"inset" "2 2 0 0"
Left
{
"1"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
}
ButtonBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Top
{
"1"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Bottom
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
}
TabBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
}
TabActiveBorder
{
"inset" "0 0 1 0"
Left
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "ControlBG"
"offset" "6 2"
}
}
}
ToolTipBorder
{
"inset" "0 0 1 0"
Left
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
}
// this is the border used for default buttons (the button that gets pressed when you hit enter)
ButtonKeyFocusBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BorderSelection"
"offset" "0 0"
}
"2"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Top
{
"1"
{
"color" "BorderSelection"
"offset" "0 0"
}
"2"
{
"color" "BorderBright"
"offset" "1 0"
}
}
Right
{
"1"
{
"color" "BorderSelection"
"offset" "0 0"
}
"2"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Bottom
{
"1"
{
"color" "BorderSelection"
"offset" "0 0"
}
"2"
{
"color" "BorderDark"
"offset" "0 0"
}
}
}
ButtonDepressedBorder
{
"inset" "2 1 1 1"
Left
{
"1"
{
"color" "BorderDark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderBright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
}
ComboBoxBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "BorderDark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderBright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
}
MenuBorder
{
"inset" "1 1 1 1"
Left
{
"1"
{
"color" "BorderBright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "BorderDark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "BorderBright"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "BorderDark"
"offset" "0 0"
}
}
}
}
}
//________________________________________________
//¯¯¯¯¯¯¯¯¯¯¯'( h0lmGUI™v4.1 by h0lm )'¯¯¯¯¯¯¯¯¯¯¯
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+755
View File
@@ -0,0 +1,755 @@
///////////////////////////////////////////////////////////
// Tracker scheme resource file
//
// sections:
// Colors - all the colors used by the scheme
// BaseSettings - contains settings for app to use to draw controls
// Fonts - list of all the fonts used by app
// Borders - description of all the borders
//
///////////////////////////////////////////////////////////
Scheme
{
//////////////////////// COLORS ///////////////////////////
// color details
// this is a list of all the colors used by the scheme
Colors
{
// base colors
"White" "255 255 255 255"
"OffWhite" "216 216 216 255"
"DullWhite" "0 0 0 0"
"Orange" "255 110 0 255"
"TransparentBlack" "0 0 0 0"
"Black" "0 0 0 255"
"Blank" "0 0 0 0"
}
///////////////////// BASE SETTINGS ////////////////////////
//
// default settings for all panels
// controls use these to determine their settings
BaseSettings
{
// vgui_controls color specifications
Border.Bright "0 0 0 0" //"200 200 200 196" // the lit side of a control
Border.Dark "0 0 0 0" //"40 40 40 196" // the dark/unlit side of a control
Border.Selection "0 0 0 0" //"0 0 0 196" // the additional border color for displaying the default/selected button
Button.TextColor "White"
Button.BgColor "Blank"
Button.ArmedTextColor "White"
Button.ArmedBgColor "Blank" [$WIN32]
Button.ArmedBgColor "190 115 0 255" [$X360]
Button.DepressedTextColor "White"
Button.DepressedBgColor "Blank"
Button.FocusBorderColor "Black"
CheckButton.TextColor "OffWhite"
CheckButton.SelectedTextColor "White"
CheckButton.BgColor "TransparentBlack"
CheckButton.Border1 "Border.Dark" // the left checkbutton border
CheckButton.Border2 "Border.Bright" // the right checkbutton border
CheckButton.Check "White" // color of the check itself
ComboBoxButton.ArrowColor "DullWhite"
ComboBoxButton.ArmedArrowColor "White"
ComboBoxButton.BgColor "Blank"
ComboBoxButton.DisabledBgColor "Blank"
"Chat.TypingText" "white"
Frame.TitleTextInsetX 16
Frame.ClientInsetX 8
Frame.ClientInsetY 6
Frame.BgColor "160 160 160 128" [$WIN32]
Frame.BgColor "80 80 80 192" [$X360]
Frame.OutOfFocusBgColor "160 160 160 32" [$WIN32]
Frame.OutOfFocusBgColor "80 80 80 192" [$X360]
Frame.FocusTransitionEffectTime "0.3" // time it takes for a window to fade in/out on focus/out of focus
Frame.TransitionEffectTime "0.3" // time it takes for a window to fade in/out on open/close
Frame.AutoSnapRange "0"
FrameGrip.Color1 "200 200 200 196"
FrameGrip.Color2 "0 0 0 196"
FrameTitleButton.FgColor "200 200 200 196"
FrameTitleButton.BgColor "Blank"
FrameTitleButton.DisabledFgColor "255 255 255 192"
FrameTitleButton.DisabledBgColor "Blank"
FrameSystemButton.FgColor "Blank"
FrameSystemButton.BgColor "Blank"
FrameSystemButton.Icon ""
FrameSystemButton.DisabledIcon ""
FrameTitleBar.Font "UiBold" [$WIN32]
FrameTitleBar.Font "DefaultLarge" [$WIN32]
FrameTitleBar.TextColor "White"
FrameTitleBar.BgColor "Blank"
FrameTitleBar.DisabledTextColor "255 255 255 192"
FrameTitleBar.DisabledBgColor "Blank"
GraphPanel.FgColor "White"
GraphPanel.BgColor "TransparentBlack"
Label.TextDullColor "DullWhite"
Label.TextColor "OffWhite"
Label.TextBrightColor "White"
Label.SelectedTextColor "White"
Label.BgColor "TransparentBlack"
Label.DisabledFgColor1 "117 117 117 255"
Label.DisabledFgColor2 "30 30 30 255"
ListPanel.TextColor "OffWhite"
ListPanel.TextBgColor "Blank"
ListPanel.BgColor "TransparentBlack"
ListPanel.SelectedTextColor "Black"
ListPanel.SelectedBgColor "Orange"
ListPanel.SelectedOutOfFocusBgColor "255 155 0 128"
ListPanel.EmptyListInfoTextColor "OffWhite"
Menu.TextColor "White"
Menu.BgColor "160 160 160 64"
Menu.ArmedTextColor "Black"
Menu.ArmedBgColor "Orange"
Menu.TextInset "6"
Panel.FgColor "Blank"
Panel.BgColor "DullWhite"
ProgressBar.FgColor "White"
ProgressBar.BgColor "TransparentBlack"
PropertySheet.TextColor "OffWhite"
PropertySheet.SelectedTextColor "White"
PropertySheet.TransitionEffectTime "0.25" // time to change from one tab to another
RadioButton.TextColor "DullWhite"
RadioButton.SelectedTextColor "White"
RichText.TextColor "OffWhite"
RichText.BgColor "TransparentBlack"
RichText.SelectedTextColor "Black"
RichText.SelectedBgColor "Orange"
ScrollBar.Wide 11
ScrollBarButton.FgColor "White"
ScrollBarButton.BgColor "Blank"
ScrollBarButton.ArmedFgColor "White"
ScrollBarButton.ArmedBgColor "Blank"
ScrollBarButton.DepressedFgColor "White"
ScrollBarButton.DepressedBgColor "Blank"
ScrollBarSlider.FgColor "Blank" // nob color
ScrollBarSlider.BgColor "0 0 0 0" // slider background color 255 255 255 64
SectionedListPanel.HeaderTextColor "White"
SectionedListPanel.HeaderBgColor "Blank"
SectionedListPanel.DividerColor "Black"
SectionedListPanel.TextColor "DullWhite"
SectionedListPanel.BrightTextColor "White"
SectionedListPanel.BgColor "TransparentBlack"
SectionedListPanel.SelectedTextColor "Black"
SectionedListPanel.SelectedBgColor "Orange"
SectionedListPanel.OutOfFocusSelectedTextColor "Black"
SectionedListPanel.OutOfFocusSelectedBgColor "255 155 0 128"
TextEntry.TextColor "OffWhite"
TextEntry.BgColor "TransparentBlack"
TextEntry.CursorColor "OffWhite"
TextEntry.DisabledTextColor "DullWhite"
TextEntry.DisabledBgColor "Blank"
TextEntry.SelectedTextColor "Black"
TextEntry.SelectedBgColor "Orange"
TextEntry.OutOfFocusSelectedBgColor "255 155 0 128"
TextEntry.FocusEdgeColor "0 0 0 196"
ToggleButton.SelectedTextColor "White"
Tooltip.TextColor "0 0 0 196"
Tooltip.BgColor "Orange"
TreeView.BgColor "TransparentBlack"
WizardSubPanel.BgColor "Blank"
// scheme-specific colors
MainMenu.TextColor "White" [$WIN32]
MainMenu.TextColor "200 200 200 255" [$X360]
MainMenu.ArmedTextColor "200 200 200 255" [$WIN32]
MainMenu.ArmedTextColor "White" [$X360]
MainMenu.DepressedTextColor "192 186 80 255"
MainMenu.MenuItemHeight "16" [$WIN32]
MainMenu.MenuItemHeight "32" [$X360]
MainMenu.Inset "32"
MainMenu.Backdrop "0 0 0 156"
Console.TextColor "OffWhite"
Console.DevTextColor "White"
NewGame.TextColor "White"
NewGame.FillColor "0 0 0 255"
NewGame.SelectionColor "Orange" [$WIN32]
NewGame.SelectionColor "0 0 0 255" [$X360]
NewGame.DisabledColor "128 128 128 196"
}
//////////////////////// BITMAP FONT FILES /////////////////////////////
//
// Bitmap Fonts are ****VERY*** expensive static memory resources so they are purposely sparse
BitmapFontFiles
{
// UI buttons, custom font, (256x64)
//"Buttons" "materials/vgui/fonts/buttons_32.vbf"
}
//////////////////////// FONTS /////////////////////////////
//
// describes all the fonts
Fonts
{
"Default"
{
"1"
{
"name" "Tahoma"
"tall" "12"
"weight" "0"
"range" "0x0000 0x017F"
"yres" "480 599"
}
"2"
{
"name" "Tahoma"
"tall" "13"
"weight" "0"
"range" "0x0000 0x017F"
"yres" "600 767"
}
"3"
{
"name" "Tahoma"
"tall" "14"
"weight" "0"
"range" "0x0000 0x017F"
"yres" "768 1023"
"antialias" "1"
}
"4"
{
"name" "Tahoma"
"tall" "16"
"weight" "0"
"range" "0x0000 0x017F"
"yres" "1024 1280"
"antialias" "1"
}
"5"
{
"name" "Tahoma"
"tall" "20"
"weight" "0"
"range" "0x0000 0x017F"
"yres" "1200 6000"
"antialias" "1"
}
}
// this is the symbol font
"Marlett"
{
"1"
{
"name" "Marlett"
"tall" "10"
"weight" "0"
"yres" "480 599"
"symbol" "1"
}
"2"
{
"name" "Marlett"
"tall" "14"
"weight" "0"
"yres" "600 767"
"symbol" "1"
}
"3"
{
"name" "Marlett"
"tall" "13"
"weight" "0"
"yres" "768 1023"
"symbol" "1"
}
"4"
{
"name" "Marlett"
"tall" "17"
"weight" "0"
"yres" "1024 1199"
"symbol" "1"
}
"5"
{
"name" "Marlett"
"tall" "22"
"weight" "0"
"yres" "1200 10000"
"symbol" "1"
}
}
"ChatFont"
{
"1"
{
"name" "Tahoma"
"tall" "13"
"weight" "1000"
"yres" "480 599"
"outline" "1"
}
"2"
{
"name" "Tahoma"
"tall" "13"
"weight" "1000"
"yres" "600 767"
"outline" "1"
}
"3"
{
"name" "Tahoma"
"tall" "13"
"weight" "1000"
"yres" "768 1023"
"outline" "1"
}
"4"
{
"name" "Tahoma"
"tall" "13"
"weight" "1000"
"yres" "1024 1199"
"outline" "1"
}
"5"
{
"name" "Tahoma"
"tall" "13"
"weight" "1000"
"yres" "1200 10000"
"outline" "1"
}
}
}
//
//////////////////// BORDERS //////////////////////////////
//
// describes all the border types
Borders
{
BaseBorder DepressedBorder
ButtonBorder RaisedBorder
ComboBoxBorder DepressedBorder
MenuBorder RaisedBorder
BrowserBorder DepressedBorder
PropertySheetBorder RaisedBorder
FrameBorder
{
// rounded corners for frames
"backgroundtype" "2"
}
DepressedBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "Border.Dark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "Border.Bright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
}
RaisedBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "Border.Bright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
Top
{
"1"
{
"color" "Border.Bright"
"offset" "0 1"
}
}
Bottom
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
}
TitleButtonBorder
{
"backgroundtype" "0"
}
TitleButtonDisabledBorder
{
"backgroundtype" "0"
}
TitleButtonDepressedBorder
{
"backgroundtype" "0"
}
ScrollBarButtonBorder
{
"inset" "2 2 0 0"
Left
{
"1"
{
"color" "Border.Bright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "Border.Dark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
}
ScrollBarButtonDepressedBorder
{
"inset" "2 2 0 0"
Left
{
"1"
{
"color" "Border.Dark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "Border.Bright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
}
TabBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "Border.Bright"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "Border.Dark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
}
TabActiveBorder
{
"inset" "0 0 1 0"
Left
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
Right
{
"1"
{
"color" "Border.Dark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
}
ToolTipBorder
{
"inset" "0 0 1 0"
Left
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
Right
{
"1"
{
"color" "Border.Dark"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
}
// this is the border used for default buttons (the button that gets pressed when you hit enter)
ButtonKeyFocusBorder
{
"inset" "0 0 1 1"
Left
{
"1"
{
"color" "Border.Selection"
"offset" "0 0"
}
"2"
{
"color" "Border.Bright"
"offset" "0 1"
}
}
Top
{
"1"
{
"color" "Border.Selection"
"offset" "0 0"
}
"2"
{
"color" "Border.Bright"
"offset" "1 0"
}
}
Right
{
"1"
{
"color" "Border.Selection"
"offset" "0 0"
}
"2"
{
"color" "Border.Dark"
"offset" "1 0"
}
}
Bottom
{
"1"
{
"color" "Border.Selection"
"offset" "0 0"
}
"2"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
}
ButtonDepressedBorder
{
"inset" "2 1 1 1"
Left
{
"1"
{
"color" "Border.Dark"
"offset" "0 1"
}
}
Right
{
"1"
{
"color" "Border.Bright"
"offset" "1 0"
}
}
Top
{
"1"
{
"color" "Border.Dark"
"offset" "0 0"
}
}
Bottom
{
"1"
{
"color" "Border.Bright"
"offset" "0 0"
}
}
}
}
//////////////////////// CUSTOM FONT FILES /////////////////////////////
//
// specifies all the custom (non-system) font files that need to be loaded to service the above described fonts
CustomFontFiles
{
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+64
View File
@@ -0,0 +1,64 @@
// ______________________
//___________.( h0lmGUI™v4.1 by h0lm ).___________
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
"Resource/UI/BuyMenu.res"
{
"buy"
{
"ControlName" "CBuyMenu"
"fieldName" "buy"
"xpos" "0"
"ypos" "0"
"wide" "640"
"tall" "480"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"setTitleBarVisible" "0"
}
"BuySubMenu"
{
"ControlName" "WizardSubPanel"
"fieldName" "BuySubMenu"
"xpos" "0"
"ypos" "0"
"wide" "640"
"tall" "480"
"autoResize" "3"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
}
"LinePanel2"
{
"ControlName" "ImagePanel"
"fieldName" "LinePanel2"
"xpos" "25"
"ypos" "20"
"zpos" "0"
"wide" "590"
"tall" "53"
"visible" "1"
"PaintBackgroundType" "2"
"fillcolor" "0 0 0 196"
}
"LinePanel"
{
"ControlName" "ImagePanel"
"fieldName" "LinePanel"
"xpos" "25"
"ypos" "78"
"zpos" "0"
"wide" "590"
"tall" "352"
"visible" "1"
"PaintBackgroundType" "2"
"fillcolor" "0 0 0 196"
}
}
//________________________________________________
//¯¯¯¯¯¯¯¯¯¯¯'( h0lmGUI™v4.1 by h0lm )'¯¯¯¯¯¯¯¯¯¯¯
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+284
View File
@@ -0,0 +1,284 @@
// ______________________
//___________.( h0lmGUI™v4.1 by h0lm ).___________
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
"Resource/UI/ClassMenu_CT.res"
{
"class_ct"
{
"ControlName" "Frame"
"fieldName" "class_ct"
"xpos" "0"
"ypos" "0"
"wide" "640"
"tall" "480"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
}
"SysMenu"
{
"ControlName" "Menu"
"fieldName" "SysMenu"
"xpos" "0"
"ypos" "0"
"wide" "64"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "0"
"enabled" "0"
"tabPosition" "0"
}
"Backgroundz"
{
"ControlName" "ImagePanel"
"fieldName" "Backgroundz"
"xpos" "115"
"ypos" "c-134"
"zpos" "0"
"wide" "411"
"tall" "40"
"visible" "1"
"fillcolor" "0 0 0 196"
}
"Backgroundx"
{
"ControlName" "ImagePanel"
"fieldName" "Backgroundx"
"xpos" "115"
"ypos" "c-91"
"zpos" "0"
"wide" "411"
"tall" "227"
"visible" "1"
"fillcolor" "0 0 0 196"
}
"HeadlineZ"
{
"ControlName" "Label"
"fieldName" "HeadlineZ"
"xpos" "127"
"ypos" "c-124"
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "PICK A WARRIOR"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "TeamMenuHeadLine"
"fgcolor_override" "255 255 255 255"
//"bgcolor_override" "200 200 200 100"
}
"LOLmlogo"
{
"ControlName" "Label"
"fieldName" "LOLmlogo"
"xpos" "428"
"ypos" "c-124"
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "COUN"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "MenuLogogo"
"fgcolor_override" "255 255 255 20"
}
"joinClass"
{
"ControlName" "Label"
"fieldName" "joinClass"
"xpos" "76"
"ypos" "22"
"wide" "450"
"tall" "48"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_Join_Class"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "MenuTitle"
"fgcolor_override" "255 255 255 0"
}
"classInfoLabel"
{
}
"ClassInfo"
{
"ControlName" "Panel"
"fieldName" "ClassInfo"
"xpos" "290" //"244"
"ypos" "164"
"wide" "0" //"400"
"tall" "0" //"380"
"autoResize" "2" //"3"
"pinCorner" "0"
"visible" "0"
"enabled" "0"
"tabPosition" "0"
}
"urban"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "urban"
"xpos" "132"
"ypos" "162"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Urban"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 5"
}
"gsg9"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "gsg9"
"xpos" "132"
"ypos" "192"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_GSG9"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 6"
}
"sas"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "sas"
"xpos" "132"
"ypos" "222"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_SAS"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 7"
}
"gign"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "gign"
"xpos" "132"
"ypos" "252"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_GIGN"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 8"
}
"autoselect_ct"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "autoselect_ct"
"xpos" "132"
"ypos" "312"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Auto_Select"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 0"
"Default" "1"
}
"deadspec"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "deadspec"
"xpos" "132"
"ypos" "282"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "&5 DEAD SPECTATE"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "vguicancel"
"Default" "1"
}
"CancelButton"
{
"ControlName" "Button"
"fieldName" "CancelButton"
"xpos" "132"
"ypos" "342"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Cancel"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"Command" "vguicancel"
}
}
//________________________________________________
//¯¯¯¯¯¯¯¯¯¯¯'( h0lmGUI™v4.1 by h0lm )'¯¯¯¯¯¯¯¯¯¯¯
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+283
View File
@@ -0,0 +1,283 @@
// ______________________
//___________.( h0lmGUI™v4.1 by h0lm ).___________
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
"Resource/UI/ClassMenu_TER.res"
{
"class_ter"
{
"ControlName" "Frame"
"fieldName" "class_ter"
"xpos" "0"
"ypos" "0"
"wide" "640"
"tall" "480"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
}
"SysMenu"
{
"ControlName" "Menu"
"fieldName" "SysMenu"
"xpos" "0"
"ypos" "0"
"wide" "64"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "0"
"enabled" "0"
"tabPosition" "0"
}
"Backgroundz"
{
"ControlName" "ImagePanel"
"fieldName" "Backgroundz"
"xpos" "115"
"ypos" "c-134"
"zpos" "0"
"wide" "411"
"tall" "40"
"visible" "1"
"fillcolor" "0 0 0 196"
}
"Backgroundx"
{
"ControlName" "ImagePanel"
"fieldName" "Backgroundx"
"xpos" "115"
"ypos" "c-91"
"zpos" "0"
"wide" "411"
"tall" "227"
"visible" "1"
"fillcolor" "0 0 0 196"
}
"HeadlineZ"
{
"ControlName" "Label"
"fieldName" "HeadlineZ"
"xpos" "127"
"ypos" "c-124"
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "PICK A WARRIOR"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "TeamMenuHeadLine"
"fgcolor_override" "255 255 255 255"
//"bgcolor_override" "200 200 200 100"
}
"LOLmlogo"
{
"ControlName" "Label"
"fieldName" "LOLmlogo"
"xpos" "428"
"ypos" "c-124"
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "COUN"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "MenuLogogo"
"fgcolor_override" "255 255 255 20"
}
"joinClass"
{
"ControlName" "Label"
"fieldName" "joinClass"
"xpos" "76"
"ypos" "22"
"wide" "450"
"tall" "48"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_Join_Class"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "MenuTitle"
"fgcolor_override" "255 255 255 0"
}
"classInfoLabel"
{
}
"ClassInfo"
{
"ControlName" "Panel"
"fieldName" "ClassInfo"
"xpos" "290" //"244"
"ypos" "164"
"wide" "0" //"400"
"tall" "0" //"380"
"autoResize" "2" //"3"
"pinCorner" "0"
"visible" "0"
"enabled" "0"
"tabPosition" "0"
}
"terror"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "terror"
"xpos" "132"
"ypos" "162"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Terror"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 1"
}
"leet"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "leet"
"xpos" "132"
"ypos" "192"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_L337_Krew"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 2"
}
"arctic"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "arctic"
"xpos" "132"
"ypos" "222"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Arctic"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 3"
}
"guerilla"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "guerilla"
"xpos" "132"
"ypos" "252"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Guerilla"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 4"
}
"autoselect_t"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "autoselect_t"
"xpos" "132"
"ypos" "312"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Auto_Select"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "joinclass 0"
"Default" "1"
}
"deadspec"
{
"ControlName" "MouseOverPanelButton"
"fieldName" "deadspec"
"xpos" "132"
"ypos" "282"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "&5 DEAD SPECTATE"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "vguicancel"
"Default" "1"
}
"CancelButton"
{
"ControlName" "Button"
"fieldName" "CancelButton"
"xpos" "132"
"ypos" "342"
"wide" "148"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "#Cstrike_Cancel"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"Command" "vguicancel"
}
}
//________________________________________________
//¯¯¯¯¯¯¯¯¯¯¯'( h0lmGUI™v4.1 by h0lm )'¯¯¯¯¯¯¯¯¯¯¯
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+935
View File
@@ -0,0 +1,935 @@
"Resource/UI/ScoreBoard.res"
{
"scores"
{
"ControlName" "CCSClientScoreBoardDialog"
"fieldName" "scores"
"xpos" "0"
"ypos" "0"
"zpos" "90"
"wide" "f0"
"tall" "480"
"settitlebarvisible" "0"
}
"ScoreboardBackground"
{
"ControlName" "ImagePanel"
"fieldName" "ScoreboardBackground"
"xpos" "c-295"
"ypos" "c-158"
"wide" "590"
"tall" "253"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "0 0 0 200"
}
"Spec_Label"
{
"ControlName" "Label"
"fieldName" "Spec_Label"
"xpos" "c-288"
"ypos" "c+59"
"zpos" "4"
"wide" "140"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "Broadcast"
"textAlignment" "south-west"
"font" "ScoreboardTeamName"
"fgcolor_override" "255 255 255 255"
}
"HeadLine"
{
"ControlName" "ImagePanel"
"fieldName" "HeadLine"
"xpos" "c-290"
"ypos" "c-144"
"wide" "580"
"tall" "1"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "255 255 255 255"
}
"SpecLine"
{
"ControlName" "ImagePanel"
"fieldName" "HeadLine"
"xpos" "c-290"
"ypos" "c+75"
"wide" "580"
"tall" "1"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "255 255 255 255"
}
"CTLine"
{
"ControlName" "ImagePanel"
"fieldName" "CTLine"
"xpos" "c-290"
"ypos" "c-125"
"wide" "290"
"tall" "1"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "128 206 255 255"
}
"TLine"
{
"ControlName" "ImagePanel"
"fieldName" "TLine"
"xpos" "c+0"
"ypos" "c-125"
"wide" "290"
"tall" "1"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "255 26 28 255"
}
"CTScoreBox"
{
"ControlName" "ImagePanel"
"fieldName" "CTScoreBox"
"xpos" "c-60"
"ypos" "c-137"
"wide" "25"
"tall" "12"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "128 206 255 255"
}
"TScoreBox"
{
"ControlName" "ImagePanel"
"fieldName" "TScoreBox"
"xpos" "c+35"
"ypos" "c-137"
"wide" "25"
"tall" "12"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "255 26 28 255"
}
"CTPlayerBox1"
{
"ControlName" "ImagePanel"
"fieldName" "PlayerBox1"
"xpos" "c-290"
"ypos" "c-105"
"wide" "287"
"tall" "163"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "0 0 0 40"
}
"TPlayerBox1"
{
"ControlName" "ImagePanel"
"fieldName" "PlayerBox1"
"xpos" "c+4"
"ypos" "c-105"
"wide" "287"
"tall" "163"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "0"
"fillcolor" "0 0 0 40"
}
"ServerNameLabel"
{
"ControlName" "Label"
"fieldName" "ServerNameLabel"
"xpos" "c-288"
"ypos" "c-157"
"zpos" "4"
"wide" "100"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" ""
"auto_wide_tocontents" "1"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
}
"DividerLabel1"
{
"ControlName" "Label"
"fieldName" "DividerLabel1"
"xpos" "10"
"ypos" "0"
"zpos" "4"
"wide" "5"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "-"
"auto_wide_tocontents" "1"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
"pin_to_sibling" "ServerNameLabel"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"MapName"
{
"ControlName" "Label"
"fieldName" "MapName"
"xpos" "10"
"ypos" "0"
"zpos" "4"
"wide" "30"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "%mapname%"
"auto_wide_tocontents" "1"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
"pin_to_sibling" "DividerLabel1"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"DividerLabel2"
{
"ControlName" "Label"
"fieldName" "DividerLabel2"
"xpos" "1"
"ypos" "0"
"zpos" "4"
"wide" "5"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "/"
"auto_wide_tocontents" "1"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
"pin_to_sibling" "MapName"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"StatsStatus"
{
"ControlName" "Label"
"fieldName" "StatsStatus"
"xpos" "1"
"ypos" "0"
"zpos" "4"
"wide" "65"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "%statsstatus%"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
"pin_to_sibling" "DividerLabel2"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"PositionLabel"
{
"ControlName" "Label"
"fieldName" "PositionLabel"
"xpos" "c+287"
"ypos" "c-157"
"zpos" "4"
"wide" "1"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" ""
"auto_wide_tocontents" "1"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "0 0 0 0"
}
"WinConditionLabel"
{
"ControlName" "Label"
"fieldName" "WinConditionLabel"
"xpos" "0"
"ypos" "0"
"zpos" "4"
"wide" "80"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" ""
"auto_wide_tocontents" "1"
"textAlignment" "east"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
"pin_to_sibling" "PositionLabel"
"pin_corner_to_sibling" "3"
"pin_to_sibling_corner" "2"
}
"CT_Label"
{
"ControlName" "Label"
"fieldName" "CT_Label"
"xpos" "c-288"
"ypos" "c-138"
"zpos" "4"
"wide" "140"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "Counter-Terrorists" //"%ct_teamname%"
"auto_wide_tocontents" "1"
"textAlignment" "west"
"font" "ScoreboardTeamName"
"fgcolor_override" "128 206 255 255"
}
"CTSeperator"
{
"ControlName" "Label"
"fieldName" "CTSeperator"
"xpos" "10"
"ypos" "0"
"zpos" "4"
"wide" "5"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "-"
"auto_wide_tocontents" "1"
"textAlignment" "west"
"font" "ScoreboardPlayersAlive"
"fgcolor_override" "128 206 255 255"
"pin_to_sibling" "CT_Label"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"CTPlayersAlive"
{
"ControlName" "Label"
"fieldName" "CTPlayersAlive"
"xpos" "10"
"ypos" "0"
"zpos" "4"
"wide" "45"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "%ct_alivecount%"
"auto_wide_tocontents" "1"
"textAlignment" "west"
"font" "ScoreboardPlayersAlive"
"fgcolor_override" "128 206 255 255"
"pin_to_sibling" "CTSeperator"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"CTPlayersAliveSuffix"
{
"ControlName" "Label"
"xpos" "4"
"ypos" "0"
"zpos" "4"
"wide" "80"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_Scoreboard_PlayersAlive"
"textAlignment" "west"
"font" "ScoreboardPlayersAliveSuffix"
"fgcolor_override" "128 206 255 255"
"pin_to_sibling" "CTPlayersAlive"
"pin_corner_to_sibling" "2"
"pin_to_sibling_corner" "3"
}
"CTTeamScore"
{
"ControlName" "Label"
"fieldName" "CTTeamScore"
"xpos" "c-97"
"ypos" "c-138"
"zpos" "4"
"wide" "100"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "%ct_totalteamscore%"
"textAlignment" "center"
"font" "ScoreboardScore"
"fgcolor_override" "255 255 255 255"
}
"T_Label"
{
"ControlName" "Label"
"fieldName" "T_Label"
"xpos" "c+256"
"ypos" "c-138"
"zpos" "4"
"wide" "140"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "Terrorists" //"%t_teamname%"
"auto_wide_tocontents" "1"
"textAlignment" "east"
"font" "ScoreboardTeamName"
"fgcolor_override" "255 26 28 255"
}
"TSeperator"
{
"ControlName" "Label"
"fieldName" "TSeperator"
"xpos" "10"
"ypos" "0"
"zpos" "4"
"wide" "5"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "-"
"auto_wide_tocontents" "1"
"textAlignment" "east"
"font" "ScoreboardPlayersAlive"
"fgcolor_override" "255 26 28 255"
"pin_to_sibling" "T_Label"
"pin_corner_to_sibling" "3"
"pin_to_sibling_corner" "2"
}
"TPlayersAlive"
{
"ControlName" "Label"
"fieldName" "TPlayersAlive"
"xpos" "10"
"ypos" "0"
"zpos" "4"
"wide" "45"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "%t_alivecount%"
"auto_wide_tocontents" "1"
"textAlignment" "east"
"font" "ScoreboardPlayersAlive"
"fgcolor_override" "255 26 28 255"
"pin_to_sibling" "TSeperator"
"pin_corner_to_sibling" "3"
"pin_to_sibling_corner" "2"
}
"TPlayersAliveSuffix"
{
"ControlName" "Label"
"xpos" "4"
"ypos" "0"
"zpos" "4"
"wide" "80"
"tall" "15"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_Scoreboard_PlayersAlive"
"textAlignment" "east"
"font" "ScoreboardPlayersAliveSuffix"
"fgcolor_override" "255 26 28 255"
"pin_to_sibling" "TPlayersAlive"
"pin_corner_to_sibling" "3"
"pin_to_sibling_corner" "2"
}
"TTeamScore"
{
"ControlName" "Label"
"fieldName" "TTeamScore"
"xpos" "c-3"
"ypos" "c-138"
"zpos" "4"
"wide" "100"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "%t_totalteamscore%"
"textAlignment" "center"
"font" "ScoreboardScore"
"fgcolor_override" "255 255 255 255"
}
"CTClanLabel"
{
"ControlName" "Label"
"fieldName" "CTClanLabel"
"xpos" "c-275"
"ypos" "c-125"
"zpos" "4"
"wide" "45"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "Clan"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "128 206 255 255"
}
"CTPlayerLabel"
{
"ControlName" "Label"
"fieldName" "CTPlayerLabel"
"xpos" "c-228"
"ypos" "c-125"
"zpos" "4"
"wide" "60"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_PlayerName"
"textAlignment" "west"
"font" "ScoreboardColumns"
"fgcolor_override" "128 206 255 255"
}
"CTPlayerScoreLabel"
{
"ControlName" "Label"
"fieldName" "CTPlayerScoreLabel"
"xpos" "c-93"
"ypos" "c-125"
"zpos" "4"
"wide" "30"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_Score"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "128 206 255 255"
}
"CTPlayerDeathsLabel"
{
"ControlName" "Label"
"fieldName" "CTPlayerDeathsLabel"
"xpos" "c-68"
"ypos" "c-125"
"zpos" "4"
"wide" "37"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_Deaths"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "128 206 255 255"
}
"CTPlayerLatencyLabel"
{
"ControlName" "Label"
"fieldName" "CTPlayerLatencyLabel"
"xpos" "c-39"
"ypos" "c-125"
"zpos" "4"
"wide" "42"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_Latency"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "128 206 255 255"
}
"TClanLabel"
{
"ControlName" "Label"
"fieldName" "TClanLabel"
"xpos" "c+20"
"ypos" "c-125"
"zpos" "4"
"wide" "45"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "Clan"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "255 26 28 255"
}
"TPlayerLabel"
{
"ControlName" "Label"
"fieldName" "TPlayerLabel"
"xpos" "c+67"
"ypos" "c-125"
"zpos" "4"
"wide" "60"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_PlayerName"
"textAlignment" "west"
"font" "ScoreboardColumns"
"fgcolor_override" "255 26 28 255"
}
"TPlayerScoreLabel"
{
"ControlName" "Label"
"fieldName" "TPlayerScoreLabel"
"xpos" "c+200"
"ypos" "c-125"
"zpos" "4"
"wide" "30"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_Score"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "255 26 28 255"
}
"TPlayerDeathsLabel"
{
"ControlName" "Label"
"fieldName" "TPlayerDeathsLabel"
"xpos" "c+225"
"ypos" "c-125"
"zpos" "4"
"wide" "37"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_Deaths"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "255 26 28 255"
}
"TPlayerLatencyLabel"
{
"ControlName" "Label"
"fieldName" "TPlayerLatencyLabel"
"xpos" "c+252"
"ypos" "c-125"
"zpos" "4"
"wide" "42"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_SB_Latency"
"textAlignment" "center"
"font" "ScoreboardColumns"
"fgcolor_override" "255 26 28 255"
}
"CTPlayerArea"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerArea"
"xpos" "c-286"
"ypos" "c-105"
"zpos" "10"
"wide" "283"
"tall" "210"
"visible" "0"
"fillcolor" "222 222 222 190"
}
"TPlayerArea"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerArea"
"xpos" "c+4"
"ypos" "c-105"
"zpos" "10"
"wide" "283"
"tall" "210"
"visible" "0"
"fillcolor" "0 222 222 190"
}
"CTPlayerAvatar0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerAvatar0"
"xpos" "c-289"
"ypos" "c-99"
"zpos" "10"
"wide" "10"
"tall" "10"
"visible" "0"
"fillcolor" "222 0 0 64"
}
"CTPlayerClan0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerClan0"
"xpos" "c-274"
"ypos" "c-99"
"zpos" "10"
"wide" "45"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"CTPlayerName0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerName0"
"xpos" "c-228"
"ypos" "c-99"
"zpos" "10"
"wide" "135"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"CTPlayerStatus0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerStatus0"
"xpos" "c-104"
"ypos" "c-99"
"zpos" "10"
"wide" "10"
"tall" "10"
"visible" "0"
"fillcolor" "222 0 0 64"
}
"CTPlayerScore0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerScore0"
"xpos" "c-95"
"ypos" "c-99"
"zpos" "10"
"wide" "30"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"CTPlayerDeaths0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerDeaths0"
"xpos" "c-70"
"ypos" "c-99"
"zpos" "10"
"wide" "37"
"tall" "10"
"visible" "0"
"fillcolor" "222 0 0 64"
}
"CTPlayerLatency0"
{
"ControlName" "ImagePanel"
"fieldName" "CTPlayerLatency0"
"xpos" "c-38"
"ypos" "c-99"
"zpos" "10"
"wide" "31"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"TPlayerAvatar0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerAvatar0"
"xpos" "c+5"
"ypos" "c-99"
"zpos" "10"
"wide" "10"
"tall" "10"
"visible" "0"
"fillcolor" "222 0 0 64"
}
"TPlayerClan0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerClan0"
"xpos" "c+20"
"ypos" "c-99"
"zpos" "10"
"wide" "45"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"TPlayerName0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerName0"
"xpos" "c+67"
"ypos" "c-99"
"zpos" "10"
"wide" "135"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"TPlayerStatus0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerStatus0"
"xpos" "c+191"
"ypos" "c-99"
"zpos" "10"
"wide" "10"
"tall" "10"
"visible" "0"
"fillcolor" "222 0 0 64"
}
"TPlayerScore0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerScore0"
"xpos" "c+199"
"ypos" "c-99"
"zpos" "10"
"wide" "30"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"TPlayerDeaths0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerDeaths0"
"xpos" "c+224"
"ypos" "c-99"
"zpos" "10"
"wide" "37"
"tall" "10"
"visible" "0"
"fillcolor" "222 0 0 64"
}
"TPlayerLatency0"
{
"ControlName" "ImagePanel"
"fieldName" "TPlayerLatency0"
"xpos" "c+258"
"ypos" "c-99"
"zpos" "10"
"wide" "30"
"tall" "10"
"visible" "0"
"fillcolor" "0 222 0 64"
}
"Spectators"
{
"ControlName" "Label"
"fieldName" "Spectators"
"labelText" "%spectators%"
"textAlignment" "west"
"xpos" "c-288"
"ypos" "c+77"
"zpos" "90"
"wide" "485"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
}
"SourceTV"
{
"ControlName" "Label"
"fieldName" "SourceTV"
"labelText" "%sourcetv%"
"textAlignment" "east"
"xpos" "c+208"
"ypos" "c+77"
"zpos" "90"
"wide" "80"
"tall" "15"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"font" "ScoreboardHeader"
"fgcolor_override" "255 255 255 255"
}
}
+308
View File
@@ -0,0 +1,308 @@
// ______________________
//___________.( h0lmGUI™v4.1 by h0lm ).___________
//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
"Resource/UI/TeamMenu.res"
{
"team"
{
"ControlName" "CTeamMenu"
"fieldName" "team"
"xpos" "0"
"ypos" "0"
"wide" "640"
"tall" "480"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
}
"SysMenu"
{
"ControlName" "Menu"
"fieldName" "SysMenu"
"xpos" "0"
"ypos" "0"
"wide" "64"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "0"
"enabled" "0"
"tabPosition" "0"
}
"MapInfo"
{
"ControlName" "RichText"
"fieldName" "MapInfo"
"xpos" "10000" //"244"
"ypos" "10000" //"116"
"wide" "10" //"316"
"tall" "10" //"286"
"autoResize" "0"
"pinCorner" "0"
"visible" "0"
"enabled" "0"
"tabPosition" "0"
}
"joinTeam"
{
"ControlName" "Label"
"fieldName" "joinTeam"
"xpos" "76"
"ypos" "22"
"wide" "450"
"tall" "48"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "#Cstrike_Join_Team"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "MenuTitle"
"fgcolor_override" "255 255 255 0"
}
"mapname"
{
"ControlName" "Label"
"fieldName" "mapname"
"xpos" "244"
"ypos" "72"
"wide" "180"
"tall" "24"
"autoResize" "0"
"pinCorner" "0"
"visible" "0"
"enabled" "1"
"labelText" ""
"textAlignment" "west"
"dulltext" "0"
"brighttext" "1"
}
"Backgroundz"
{
"ControlName" "ImagePanel"
"fieldName" "Backgroundz"
"xpos" "115"
"ypos" "c-134"
"zpos" "0"
"wide" "411"
"tall" "40"
"visible" "1"
"fillcolor" "0 0 0 196"
}
"Backgroundx"
{
"ControlName" "ImagePanel"
"fieldName" "Backgroundx"
"xpos" "115"
"ypos" "c-91"
"zpos" "0"
"wide" "411"
"tall" "227"
"visible" "1"
"fillcolor" "0 0 0 196"
}
"HeadlineZ"
{
"ControlName" "Label"
"fieldName" "HeadlineZ"
"xpos" "127"
"ypos" "c-124"
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "PICK A TEAM"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "TeamMenuHeadLine"
"fgcolor_override" "255 255 255 255"
//"bgcolor_override" "200 200 200 100"
}
"LOLmlogo"
{
"ControlName" "Label"
"fieldName" "LOLmlogo"
"xpos" "428"
"ypos" "c-124"
"wide" "200"
"tall" "20"
"autoResize" "0"
"pinCorner" "0"
"visible" "1"
"enabled" "1"
"labelText" "COUN"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"font" "MenuLogogo"
"fgcolor_override" "255 255 255 20"
}
"terbuttonbg"
{
"ControlName" "ImagePanel"
"fieldName" "terbuttonbg"
"xpos" "145"
"ypos" "c-66"
"wide" "160"
"tall" "22"
"visible" "1"
"fillcolor" "102 0 0 128"
}
"terbutton"
{
"ControlName" "Button"
"fieldName" "terbutton"
"xpos" "145"
"ypos" "c-66"
"wide" "160"
"tall" "22"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "3"
"labelText" "&1 TERRORIST-FACTION"
"textAlignment" "center"
"dulltext" "0"
"brighttext" "0"
"command" "jointeam 2"
"Font" "TeamMenuOption"
}
"ctbuttonbg"
{
"ControlName" "ImagePanel"
"fieldName" "ctbuttonbg"
"xpos" "336"
"ypos" "c-66"
"wide" "175"
"tall" "22"
"visible" "1"
"fillcolor" "0 39 102 128"
}
"ctbutton"
{
"ControlName" "Button"
"fieldName" "ctbutton"
"xpos" "336"
"ypos" "c-66"
"wide" "175"
"tall" "22"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "4"
"labelText" "&2 COUNTER-TERRORISTS"
"textAlignment" "center"
"dulltext" "0"
"brighttext" "0"
"command" "jointeam 3"
"Font" "TeamMenuOption"
}
"vipbutton"
{
"ControlName" "Button"
"fieldName" "vipbutton"
"xpos" "76"
"ypos" "180"
"wide" "148"
"tall" "20"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "5"
"labelText" "#Cstrike_VIP"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "jointeam 3"
}
"autobutton"
{
"ControlName" "Button"
"fieldName" "autobutton"
"xpos" "228"
"ypos" "c-26"
"wide" "78"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "1"
"labelText" "&5 AUTO-SIGN"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "jointeam 0"
"Default" "1"
"Font" "TeamMenuOption2"
}
"specbutton"
{
"ControlName" "Button"
"fieldName" "specbutton"
"xpos" "336"
"ypos" "c-26"
"wide" "71"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "2"
"labelText" "&6 SPECTATE"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"command" "jointeam 1"
"Font" "TeamMenuOption2"
}
"LinweBor"
{
"ControlName" "ImagePanel"
"fieldName" "LinweBor"
"xpos" "144"
"ypos" "c+13"
"zpos" "0"
"wide" "354"
"tall" "2"
"visible" "1"
"fillcolor" "0 0 0 100"
}
"CancelButton"
{
"ControlName" "Button"
"fieldName" "CancelButton"
"xpos" "447"
"ypos" "c+107"
"wide" "64"
"tall" "18"
"autoResize" "0"
"pinCorner" "2"
"visible" "1"
"enabled" "1"
"tabPosition" "0"
"labelText" "&0 CANCEL"
"textAlignment" "west"
"dulltext" "0"
"brighttext" "0"
"Command" "vguicancel"
"Font" "TeamMenuOption2"
}
}
//________________________________________________
//¯¯¯¯¯¯¯¯¯¯¯'( h0lmGUI™v4.1 by h0lm )'¯¯¯¯¯¯¯¯¯¯¯
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+346
View File
@@ -0,0 +1,346 @@
// sample animation script
//
//
// commands:
// Animate <panel name> <variable> <target value> <interpolator> <start time> <duration>
// variables:
// FgColor
// BgColor
// Position
// Size
// Blur (hud panels only)
// TextColor (hud panels only)
// Ammo2Color (hud panels only)
// Alpha (hud weapon selection only)
// SelectionAlpha (hud weapon selection only)
// TextScan (hud weapon selection only)
//
// interpolator:
// Linear
// Accel - starts moving slow, ends fast
// Deaccel - starts moving fast, ends slow
// Spline - simple ease in/out curve
// Pulse - < freq > over the duration, the value is pulsed (cosine) freq times ending at the dest value (assuming freq is integral)
// Flicker - < randomness factor 0.0 to 1.0 > over duration, each frame if random # is less than factor, use end value, otherwise use prev value
//
// RunEvent <event name> <start time>
// starts another even running at the specified time
//
// StopEvent <event name> <start time>
// stops another event that is current running at the specified time
//
// StopAnimation <panel name> <variable> <start time>
// stops all animations refering to the specified variable in the specified panel
//
// StopPanelAnimations <panel name> <start time>
// stops all active animations operating on the specified panel
//
// SetFont <panel name> <fontparameter> <fontname from scheme> <set time>
//
// SetTexture <panel name> <textureidname> <texturefilename> <set time>
//
// SetString <panel name> <string varname> <stringvalue> <set time>
event LevelInit
{
}
event OpenWeaponSelectionMenu
{
StopEvent CloseWeaponSelectionMenu 0.0
StopEvent WeaponPickup 0.0
// make the display visible
Animate HudWeaponSelection Alpha "128" Linear 0.0 0.1
Animate HudWeaponSelection SelectionAlpha "255" Linear 0.0 0.1
Animate HudWeaponSelection FgColor "FgColor" Linear 0.0 0.1
//Animate HudWeaponSelection TextColor "BrightFg" Linear 0.0 0.1
Animate HudWeaponSelection TextScan "1" Linear 0.0 0.1
}
event CloseWeaponSelectionMenu
{
StopEvent CloseWeaponSelectionMenu 0.0
StopEvent WeaponPickup 0.0
// make the display visible
Animate HudWeaponSelection Alpha "128" Linear 0.0 0.1
Animate HudWeaponSelection SelectionAlpha "255" Linear 0.0 0.1
Animate HudWeaponSelection FgColor "FgColor" Linear 0.0 0.1
//Animate HudWeaponSelection TextColor "BrightFg" Linear 0.0 0.1
Animate HudWeaponSelection TextScan "1" Linear 0.0 0.1
}
event MenuOpen
{
StopEvent MenuClose 0.0
// fade in
Animate HudMenu Alpha "255" Linear 0.0 0.1
Animate HudMenu SelectionAlpha "255" Linear 0.0 0.1
Animate HudMenu FgColor "FgColor" Linear 0.0 0.1
Animate HudMenu MenuColor "MenuColor" Linear 0.0 0.1
Animate HudMenu ItemColor "ItemColor" Linear 0.0 0.1
Animate HudMenu TextScan "1" Linear 0.0 0.1
// Undo any blur
Animate HudMenu Blur "1" Linear 0.0 0.01
}
event MenuClose
{
// Hide it
Animate HudMenu Alpha "0" Linear 0.0 1
Animate HudMenu SelectionAlpha "0" Linear 0.0 1
Animate HudMenu FgColor "0 0 0 0" Linear 0.0 1
Animate HudMenu MenuColor "0 0 0 0" Linear 0.0 1
Animate HudMenu ItemColor "0 0 0 0" Linear 0.0 1
}
event MenuPulse
{
Animate HudMenu Blur "7" Linear 0.0 0.1
Animate HudMenu Blur "2" Deaccel 0.1 0.1
Animate HudMenu Blur "7" Linear 0.2 0.1
Animate HudMenu Blur "2" Deaccel 0.3 0.1
Animate HudMenu Blur "7" Linear 0.4 0.1
Animate HudMenu Blur "2" Deaccel 0.5 0.1
Animate HudMenu Blur "1" Deaccel 0.6 0.4
}
event TimerIncrement
{
Animate HudTimer Blur "7" Linear 0.0 0.1
Animate HudTimer Blur "2" Deaccel 0.1 0.8
Animate HudTimer Blur "0" Deaccel 1.1 1.5
}
event TimerDecrement
{
Animate HudTimer Blur "7" Linear 0.0 0.1
Animate HudTimer Blur "2" Deaccel 0.1 0.8
Animate HudTimer Blur "0" Deaccel 1.1 1.5
}
event ResourceIncrement
{
Animate HudResources Blur "3" Linear 0.0 0.0
Animate HudResources PulseAmount "0" Linear 0.0 0.01
Animate HudResources Blur "1" Deaccel 0.1 1.5
Animate HudResources PulseAmount "1" Linear 0.1 2
Animate HudResources PulseAmount "0" Linear 2 2
}
event ResourceDecrement
{
Animate HudResources Blur "7" Linear 0.0 0.0
Animate HudResources PulseAmount "0" Linear 0.0 0.01
Animate HudResources Blur "1" Deaccel 0.1 1.5
Animate HudResources PulseAmount "1" Linear 0.1 2
Animate HudResources PulseAmount "0" Linear 2 2
}
event ResourcePickup
{
Animate HudResourcesPickup Alpha "255" Linear 0 0
Animate HudResourcesPickup Position "80 r40" Linear 0 0
Animate HudResourcesPickup Position "80 r120" Deaccel 0 1
Animate HudResourcesPickup Blur "7" Deaccel 0 0.2
Animate HudResourcesPickup Alpha "0" Deaccel .8 0.2
Animate HudResourcesPickup Blur "1" Deaccel 0.2 0.3
}
event PrimaryAmmoIncrement
{
}
event PrimaryAmmoDecrement
{
Animate HudAmmoPrimary FgColor "HudIcon_Red" Linear 0.0 0.0001
Animate HudAmmoPrimary FgColor "FgColor" Accel 0.0 3.0
}
event PrimaryAmmoEmpty
{
}
event SecondaryAmmoIncrement
{
}
event SecondaryAmmoDecrement
{
Animate HudAmmoPrimary FgColor "HudIcon_Red" Linear 0.0 0.0001
Animate HudAmmoPrimary FgColor "FgColor" Accel 0.0 3.0
}
event SecondaryAmmoEmpty
{
}
event ShowPrimaryAmmoClipShowSecondaryAmmo
{
// Turn on secondary
Animate HudAmmoSecondary Alpha "255" Linear 0.0 0.4
// Turn on secondary
Animate HudAmmoPrimaryClip Alpha "255" Linear 0.0 0.4
// Move primary to left
// Animate HudAmmoPrimary Position "r125 400" Deaccel 0.0 0.4
// Animate HudAmmoPrimaryClip Position "r55 400" Deaccel 0.0 0.4
}
event ShowPrimaryAmmoClipHideSecondaryAmmo
{
// Turn off secondary
Animate HudAmmoSecondary Alpha "0" Linear 0.0 0.4
// Turn on secondary
Animate HudAmmoPrimaryClip Alpha "255" Linear 0.0 0.4
// Move primary to left
// Animate HudAmmoPrimary Position "r100 400" Deaccel 0.0 0.4
// Animate HudAmmoPrimaryClip Position "r30 400" Deaccel 0.0 0.4
}
event HidePrimaryAmmoClipShowSecondaryAmmo
{
// Turn on secondary
Animate HudAmmoSecondary Alpha "255" Linear 0.0 0.4
// Turn off secondary
Animate HudAmmoPrimaryClip Alpha "0" Linear 0.0 0.4
// Move primary to left
// Animate HudAmmoPrimary Position "100 400" Deaccel 0.0 0.4
// Animate HudAmmoPrimaryClip Position "r30 400" Deaccel 0.0 0.4
}
event HidePrimaryAmmoClipHideSecondaryAmmo
{
// Turn off secondary
Animate HudAmmoSecondary Alpha "0" Linear 0.0 0.4
// Turn off secondary
Animate HudAmmoPrimaryClip Alpha "0" Linear 0.0 0.4
// Move primary to left
// Animate HudAmmoPrimary Position "r70 400" Deaccel 0.0 0.4
// Animate HudAmmoPrimaryClip Position "r30 400" Deaccel 0.0 0.4
}
//activecolor - instantly turn red, fade back to yellow
event AccountMoneyRemoved
{
Animate HudAccount FgColor "HudIcon_Red" Linear 0.0 0.0001
Animate HudAccount FgColor "toxicHUD" Accel 0.0 3.0
Animate HudAccount Ammo2Color "HudIcon_Red" Linear 0.0 0.0001
Animate HudAccount Ammo2Color "0 0 0 0" Accel 0.0 3.0
}
//activecolor - instantly turn green, fade back to yellow
event AccountMoneyAdded
{
Animate HudAccount FgColor "HudIcon_Green" Linear 0.0 0.0001
Animate HudAccount FgColor "toxicHUD" Accel 0.0 3.0
Animate HudAccount Ammo2Color "HudIcon_Green" Accel 0.0 0.0001
Animate HudAccount Ammo2Color "0 0 0 0" Accel 0.0 3.0
}
event AccountMoneyInvisible
{
Animate HudAccount FgColor "toxicHUD" Accel 0.0 0.0001
Animate HudAccount Ammo2Color "0 0 0 0" Accel 0.0 0.0001
}
event HealthRestored
{
StopPanelAnimations HudHealth 0.0
Animate HudHealth FgColor "toxicHealth" Linear 0.0 0.01
Animate HudHealth Blur "7" Deaccel 0.0 0.2
Animate HudHealth Blur "1" Deaccel 0.2 1.0
}
event HealthTookDamage
{
Animate HudHealth FgColor "HudIcon_Red" Linear 0.0 0.1
Animate HudHealth FgColor "toxicHealth" Pulse 4 0.1 1.0
Animate HudHealth Blur "7" Deaccel 0.0 0.2
Animate HudHealth Blur "1" Deaccel 0.2 0.3
}
event HealthLow
{
Animate HudHealth FgColor "HudIcon_Red" Linear 0.0 0.1
Animate HudHealth FgColor "toxicHealth" Pulse 2000 0.1 1000.0
}
event HintMessageShow
{
// show the hints
Animate HudHintDisplay Alpha 255 Linear 0.0 0.5
Animate HudHintDisplay FgColor "HintMessageFg" Linear 0.0 0.01
// hide the panel after a while
Animate HudHintDisplay Alpha 0 Linear 6.0 1.0
}
event HintMessageHide
{
Animate HudHintDisplay Alpha 0 Linear 0.0 0.5
}
event HintMessageLower
{
Animate HudHintDisplay YOffset "60" Deaccel 0.0 0.01
}
event HintMessageRaise
{
Animate HudHintDisplay YOffset "0" Deaccel 0.0 0.4
}
event KeyHintMessageShow
{
// show the hints
Animate HudHintKeyDisplay Alpha 255 Linear 0.0 0.5
Animate HudHintKeyDisplay FgColor "HintMessageFg" Linear 0.0 0.01
// hide the panel after a while
Animate HudHintKeyDisplay Alpha 0 Linear 6.0 1.0
}
event KeyHintMessageHide
{
Animate HudHintKeyDisplay Alpha 0 Linear 0.0 0.5
}
event MapOff
{
Animate overview Position "0 0" Linear 0.0 0.001
Animate overview Size "0 0" Linear 0.0 0.001
}
event MapZoomToSmall
{
Animate overview Position "16 16" Linear 0.0 0.2
Animate overview Size "160 120" Linear 0.0 0.2
StopAnimation overview zoom 0.0
Animate overview zoom "1.0" Linear 0.0 0.0001
Animate overview zoom "3.0" Spline 0.0001 1.0
}
event MapZoomToLarge
{
Animate overview Position "c-300 20" Linear 0.0 0.2
Animate overview Size "600 440" Linear 0.0 0.2
StopAnimation overview zoom 0.0
Animate overview zoom "1.0" Spline 0.0 0.2
}
+796
View File
@@ -0,0 +1,796 @@
"Resource/HudLayout.res"
{
HudHealth
{
"fieldName" "HudHealth"
"xpos" "8"
"ypos" "22446"
"zpos" "0"
"wide" "80"
"tall" "25"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"bgcolor_override" "0 0 0 96"
"icon_xpos" "8"
"icon_ypos" "-4"
"digit_xpos" "35"
"digit_ypos" "-4"
"LowHealthColor" "HudIcon_Red"
}
HudArmor
{
"fieldName" "HudArmor"
"xpos" "22148"
"ypos" "22446"
"zpos" "1"
"wide" "80"
"tall" "25"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"bgcolor_override" "0 0 0 96"
"icon_xpos" "8"
"icon_ypos" "-4"
"digit_xpos" "34"
"digit_ypos" "-4"
}
HudRoundTimer
{
"fieldName" "HudRoundTimer"
"xpos" "c-2228"
"ypos" "4446"
"zpos" "1"
"wide" "98"
"tall" "25"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"bgcolor_override" "0 0 0 96"
"FlashColor" "HudIcon_Red"
"icon_xpos" "8"
"icon_ypos" "-4"
"digit_xpos" "42"
"digit_ypos" "-4"
}
HudAmmo
{
"fieldName" "HudAmmo"
"xpos" "r222157"
"ypos" "446"
"zpos" "1"
"wide" "142"
"tall" "25"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"bgcolor_override" "0 0 0 96"
"digit_xpos" "8"
"digit_ypos" "-4"
"digit2_xpos" "63"
"digit2_ypos" "-4"
"bar_xpos" "53"
"bar_ypos" "3"
"bar_height" "20"
"bar_width" "2"
"icon_xpos" "110"
"icon_ypos" "2"
}
HudAccount
{
"fieldName" "HudAccount"
"xpos" "r22123"
"ypos" "394"
"wide" "108"
"tall" "45"
"visible" "0"
"enabled" "0"
"PaintBackgroundType" "2"
// "bgcolor_override" "0 0 0 96"
"icon_xpos" "2229"
"icon_ypos" "2126"
"digit_xpos" "2100"
"digit_ypos" "22216"
"icon2_xpos" "229"
"icon2_ypos" "-4"
"digit2_xpos" "2100"
"digit2_ypos" "-4"
}
overview
{
"fieldname" "overview"
"visible" "1"
"enabled" "1"
"xpos" "0"
"ypos" "22480"
"wide" "0"
"tall" "0"
}
HudCommentary
{
"fieldName" "HudCommentary"
"xpos" "c-22190"
"ypos" "350"
"wide" "380"
"tall" "40"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"bar_xpos" "50"
"bar_ypos" "20"
"bar_height" "8"
"bar_width" "320"
"speaker_xpos" "50"
"speaker_ypos" "8"
"count_xpos_from_right" "10" // Counts from the right side
"count_ypos" "8"
"icon_texture" "vgui/hud/icon_commentary"
"icon_xpos" "0"
"icon_ypos" "0"
"icon_width" "40"
"icon_height" "40"
}
HudHDRDemo
{
"fieldName" "HudHDRDemo"
"xpos" "0"
"ypos" "0"
"wide" "640"
"tall" "480"
"visible" "0"
"enabled" "1"
"Alpha" "255"
"PaintBackgroundType" "2"
"BorderColor" "0 0 0 255"
"BorderLeft" "16"
"BorderRight" "16"
"BorderTop" "16"
"BorderBottom" "64"
"BorderCenter" "0"
"TextColor" "255 255 255 255"
"LeftTitleY" "422"
"RightTitleY" "422"
}
TargetID
{
"fieldName" "TargetID"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudSuit
{
"fieldName" "HudSuit"
"xpos" "22140"
"ypos" "22432"
"wide" "108"
"tall" "36"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"text_xpos" "8"
"text_ypos" "20"
"digit_xpos" "50"
"digit_ypos" "2"
}
HudProgressBar
{
"fieldName" "HudProgressBar"
"xpos" "c-150"
"ypos" "300"
"wide" "300"
"tall" "15"
"visible" "1"
"enabled" "1"
"BorderThickness" "1"
"PaintBackgroundType" "2"
}
HudShoppingCart
{
"fieldName" "HudShoppingCart"
"xpos" "2264"
"ypos" "22240"
"wide" "40"
"tall" "40"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"IconColor" "HudIcon_Green"
}
HudC4
{
"fieldName" "HudC4"
"xpos" "16"
"ypos" "240"
"wide" "40"
"tall" "40"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"IconColor" "HudIcon_Green"
"FlashColor" "HudIcon_Red"
}
HudDefuser
{
"fieldName" "HudDefuser"
"xpos" "16"
"ypos" "240"
"wide" "40"
"tall" "40"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"IconColor" "HudIcon_Green"
}
HudHostageRescueZone
{
"fieldName" "HudHostageRescueZone"
"xpos" "16"
"ypos" "240"
"wide" "40"
"tall" "40"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"IconColor" "HudIcon_Green"
"FlashColor" "HudIcon_Red"
}
HudScenarioIcon
{
"fieldName" "HudScenarioIcon"
"xpos" "c110"
"ypos" "443"
"wide" "40"
"tall" "44"
"visible" "1"
"enabled" "1"
"PaintBackgroundType" "2"
"IconColor" "Hostage_Yellow"
}
HudFlashlight
{
"fieldName" "HudFlashlight"
"visible" "1"
"enabled" "1"
"xpos" "16"
"ypos" "370"
"wide" "102"
"tall" "20"
"text_xpos" "8"
"text_ypos" "6"
"TextColor" "255 170 0 220"
"PaintBackgroundType" "2"
}
HudDamageIndicator
{
"fieldName" "HudDamageIndicator"
"visible" "1"
"enabled" "1"
"DmgColorLeft" "255 0 0 0"
"DmgColorRight" "255 0 0 0"
"dmg_xpos" "30"
"dmg_ypos" "100"
"dmg_wide" "36"
"dmg_tall1" "240"
"dmg_tall2" "200"
}
HudZoom
{
"fieldName" "HudZoom"
"visible" "1"
"enabled" "1"
"Circle1Radius" "66"
"Circle2Radius" "74"
"DashGap" "16"
"DashHeight" "4"
"BorderThickness" "88"
}
HudWeaponSelection
{
"fieldName" "HudWeaponSelection"
"xpos" "r640"
"wide" "640"
"ypos" "16"
"visible" "1"
"enabled" "1"
"SmallBoxSize" "60"
"LargeBoxWide" "108"
"LargeBoxTall" "80"
"BoxGap" "8"
"SelectionNumberXPos" "4"
"SelectionNumberYPos" "4"
"SelectionGrowTime" "0.4"
"IconXPos" "8"
"IconYPos" "0"
"TextYPos" "68"
"TextColor" "SelectionTextFg"
"MaxSlots" "5"
"PlaySelectSounds" "0"
}
HudCrosshair
{
"fieldName" "HudCrosshair"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudDeathNotice
{
"fieldName" "HudDeathNotice"
"visible" "1"
"enabled" "1"
"xpos" "r640"
"ypos" "12"
"wide" "628"
"tall" "468"
"MaxDeathNotices" "4"
"LineHeight" "22"
"RightJustify" "1" // If 1, draw notices from the right
"TextFont" "Default"
"CTTextColor" "CT_Blue"
"TerroristTextColor" "T_Red"
}
HudVehicle
{
"fieldName" "HudVehicle"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
CVProfPanel
{
"fieldName" "CVProfPanel"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
ScorePanel
{
"fieldName" "ScorePanel"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudTrain
{
"fieldName" "HudTrain"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudMOTD
{
"fieldName" "HudMOTD"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudMessage
{
"fieldName" "HudMessage"
"visible" "1"
"enabled" "1"
"wide" "f0"
"tall" "480"
}
HudMenu
{
"fieldName" "HudMenu"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
"zpos" "1"
"TextFont" "Default"
"ItemFont" "Default"
"ItemFontPulsing" "Default"
}
HudCloseCaption
{
"fieldName" "HudCloseCaption"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudHistoryResource
{
"fieldName" "HudHistoryResource"
"visible" "1"
"enabled" "1"
"xpos" "r640"
"wide" "640"
"tall" "350"
"history_gap" "50"
}
HudGeiger
{
"fieldName" "HudGeiger"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HUDQuickInfo
{
"fieldName" "HUDQuickInfo"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudWeapon
{
"fieldName" "HudWeapon"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudAnimationInfo
{
"fieldName" "HudAnimationInfo"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
CBudgetPanel
{
"fieldName" "CBudgetPanel"
"visible" "0"
"enabled" "0"
"wide" "640"
"tall" "480"
}
CTextureBudgetPanel
{
"fieldName" "CTextureBudgetPanel"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudPredictionDump
{
"fieldName" "HudPredictionDump"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudRadar
{
"fieldName" "HudRadar"
"visible" "1"
"enabled" "1"
"xpos" "22216"
"ypos" "22216"
"wide" "96"
"tall" "96"
}
HudLocation
{
"fieldName" "HudLocation"
"visible" "1"
"enabled" "1"
"xpos" "16"
"ypos" "112"
"wide" "96"
"tall" "16"
"textAlignment" "north"
}
HudScope
{
"fieldName" "HudZoom"
"visible" "1"
"enabled" "1"
"wide" "640"
"tall" "480"
}
HudVoiceSelfStatus
{
"fieldName" "HudVoiceSelfStatus"
"visible" "1"
"enabled" "1"
"xpos" "r34"
"ypos" "355"
"wide" "24"
"tall" "24"
}
HudVoiceStatus
{
"fieldName" "HudVoiceStatus"
"visible" "1"
"enabled" "1"
"xpos" "r200"
"ypos" "0"
"wide" "200"
"tall" "400"
"item_tall" "16"
"item_wide" "195"
"item_spacing" "2"
"show_avatar" "1"
"show_friend" "1"
"show_voice_icon" "0"
"show_dead_icon" "1"
"dead_xpos" "0"
"dead_ypos" "0"
"dead_wide" "16"
"dead_tall" "16"
"avatar_xpos" "14"
"avatar_ypos" "0"
"avatar_wide" "16"
"avatar_tall" "16"
"text_xpos" "42"
"fade_in_time" "0.07"
"fade_out_time" "1.0"
}
HudFlashbang
{
}
HudHintDisplay
{
"fieldName" "HudHintDisplay"
"visible" "0"
"enabled" "1"
"xpos" "c-240"
"ypos" "c110"
"wide" "480"
"tall" "100"
"text_xpos" "8"
"text_ypos" "8"
"center_x" "0" // center text horizontally
"center_y" "-1" // align text on the bottom
"HintSize" "1"
}
HudHintKeyDisplay
{
"fieldName" "HudHintKeyDisplay"
"visible" "0"
"enabled" "1"
"xpos" "r120"
"ypos" "r340"
"wide" "100"
"tall" "200"
"text_xpos" "8"
"text_ypos" "8"
"text_xgap" "8"
"text_ygap" "8"
"TextColor" "255 170 0 220"
"PaintBackgroundType" "2"
}
HudTerritory
{
"fieldName" "HudTerritory"
"visible" "1"
"enabled" "1"
"xpos" "240"
"ypos" "432"
"wide" "240"
"tall" "48"
}
TerritorySCore
{
"fieldName" "TerritoryScore"
"visible" "0"
"enabled" "0"
"xpos" "240"
"ypos" "450"
"wide" "200"
"tall" "200"
"text_xpos" "8"
"text_ypos" "4"
}
"HudChat"
{
"ControlName" "EditablePanel"
"fieldName" "HudChat"
"visible" "1"
"enabled" "1"
"xpos" "0" [$WIN32]
"xpos" "0" [$X360]
"ypos" "0"
"wide" "f0"
"tall" "f0"
"PaintBackgroundType" "0"
"bgcolor_override" "0 0 0 0"
}
WinPanel_Round
{
"fieldName" "WinPanel_Round"
"visible" "1"
"enabled" "1"
"xpos" "c-110"
"ypos" "287"
"zpos" "0"
"wide" "220"
"tall" "138"
"PaintBackgroundType" "2"
}
WinPanel_Match
{
"fieldName" "WinPanel_Match"
"visible" "1"
"enabled" "1"
"xpos" "c-150"
"ypos" "c-175"
"wide" "300"
"tall" "350"
"PaintBackgroundType" "2"
}
FreezePanel
{
"fieldName" "FreezePanel"
"visible" "1"
"enabled" "1"
"xpos" "0"
"ypos" "0"
"wide" "f0"
"tall" "480"
}
FreezePanelCallout
{
"fieldName" "FreezePanelCallout"
"visible" "1"
"enabled" "1"
"xpos" "200"
"ypos" "200"
"wide" "100"
"tall" "50"
}
AchievementAnnouncePanel
{
"fieldName" "AchievementAnnouncePanel"
"visible" "1"
"enabled" "1"
"xpos" "0"
"ypos" "0"
"wide" "f0"
"tall" "480"
}
StatPanel
{
"fieldName" "StatPanel"
"visible" "0"
"enabled" "1"
}
AchievementNotificationPanel
{
"fieldName" "AchievementNotificationPanel"
"visible" "0"
"enabled" "1"
}
HUDAutoAim
{
"fieldName" "HUDAutoAim"
"visible" "0"
"enabled" "1"
}
"HudAchievementTracker"
{
"ControlName" "EditablePanel"
"fieldName" "HudAchievementTracker"
"xpos" "10"
"NormalY" "120"
"EngineerY" "170"
"zpos" "20"
"wide" "250"
"tall" "280"
"visible" "1"
"enabled" "1"
}
}
+37
View File
@@ -0,0 +1,37 @@
FROM denoland/deno:debian-2.1.4
# Install archive extraction tools
RUN apt-get update && apt-get install -y \
unar \
unzip \
bzip2 \
&& rm -rf /var/lib/apt/lists/*
# Create app directory
WORKDIR /app
# Copy the scripts
COPY common.ts .
COPY mapsdl.ts .
COPY mapsdl-all.ts .
# Run as UID 1000 to match cssds (steam user)
RUN groupadd -g 1000 steam && useradd -u 1000 -g steam -m steam
# Create directories for credentials and data
RUN mkdir -p /app/credentials /maps /tmp/mapsdl && \
chown steam:steam /maps /tmp/mapsdl
# Cache Deno dependencies
RUN deno cache --allow-import mapsdl.ts mapsdl-all.ts
# Set default environment variables
ENV MAPS_DIR=/maps
ENV TEMP_DIR=/tmp/mapsdl
ENV GOOGLE_APPLICATION_CREDENTIALS=/app/credentials/service-account.json
# Run as same UID as cssds
USER steam
# Default command runs dry-run mode
CMD ["run", "-A", "mapsdl.ts", "--dry-run"]
+474
View File
@@ -0,0 +1,474 @@
import { join } from "https://deno.land/std@0.210.0/path/mod.ts";
import { type CredentialsClient } from "https://googleapis.deno.dev/v1/drive:v3.ts";
import { SignJWT, importPKCS8 } from "https://deno.land/x/jose@v4.14.4/index.ts";
// Types
export interface GDriveFile {
id: string;
name: string;
size: string;
}
export interface Manifest {
total: number;
found: number;
missing: string[];
notInGDrive: string[];
}
export type GDriveFolders = { aToK: string; lToZ: string };
export type DownloadConfig = { mapsDir: string; tempDir: string; concurrency: number };
// Service account auth that exchanges JWT for an OAuth2 access token
export class ServiceAccountAuth implements CredentialsClient {
#clientEmail: string;
#privateKey: string;
#tokenUri: string;
#scope: string;
#accessToken: string | null = null;
#tokenExpiry = 0;
constructor(json: { client_email: string; private_key: string; token_uri?: string }, scope: string) {
this.#clientEmail = json.client_email;
this.#privateKey = json.private_key;
this.#tokenUri = json.token_uri ?? "https://oauth2.googleapis.com/token";
this.#scope = scope;
}
async getRequestHeaders(_url?: string): Promise<Record<string, string>> {
if (!this.#accessToken || Date.now() / 1000 > this.#tokenExpiry - 60) {
await this.#refreshToken();
}
return { Authorization: `Bearer ${this.#accessToken}` };
}
async #refreshToken(): Promise<void> {
const now = Math.floor(Date.now() / 1000);
const key = await importPKCS8(this.#privateKey, "RS256");
const assertion = await new SignJWT({
iss: this.#clientEmail,
scope: this.#scope,
aud: this.#tokenUri,
})
.setProtectedHeader({ alg: "RS256", typ: "JWT" })
.setIssuedAt(now)
.setExpirationTime(now + 3600)
.sign(key);
const resp = await fetch(this.#tokenUri, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion,
}),
});
if (!resp.ok) {
const body = await resp.text();
throw new Error(`Token exchange failed (${resp.status}): ${body}`);
}
const data = await resp.json();
this.#accessToken = data.access_token;
this.#tokenExpiry = now + (data.expires_in ?? 3600);
}
}
// Google Drive API client with service account
export class GoogleDriveClient {
private auth!: CredentialsClient;
async authenticate(serviceAccountPath: string): Promise<void> {
console.log("[AUTH] Authenticating with Google Drive API...");
const keyFile = await Deno.readTextFile(serviceAccountPath);
this.auth = new ServiceAccountAuth(
JSON.parse(keyFile),
"https://www.googleapis.com/auth/drive.readonly",
);
console.log("[OK] Authentication successful");
}
async listFiles(folderId: string): Promise<GDriveFile[]> {
const files: GDriveFile[] = [];
let pageToken: string | undefined;
do {
const params = new URLSearchParams({
q: `'${folderId}' in parents and trashed=false`,
fields: "nextPageToken, files(id, name, size)",
pageSize: "1000",
});
if (pageToken) params.set("pageToken", pageToken);
const url = `https://www.googleapis.com/drive/v3/files?${params}`;
const headers = await this.auth.getRequestHeaders(url);
const resp = await fetch(url, { headers });
if (!resp.ok) {
throw new Error(`Drive listFiles failed (${resp.status}): ${await resp.text()}`);
}
const data = await resp.json();
for (const f of data.files ?? []) {
if (f.id && f.name) {
files.push({ id: f.id, name: f.name, size: String(f.size ?? "") });
}
}
pageToken = data.nextPageToken ?? undefined;
} while (pageToken);
return files;
}
async downloadFile(fileId: string, destPath: string): Promise<void> {
const url = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media`;
const headers = await this.auth.getRequestHeaders(url);
const response = await fetch(url, { headers });
if (!response.ok) {
throw new Error(`Download failed: ${response.statusText}`);
}
const bytes = new Uint8Array(await response.arrayBuffer());
await Deno.writeFile(destPath, bytes);
}
}
// Helpers
export function formatBytes(n: number): string {
if (n < 1024) return `${n} B`;
if (n < 1024 * 1024) return `${(n / 1024).toFixed(2)} KB`;
if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(2)} MB`;
return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;
}
export async function getLocalMaps(mapsDir: string): Promise<Set<string>> {
console.log(`[DIR] Scanning local maps directory: ${mapsDir}`);
const localMaps = new Set<string>();
try {
for await (const entry of Deno.readDir(mapsDir)) {
if (entry.isFile && entry.name.endsWith(".bsp.bz2")) {
const mapName = entry.name.replace(/\.bsp\.bz2$/, "");
localMaps.add(mapName);
}
}
} catch (error) {
if (error instanceof Deno.errors.NotFound) {
console.warn(`[!] Maps directory not found: ${mapsDir}`);
await Deno.mkdir(mapsDir, { recursive: true });
} else {
throw error;
}
}
console.log(`[OK] Found ${localMaps.size} local maps`);
return localMaps;
}
export function buildManifest(
requiredMaps: Set<string>,
localMaps: Set<string>,
): Manifest {
console.log("[STATS] Building manifest of missing maps...");
const missing: string[] = [];
for (const mapName of requiredMaps) {
if (!localMaps.has(mapName)) {
missing.push(mapName);
}
}
return {
total: requiredMaps.size,
found: localMaps.size,
missing,
notInGDrive: [],
};
}
export async function searchGDriveForMaps(
client: GoogleDriveClient,
manifest: Manifest,
gdriveFolders: GDriveFolders,
verbose: boolean,
): Promise<Map<string, GDriveFile>> {
console.log("\n[CLOUD] Searching Google Drive folders...");
const [filesAK, filesLZ] = await Promise.all([
client.listFiles(gdriveFolders.aToK),
client.listFiles(gdriveFolders.lToZ),
]);
const allFiles = [...filesAK, ...filesLZ];
console.log(`[OK] Found ${allFiles.length} files in Google Drive`);
console.log(` - A-K folder: ${filesAK.length} files`);
console.log(` - L-Z folder: ${filesLZ.length} files`);
// Build map of normalized names to GDrive files
const gdriveMap = new Map<string, GDriveFile>();
for (const file of allFiles) {
const normalized = file.name
.replace(/\.bsp\.bz2$/i, "")
.replace(/\.(rar|bz2|zip|bsp)$/i, "")
.toLowerCase()
.trim();
if (normalized.startsWith("surf_")) {
gdriveMap.set(normalized, file);
}
}
if (verbose) {
console.log("\n[>>] Debug - First 5 GDrive files (normalized):");
Array.from(gdriveMap.keys()).slice(0, 5).forEach(name => {
console.log(` - "${name}"`);
});
console.log("\n[>>] Debug - First 5 missing maps:");
manifest.missing.slice(0, 5).forEach(name => {
console.log(` - "${name.toLowerCase().trim()}"`);
});
}
// Check which missing maps are available in GDrive
const availableMaps = new Map<string, GDriveFile>();
for (const mapName of manifest.missing) {
const normalized = mapName.toLowerCase().trim();
if (gdriveMap.has(normalized)) {
availableMaps.set(mapName, gdriveMap.get(normalized)!);
} else {
manifest.notInGDrive.push(mapName);
}
}
// Sum total download size
let totalBytes = 0;
for (const file of availableMaps.values()) {
const size = parseInt(file.size, 10);
if (!isNaN(size)) totalBytes += size;
}
console.log(`\n[STATS] Cross-reference results:`);
console.log(` [OK] Available to download: ${availableMaps.size} maps`);
console.log(` [X] Not in Google Drive: ${manifest.notInGDrive.length} maps`);
console.log(` Total download size: ${formatBytes(totalBytes)}`);
if (manifest.notInGDrive.length > 0) {
console.log(`\n[!] Maps not found in Google Drive (showing first 10):`);
manifest.notInGDrive.slice(0, 10).forEach(map => {
console.log(` - ${map}`);
});
if (manifest.notInGDrive.length > 10) {
console.log(` ... and ${manifest.notInGDrive.length - 10} more`);
}
}
return availableMaps;
}
// Cross-device safe move (copy + delete)
export async function moveFile(src: string, dest: string): Promise<void> {
try {
await Deno.rename(src, dest);
} catch (e) {
if ((e as Error).message.includes("os error 18")) {
await Deno.copyFile(src, dest);
await Deno.remove(src);
} else {
throw e;
}
}
}
export async function downloadAndExtractMaps(
client: GoogleDriveClient,
mapsToDownload: Map<string, GDriveFile>,
config: DownloadConfig,
): Promise<{ success: number; failed: number }> {
console.log(`\n[DL] Downloading ${mapsToDownload.size} maps...`);
await Deno.mkdir(config.tempDir, { recursive: true });
const stats = { success: 0, failed: 0 };
let completed = 0;
const entries = Array.from(mapsToDownload.entries());
for (let i = 0; i < entries.length; i += config.concurrency) {
const batch = entries.slice(i, i + config.concurrency);
await Promise.all(
batch.map(async ([mapName, gdriveFile]) => {
try {
completed++;
console.log(`[${completed}/${mapsToDownload.size}] Downloading ${mapName}...`);
const archivePath = join(config.tempDir, gdriveFile.name);
const tempBspPath = join(config.tempDir, `${mapName}.bsp`);
const bz2Path = join(config.mapsDir, `${mapName}.bsp.bz2`);
await client.downloadFile(gdriveFile.id, archivePath);
if (gdriveFile.name.endsWith(".rar")) {
await extractRAR(archivePath, mapName, config.tempDir, config.tempDir);
await Deno.remove(archivePath);
} else if (gdriveFile.name.endsWith(".bz2")) {
await decompressBZ2(archivePath, tempBspPath);
await Deno.remove(archivePath);
} else if (gdriveFile.name.endsWith(".zip")) {
await extractZIP(archivePath, mapName, config.tempDir, config.tempDir);
await Deno.remove(archivePath);
} else if (gdriveFile.name.endsWith(".bsp")) {
await moveFile(archivePath, tempBspPath);
} else {
throw new Error(`Unknown archive format: ${gdriveFile.name}`);
}
await verifyBSP(tempBspPath);
await compressBSP(tempBspPath, bz2Path);
await Deno.remove(tempBspPath);
stats.success++;
console.log(` [OK] ${mapName} downloaded and compressed`);
} catch (error) {
stats.failed++;
console.error(` [X] Failed to download ${mapName}: ${(error as Error).message}`);
}
})
);
}
return stats;
}
export async function extractRAR(archivePath: string, mapName: string, destDir: string, tempDir: string): Promise<void> {
const tempExtractDir = join(tempDir, `extract_${mapName}`);
await Deno.mkdir(tempExtractDir, { recursive: true });
const process = new Deno.Command("unar", {
args: ["-f", "-o", tempExtractDir, archivePath],
stdout: "piped",
stderr: "piped",
});
const { code, stderr } = await process.output();
if (code !== 0) {
const errorMsg = new TextDecoder().decode(stderr);
throw new Error(`unar failed: ${errorMsg}`);
}
const bspFile = await findBSPFile(tempExtractDir, mapName);
if (!bspFile) {
throw new Error(`No BSP file found in archive for ${mapName}`);
}
await moveFile(bspFile, join(destDir, `${mapName}.bsp`));
await Deno.remove(tempExtractDir, { recursive: true });
}
export async function extractZIP(archivePath: string, mapName: string, destDir: string, tempDir: string): Promise<void> {
const tempExtractDir = join(tempDir, `extract_${mapName}`);
await Deno.mkdir(tempExtractDir, { recursive: true });
const process = new Deno.Command("unzip", {
args: ["-o", archivePath, "-d", tempExtractDir],
stdout: "piped",
stderr: "piped",
});
const { code, stderr } = await process.output();
if (code !== 0) {
const errorMsg = new TextDecoder().decode(stderr);
throw new Error(`unzip failed: ${errorMsg}`);
}
const bspFile = await findBSPFile(tempExtractDir, mapName);
if (!bspFile) {
throw new Error(`No BSP file found in archive for ${mapName}`);
}
await moveFile(bspFile, join(destDir, `${mapName}.bsp`));
await Deno.remove(tempExtractDir, { recursive: true });
}
export async function decompressBZ2(archivePath: string, outputPath: string): Promise<void> {
const process = new Deno.Command("bunzip2", {
args: ["-c", archivePath],
stdout: "piped",
});
const { code, stdout } = await process.output();
if (code !== 0) {
throw new Error(`bunzip2 failed with exit code ${code}`);
}
await Deno.writeFile(outputPath, stdout);
}
export async function findBSPFile(dir: string, mapName: string): Promise<string | null> {
for await (const entry of Deno.readDir(dir)) {
const fullPath = join(dir, entry.name);
if (entry.isFile && entry.name.endsWith(".bsp")) {
const baseName = entry.name.replace(/\.bsp$/i, "").toLowerCase();
if (baseName === mapName.toLowerCase()) {
return fullPath;
}
} else if (entry.isDirectory) {
const found = await findBSPFile(fullPath, mapName);
if (found) return found;
}
}
return null;
}
export async function verifyBSP(bspPath: string): Promise<void> {
const file = await Deno.open(bspPath, { read: true });
try {
const buffer = new Uint8Array(4);
await file.read(buffer);
const signature = new TextDecoder().decode(buffer);
if (signature !== "VBSP") {
throw new Error(`Invalid BSP signature: ${signature}`);
}
const stat = await Deno.stat(bspPath);
if (stat.size < 1024 * 1024) {
throw new Error("BSP file too small - possibly corrupted");
}
} finally {
file.close();
}
}
export async function compressBSP(bspPath: string, bz2Path: string): Promise<void> {
const process = new Deno.Command("bzip2", {
args: ["-c", bspPath],
stdout: "piped",
});
const { code, stdout } = await process.output();
if (code !== 0) throw new Error(`bzip2 failed with exit code ${code}`);
await Deno.writeFile(bz2Path, stdout);
}
+116
View File
@@ -0,0 +1,116 @@
import { parse } from "https://deno.land/std@0.210.0/flags/mod.ts";
import {
GoogleDriveClient,
getLocalMaps,
buildManifest,
searchGDriveForMaps,
downloadAndExtractMaps,
} from "./common.ts";
const CONFIG = {
sqlUrl: "https://raw.githubusercontent.com/bhopppp/Shavit-Surf-Timer/master/sql/surfzones.sql",
mapsDir: Deno.env.get("MAPS_DIR") || "/home/ntr/surf_megastructure/data/cssds/cstrike/maps",
tempDir: Deno.env.get("TEMP_DIR") || "/tmp/mapsdl",
serviceAccountPath: Deno.env.get("GOOGLE_APPLICATION_CREDENTIALS") || "./credentials/service-account.json",
gdriveFolders: {
aToK: "17QJ-Wzk9eMHKZqX227HkPCg9_Vmrf9h-",
lToZ: "1f3Oe65BngrSxTPKHAt6MEwK0FTsDbUsO",
},
concurrency: 5,
};
async function downloadSurfZonesSQL(): Promise<string> {
console.log(`[DL] Downloading SQL file from ${CONFIG.sqlUrl}...`);
const response = await fetch(CONFIG.sqlUrl);
if (!response.ok) {
throw new Error(`Failed to download SQL: ${response.statusText}`);
}
return await response.text();
}
function extractMapNamesFromSQL(sqlContent: string): Set<string> {
console.log("[>>] Extracting map names from SQL...");
const mapNames = new Set<string>();
const insertRegex = /INSERT INTO\s+`?(?:map)?zones`?\s+.*?VALUES\s*\((.*?)\);/gis;
for (const match of sqlContent.matchAll(insertRegex)) {
const valuesSection = match[1];
const stringRegex = /'([^']+)'/g;
for (const stringMatch of valuesSection.matchAll(stringRegex)) {
const value = stringMatch[1];
if (value.startsWith("surf_")) {
mapNames.add(value);
}
}
}
console.log(`[OK] Found ${mapNames.size} unique surf maps in SQL`);
return mapNames;
}
async function main() {
const args = parse(Deno.args);
console.log("[*] Surf Map Downloader\n");
console.log("━".repeat(60));
try {
const sqlContent = await downloadSurfZonesSQL();
const requiredMaps = extractMapNamesFromSQL(sqlContent);
const localMaps = await getLocalMaps(CONFIG.mapsDir);
const manifest = buildManifest(requiredMaps, localMaps);
console.log("\n[INFO] Summary:");
console.log(` Total maps in SQL: ${manifest.total}`);
console.log(` Already downloaded: ${manifest.found}`);
console.log(` Missing: ${manifest.missing.length}`);
if (manifest.missing.length === 0) {
console.log("\n[*] All maps are already downloaded!");
Deno.exit(0);
}
const client = new GoogleDriveClient();
await client.authenticate(CONFIG.serviceAccountPath);
const mapsToDownload = await searchGDriveForMaps(client, manifest, CONFIG.gdriveFolders, args.verbose === true);
if (mapsToDownload.size === 0) {
console.log("\n[!] No maps available to download from Google Drive");
Deno.exit(0);
}
if (args["dry-run"]) {
console.log("\n[END] Dry run complete. Use without --dry-run to download.");
Deno.exit(0);
}
const stats = await downloadAndExtractMaps(client, mapsToDownload, {
mapsDir: CONFIG.mapsDir,
tempDir: CONFIG.tempDir,
concurrency: CONFIG.concurrency,
});
console.log("\n" + "━".repeat(60));
console.log("[OK] Download Complete!\n");
console.log(`[DL] Successfully downloaded: ${stats.success} maps`);
console.log(`[X] Failed: ${stats.failed} maps`);
console.log(`[!] Not in Google Drive: ${manifest.notInGDrive.length} maps`);
console.log("━".repeat(60));
Deno.exit(stats.failed > 0 ? 1 : 0);
} catch (error) {
console.error(`\n[X] Fatal error: ${(error as Error).message}`);
if (args.verbose) {
console.error((error as Error).stack);
}
Deno.exit(1);
}
}
if (import.meta.main) {
main();
}
+94
View File
@@ -0,0 +1,94 @@
import { parse } from "https://deno.land/std@0.210.0/flags/mod.ts";
import {
GoogleDriveClient,
getLocalMaps,
buildManifest,
searchGDriveForMaps,
downloadAndExtractMaps,
} from "./common.ts";
function loadMapList(): string[] {
const listFile = Deno.env.get("MAPS_LIST_FILE");
if (listFile) {
const text = Deno.readTextFileSync(listFile);
return text.split("\n").map(s => s.replace(/\/\/.*/, "").trim()).filter(Boolean);
}
return (Deno.env.get("MAPS_WISHLIST") || "").split("\n").map(s => s.trim()).filter(Boolean);
}
const CONFIG = {
maps: loadMapList(),
mapsDir: Deno.env.get("MAPS_DIR") || "/home/ntr/surf_megastructure/data/cssds/cstrike/maps",
tempDir: Deno.env.get("TEMP_DIR") || "/tmp/mapsdl",
serviceAccountPath: Deno.env.get("GOOGLE_APPLICATION_CREDENTIALS") || "./credentials/service-account.json",
gdriveFolders: {
aToK: "17QJ-Wzk9eMHKZqX227HkPCg9_Vmrf9h-",
lToZ: "1f3Oe65BngrSxTPKHAt6MEwK0FTsDbUsO",
},
concurrency: 5,
};
async function main() {
const args = parse(Deno.args);
console.log("[*] Surf Map Downloader\n");
console.log("━".repeat(60));
try {
const requiredMaps = new Set(CONFIG.maps);
console.log(`[OK] Wishlist: ${requiredMaps.size} maps`);
const localMaps = await getLocalMaps(CONFIG.mapsDir);
const manifest = buildManifest(requiredMaps, localMaps);
console.log("\n[INFO] Summary:");
console.log(` Total maps in wishlist: ${manifest.total}`);
console.log(` Already downloaded: ${manifest.found}`);
console.log(` Missing: ${manifest.missing.length}`);
if (manifest.missing.length === 0) {
console.log("\n[*] All maps are already downloaded!");
Deno.exit(0);
}
const client = new GoogleDriveClient();
await client.authenticate(CONFIG.serviceAccountPath);
const mapsToDownload = await searchGDriveForMaps(client, manifest, CONFIG.gdriveFolders, args.verbose === true);
if (mapsToDownload.size === 0) {
console.log("\n[!] No maps available to download from Google Drive");
Deno.exit(0);
}
if (args["dry-run"]) {
console.log("\n[END] Dry run complete. Use without --dry-run to download.");
Deno.exit(0);
}
const stats = await downloadAndExtractMaps(client, mapsToDownload, {
mapsDir: CONFIG.mapsDir,
tempDir: CONFIG.tempDir,
concurrency: CONFIG.concurrency,
});
console.log("\n" + "━".repeat(60));
console.log("[OK] Download Complete!\n");
console.log(`[DL] Successfully downloaded: ${stats.success} maps`);
console.log(`[X] Failed: ${stats.failed} maps`);
console.log(`[!] Not in Google Drive: ${manifest.notInGDrive.length} maps`);
console.log("━".repeat(60));
Deno.exit(stats.failed > 0 ? 1 : 0);
} catch (error) {
console.error(`\n[X] Fatal error: ${(error as Error).message}`);
if (args.verbose) {
console.error((error as Error).stack);
}
Deno.exit(1);
}
}
if (import.meta.main) {
main();
}
+9 -3
View File
@@ -2,7 +2,13 @@
"folders":
[
{
"path": "."
}
]
"path": ".",
},
{
"path": "C:\\Users\\ntr\\code\\ntwl\\surf",
},
{
"path": "h:ome\\ntr\\ntwl\\surf",
},
],
}