├── .github ├── FUNDING.yml └── README.md ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── Cargo.toml ├── LICENSE ├── assets ├── favicon.ico ├── header.png └── icon.png ├── build └── main.rs ├── rustfmt.toml └── src ├── app.rs ├── gui.rs └── main.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: lencydev -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 |
2 | header 3 |
4 | Release 5 | License 6 | Downloads 7 | Forks 8 | Stars 9 |
10 | Ko-fi 11 |
12 | 13 | ## Features 14 | - **Color Detection:** Automatically fires when the configured enemy highlight color is detected in the trigger area. 15 | - **Customizable Trigger Area:** Define the size of the detection area at the center of your screen. 16 | - **Adjustable Trigger Delay:** Set a delay (in milliseconds) before firing after color detection. 17 | - **Configurable Trigger Keys:** Choose specific keyboard keys or mouse buttons to activate the triggerbot (hold mode). 18 | - **Color Tolerance:** Adjust the sensitivity of color detection to account for variations in lighting or effects. 19 | - **Resolution Setting:** Configure the application based on your in-game screen resolution. 20 | - **Simple GUI:** Easy-to-use interface for managing settings. 21 | 22 | # Usage 23 | 1. Download the latest release from the [releases](https://github.com/lencydev/valorant-triggerbot/releases) page. 24 | 2. Run the `valorant-triggerbot.exe` file. 25 | 3. Configure the settings in the application to match your preferences and in-game settings. 26 | 4. Click the `Enable` button to activate the triggerbot. 27 | 28 | ## Configuration 29 | Use the application's graphical interface to adjust the following settings: 30 | 31 | - **Resolution:** Set this to match your Valorant game resolution (e.g. 1920x1080). 32 | - **Trigger Keys:** Select the keys/buttons you want to hold to activate the triggerbot (only active if `Always Open` is off). 33 | - **Trigger Delay:** The time in milliseconds the bot waits after detecting the color before firing. Increase if it fires too early, decrease if too late. 34 | - **Trigger Area:** The size (in pixels) of the square area in the center of the screen where the bot looks for the target color. 35 | - **Target Color:** The RGB values of the enemy highlight color. Default is Purple (R 240 G 90 B 255). 36 | - **Color Tolerance:** How much variation from the Target Color is allowed. Higher values are more lenient but might cause false positives. Lower values are stricter. 37 | 38 | ### Valorant Settings 39 | These are the in-game settings required for the triggerbot to work correctly: 40 | - `General > Accessibility > Enemy Highlight Color:` Select `Purple` (or match the Target Color configured in the bot). 41 | - `Controls > Equipment > Weapons > Fire:` Set the secondary keybind to `K` (the bot simulates pressing `K`). 42 | 43 | ### Default Settings 44 | These are the default and recommended starting settings. 45 | Adjust them based on your needs. 46 | - `Resolution:` 1920x1080 47 | - `Trigger Keys:` Left Shift 48 | - `Trigger Delay:` 50ms 49 | - `Trigger Area:` 5.0 50 | - `Target Color:` Purple (R 240 G 90 B 255) 51 | - `Color Tolerance:` 50 52 | 53 | # Building from Source 54 | If you prefer to build the application yourself, follow these steps: 55 | 56 | 1. Ensure you have [Rust](https://www.rust-lang.org/tools/install) installed on your system. 57 | 2. Clone the repository: 58 | 59 | ```bash 60 | git clone https://github.com/lencydev/valorant-triggerbot.git 61 | cd valorant-triggerbot 62 | ``` 63 | 3. Build the project: 64 | 65 | ```bash 66 | cargo build --release 67 | ``` 68 | 4. After the compilation: 69 | - Navigate to the `target/release` directory. 70 | - Find the `valorant-triggerbot.exe` file. 71 | - Run the executable to start the application. 72 | 73 | # Disclaimer 74 | > [!WARNING] 75 | > Using third-party applications that interact with the game, like this triggerbot,
76 | > is against Riot Games' Terms of Service and can lead to account suspension or permanent ban.
77 | > Use this software entirely at your own risk. 78 | 79 | - While efforts may be made to avoid detection, anti-cheat systems like Vanguard are constantly updated, and detection is always a possibility. 80 | - The author is not responsible for any bans or other consequences resulting from the use of this software. 81 | 82 | # Support 83 | If you encounter issues or have questions, you can: 84 | - Check the [Troubleshooting](#troubleshooting) and [FAQ](#faq) sections below. 85 | - Message me on [discord](https://discord.com/users/313738210729656332). 86 | 87 | ## Troubleshooting 88 | - **Triggerbot not firing:** 89 | - Ensure Valorant's `Enemy Highlight Color` matches the bot's `Target Color`. 90 | - Verify the secondary fire keybind in Valorant is set to `K`. 91 | - Check if the `Resolution` setting in the bot matches your game resolution. 92 | - Make sure the bot is `Enabled`. 93 | - Try increasing `Color Tolerance` slightly. 94 | - Ensure the trigger area is positioned correctly over your crosshair. 95 | 96 | ## FAQ 97 | - **Q: Is this safe to use? Will I get banned?** 98 | - **A:** Using any third-party tool that gives an unfair advantage violates Valorant's ToS and carries a high risk of banning. Use at your own discretion. See the [Disclaimer](#disclaimer). 99 | - **Q: Does it work with different enemy highlight colors?** 100 | - **A:** Yes, but you need to manually configure the correct RGB values in the `Target Color` setting within the triggerbot application. 101 | - **Q: Does it work on all screen resolutions?** 102 | - **A:** It should work if you correctly set your game's resolution in the triggerbot's `Resolution` setting. 103 | - **Q: Can I change the key the bot presses to fire?** 104 | - **A:** Currently, the bot is hardcoded to press `K`. You need to set `K` as your secondary fire keybind in Valorant. Modifying this would require changing the source code. 105 | 106 | ## How it Works 107 | The triggerbot operates on a simple principle: 108 | 1. It continuously captures a small portion of your screen defined by the `Trigger Area` setting, centered around where your crosshair typically is. 109 | 2. It analyzes the pixels within this captured area. 110 | 3. If it finds pixels matching the configured `Target Color` (within the specified `Color Tolerance`), it assumes an enemy is under the crosshair. 111 | 4. After waiting for the configured `Trigger Delay`, it simulates a key press (`K` by default) to make the game fire. 112 | 113 |
114 | 115 |
116 | GUI 117 |
118 | 119 |
120 | 121 |
122 | 123 |
124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "rust-lang.rust-analyzer" 4 | ] 5 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | * Workbench 4 | **/ 5 | 6 | "workbench.colorTheme": "One Dark Pro Night Flat", 7 | "workbench.iconTheme": "material-icon-theme", 8 | 9 | /** 10 | * Editor 11 | **/ 12 | 13 | "editor.bracketPairColorization.enabled": true, 14 | "editor.codeActionsOnSave": { 15 | "source.fixAll": "always" 16 | }, 17 | "editor.codeLens": true, 18 | "editor.cursorSmoothCaretAnimation": "on", 19 | "editor.defaultFormatter": "rust-lang.rust-analyzer", 20 | "editor.fontFamily": "Fira Code", 21 | "editor.fontLigatures": true, 22 | "editor.formatOnPaste": true, 23 | "editor.formatOnSave": true, 24 | "editor.formatOnSaveMode": "file", 25 | "editor.guides.bracketPairs": true, 26 | "editor.linkedEditing": true, 27 | "editor.minimap.enabled": false, 28 | "editor.quickSuggestions": { 29 | "strings": "on" 30 | }, 31 | "editor.renderWhitespace": "none", 32 | "editor.smoothScrolling": true, 33 | "editor.stickyScroll.enabled": false, 34 | "editor.tabSize": 2, 35 | "editor.unicodeHighlight.includeStrings": false, 36 | 37 | /** 38 | * File Management 39 | **/ 40 | 41 | "files.associations": { 42 | "*.css": "tailwindcss" 43 | }, 44 | "files.autoSave": "afterDelay", 45 | "files.trimTrailingWhitespace": true, 46 | 47 | /** 48 | * Explorer 49 | **/ 50 | 51 | "explorer.compactFolders": false, 52 | "explorer.decorations.badges": true, 53 | "explorer.fileNesting.enabled": true, 54 | "explorer.fileNesting.expand": false, 55 | "explorer.sortOrder": "type", 56 | "explorer.sortOrderLexicographicOptions": "lower", 57 | 58 | /** 59 | * Terminal 60 | **/ 61 | 62 | "terminal.integrated.allowChords": true, 63 | "terminal.integrated.fontFamily": "Fira Code", 64 | "terminal.integrated.sendKeybindingsToShell": true, 65 | "terminal.integrated.smoothScrolling": true, 66 | 67 | /** 68 | * Git 69 | **/ 70 | 71 | "git.autofetch": true, 72 | "git.confirmSync": false, 73 | "git.enableSmartCommit": true, 74 | 75 | /** 76 | * Language Specific 77 | **/ 78 | 79 | "[markdown]": { 80 | "editor.wordWrap": "off" 81 | }, 82 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "valorant-triggerbot" 3 | version = "1.4.0" 4 | edition = "2021" 5 | build = "build/main.rs" 6 | 7 | [dependencies] 8 | screenshots = "0.8.10" 9 | device_query = "1.1.3" 10 | image = "0.24.9" 11 | winit = "0.29" 12 | eframe = "0.29.1" 13 | inputbot = "0.6" 14 | winapi = { version = "0.3.9", features = ["winuser", "windef"] } 15 | enigo = "0.1" 16 | 17 | [build-dependencies] 18 | winres = "0.1" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 lencydev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lencydev/valorant-triggerbot/160babac9c5a362daf3812787591b225c4fd41e0/assets/favicon.ico -------------------------------------------------------------------------------- /assets/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lencydev/valorant-triggerbot/160babac9c5a362daf3812787591b225c4fd41e0/assets/header.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lencydev/valorant-triggerbot/160babac9c5a362daf3812787591b225c4fd41e0/assets/icon.png -------------------------------------------------------------------------------- /build/main.rs: -------------------------------------------------------------------------------- 1 | use winres::WindowsResource; 2 | 3 | fn main () { 4 | 5 | if cfg!(target_os = "windows") { 6 | 7 | WindowsResource::new().set_icon("assets/favicon.ico").compile().unwrap(); 8 | } 9 | } -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 -------------------------------------------------------------------------------- /src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::gui; 2 | 3 | use device_query::{DeviceQuery, DeviceState, Keycode}; 4 | use eframe::{egui::Context, App, Frame}; 5 | use enigo::{Enigo, Key, KeyboardControllable}; 6 | use inputbot::MouseButton; 7 | use screenshots::Screen; 8 | 9 | use std::{ 10 | cmp::PartialEq, 11 | fmt::{Display, Formatter, Result}, 12 | thread, 13 | time::Duration, 14 | }; 15 | 16 | #[derive(PartialEq, Debug)] 17 | pub enum TriggerKey { 18 | Keyboard(Keycode), 19 | Mouse(MouseButton), 20 | } 21 | 22 | #[derive(PartialEq)] 23 | pub struct Settings { 24 | pub resolution: Resolution, 25 | pub trigger_keys: Vec, 26 | pub trigger_delay: u64, 27 | pub trigger_area: f32, 28 | pub target_color: [i32; 3], 29 | pub color_tolerance: i32, 30 | pub always_open: bool, 31 | } 32 | 33 | impl Default for Settings { 34 | fn default() -> Self { 35 | Self { 36 | resolution: Resolution { 37 | width: 1920, 38 | height: 1080, 39 | }, 40 | trigger_keys: vec![TriggerKey::Keyboard(Keycode::LShift)], 41 | trigger_delay: 50, 42 | trigger_area: 5.0, 43 | target_color: [240, 90, 255], 44 | color_tolerance: 50, 45 | always_open: false, 46 | } 47 | } 48 | } 49 | 50 | #[derive(PartialEq, Clone, Copy)] 51 | pub struct Resolution { 52 | pub width: u32, 53 | pub height: u32, 54 | } 55 | 56 | pub struct TriggerArea { 57 | pub x_percent: f32, 58 | pub y_percent: f32, 59 | pub width_percent: f32, 60 | pub height_percent: f32, 61 | } 62 | 63 | pub struct Triggerbot { 64 | pub enabled: bool, 65 | pub device_state: DeviceState, 66 | pub screen: Screen, 67 | pub trigger_area: TriggerArea, 68 | pub enigo: Enigo, 69 | pub settings: Settings, 70 | } 71 | 72 | impl Triggerbot { 73 | pub fn default() -> Self { 74 | let mut triggerbot = Self { 75 | enabled: false, 76 | device_state: DeviceState::new(), 77 | screen: Screen::from_point(0, 0).unwrap(), 78 | trigger_area: TriggerArea { 79 | x_percent: 0.0, 80 | y_percent: 0.0, 81 | width_percent: 0.0, 82 | height_percent: 0.0, 83 | }, 84 | enigo: Enigo::new(), 85 | settings: Settings::default(), 86 | }; 87 | 88 | triggerbot.update_trigger_area(); 89 | 90 | triggerbot 91 | } 92 | 93 | pub fn reset_settings(&mut self) { 94 | self.settings = Settings::default(); 95 | self.update_trigger_area(); 96 | } 97 | 98 | pub fn is_default_settings(&self) -> bool { 99 | self.settings == Settings::default() 100 | } 101 | 102 | pub fn set_resolution(&mut self, width: u32, height: u32) { 103 | self.settings.resolution = Resolution { width, height }; 104 | 105 | self.update_trigger_area(); 106 | } 107 | 108 | pub fn triggerbot(&mut self) { 109 | let keys = self.device_state.get_keys(); 110 | 111 | let trigger_active = !self.settings.always_open 112 | && self 113 | .settings 114 | .trigger_keys 115 | .iter() 116 | .any(|trigger| match trigger { 117 | TriggerKey::Keyboard(key) => keys.contains(key), 118 | TriggerKey::Mouse(button) => button.is_pressed(), 119 | }); 120 | 121 | if self.enabled 122 | && (trigger_active || self.settings.always_open) 123 | && self.is_target_color_present() 124 | { 125 | self.enigo.key_click(Key::Layout('k')); 126 | 127 | if self.settings.trigger_delay > 0 { 128 | thread::sleep(Duration::from_millis(self.settings.trigger_delay)); 129 | } 130 | } 131 | } 132 | 133 | fn is_target_color_present(&self) -> bool { 134 | let (width, height) = ( 135 | self.settings.resolution.width, 136 | self.settings.resolution.height, 137 | ); 138 | 139 | let x = (self.trigger_area.x_percent * width as f32) as i32; 140 | let y = (self.trigger_area.y_percent * height as f32) as i32; 141 | let w = (self.trigger_area.width_percent * width as f32) as u32; 142 | let h = (self.trigger_area.height_percent * height as f32) as u32; 143 | 144 | let capture = self.screen.capture_area(x, y, w, h).unwrap(); 145 | 146 | let pixels = capture.pixels(); 147 | 148 | let matching_pixels: Vec<_> = pixels 149 | .filter(|p| { 150 | p.0 151 | .iter() 152 | .zip(&self.settings.target_color) 153 | .all(|(a, b)| ((*a as i32) - b).abs() <= self.settings.color_tolerance) 154 | }) 155 | .collect(); 156 | 157 | !matching_pixels.is_empty() 158 | } 159 | 160 | pub fn update_trigger_area(&mut self) { 161 | let (width, height) = ( 162 | self.settings.resolution.width, 163 | self.settings.resolution.height, 164 | ); 165 | 166 | self.trigger_area = TriggerArea { 167 | x_percent: 0.5 - (self.settings.trigger_area / 2.0 / width as f32), 168 | y_percent: 0.5 - (self.settings.trigger_area / 2.0 / height as f32), 169 | width_percent: self.settings.trigger_area / width as f32, 170 | height_percent: self.settings.trigger_area / height as f32, 171 | }; 172 | } 173 | 174 | pub fn get_keys(&self) -> Vec { 175 | let mut triggers = vec![ 176 | TriggerKey::Mouse(MouseButton::LeftButton), 177 | TriggerKey::Mouse(MouseButton::MiddleButton), 178 | TriggerKey::Mouse(MouseButton::RightButton), 179 | TriggerKey::Mouse(MouseButton::X1Button), 180 | TriggerKey::Mouse(MouseButton::X2Button), 181 | ]; 182 | 183 | for key in vec![ 184 | Keycode::LShift, 185 | Keycode::RShift, 186 | Keycode::LControl, 187 | Keycode::RControl, 188 | Keycode::LAlt, 189 | Keycode::RAlt, 190 | Keycode::A, 191 | Keycode::F, 192 | Keycode::B, 193 | Keycode::G, 194 | Keycode::C, 195 | Keycode::H, 196 | Keycode::D, 197 | Keycode::I, 198 | Keycode::E, 199 | Keycode::J, 200 | Keycode::K, 201 | Keycode::P, 202 | Keycode::L, 203 | Keycode::Q, 204 | Keycode::M, 205 | Keycode::R, 206 | Keycode::N, 207 | Keycode::S, 208 | Keycode::O, 209 | Keycode::T, 210 | Keycode::U, 211 | Keycode::Z, 212 | Keycode::V, 213 | Keycode::Y, 214 | Keycode::W, 215 | Keycode::X, 216 | ] { 217 | triggers.push(TriggerKey::Keyboard(key)); 218 | } 219 | 220 | triggers 221 | } 222 | 223 | pub fn get_keys_display_name(&self, trigger: &TriggerKey) -> String { 224 | match trigger { 225 | TriggerKey::Keyboard(key) => match key { 226 | Keycode::LShift => "Left Shift".to_string(), 227 | Keycode::RShift => "Right Shift".to_string(), 228 | Keycode::LControl => "Left Control".to_string(), 229 | Keycode::RControl => "Right Control".to_string(), 230 | Keycode::LAlt => "Left Alt".to_string(), 231 | Keycode::RAlt => "Right Alt".to_string(), 232 | _ => format!("{:?}", key), 233 | }, 234 | TriggerKey::Mouse(key) => match key { 235 | MouseButton::LeftButton => "Mouse Left".to_string(), 236 | MouseButton::MiddleButton => "Mouse Middle (Wheel)".to_string(), 237 | MouseButton::RightButton => "Mouse Right".to_string(), 238 | MouseButton::X1Button => "Mouse Backward (X1)".to_string(), 239 | MouseButton::X2Button => "Mouse Forward (X2)".to_string(), 240 | _ => format!("{:?}", key), 241 | }, 242 | } 243 | } 244 | } 245 | 246 | impl App for Triggerbot { 247 | fn update(&mut self, ctx: &Context, _frame: &mut Frame) { 248 | gui::build(self, ctx); 249 | 250 | self.triggerbot(); 251 | 252 | ctx.request_repaint(); 253 | } 254 | } 255 | 256 | impl Display for Resolution { 257 | fn fmt(&self, f: &mut Formatter<'_>) -> Result { 258 | write!(f, "{}x{}", self.width, self.height) 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /src/gui.rs: -------------------------------------------------------------------------------- 1 | use crate::app::Triggerbot; 2 | 3 | use eframe::egui::{ 4 | Button, CentralPanel, Color32, ComboBox, Context, DragValue, Frame, RichText, ScrollArea, Slider, 5 | Stroke, Vec2, 6 | }; 7 | 8 | pub fn build(app: &mut Triggerbot, ctx: &Context) { 9 | CentralPanel::default().show(ctx, |ui| { 10 | ui.vertical(|ui| { 11 | ui.set_width(ui.available_width()); 12 | 13 | ui.group(|ui| { 14 | ui.set_width(ui.available_width()); 15 | 16 | ui.horizontal(|ui| { 17 | let mut width = app.settings.resolution.width; 18 | let mut height = app.settings.resolution.height; 19 | 20 | ui.label("Resolution:"); 21 | if ui 22 | .add(DragValue::new(&mut width).speed(1).range(1..=5000)) 23 | .changed() 24 | { 25 | app.set_resolution(width, app.settings.resolution.height); 26 | } 27 | ui.label("x"); 28 | if ui 29 | .add(DragValue::new(&mut height).speed(1).range(1..=5000)) 30 | .changed() 31 | { 32 | app.set_resolution(app.settings.resolution.width, height); 33 | } 34 | 35 | ui.checkbox(&mut app.settings.always_open, "Always Open"); 36 | }); 37 | 38 | ui.add_space(5.0); 39 | 40 | ui.horizontal(|ui| { 41 | ui.set_width(ui.available_width()); 42 | 43 | ui.label("Trigger Keys:"); 44 | 45 | ComboBox::from_id_salt("combobox_trigger_keys") 46 | .selected_text(format!("{} keys selected", app.settings.trigger_keys.len())) 47 | .width(160.0) 48 | .show_ui(ui, |ui| { 49 | ui.set_min_width(160.0); 50 | ui.set_max_height(80.0); 51 | 52 | ScrollArea::vertical().max_height(200.0).show(ui, |ui| { 53 | let available_triggers = app.get_keys(); 54 | 55 | for trigger in available_triggers { 56 | let mut is_selected = app.settings.trigger_keys.contains(&trigger); 57 | let display_name = app.get_keys_display_name(&trigger); 58 | 59 | if ui.checkbox(&mut is_selected, display_name).changed() { 60 | if is_selected && !app.settings.trigger_keys.contains(&trigger) { 61 | app.settings.trigger_keys.push(trigger); 62 | } else if !is_selected { 63 | if let Some(pos) = 64 | app.settings.trigger_keys.iter().position(|x| *x == trigger) 65 | { 66 | app.settings.trigger_keys.remove(pos); 67 | } 68 | } 69 | } 70 | } 71 | }); 72 | }); 73 | }); 74 | 75 | ui.add_space(5.0); 76 | 77 | ui.horizontal(|ui| { 78 | ui.set_width(ui.available_width()); 79 | 80 | ui.label("Trigger Delay (ms):"); 81 | ui.add(Slider::new(&mut app.settings.trigger_delay, 0..=3000)); 82 | }); 83 | 84 | ui.add_space(5.0); 85 | 86 | ui.horizontal(|ui| { 87 | ui.set_width(ui.available_width()); 88 | 89 | ui.label("Trigger Area:"); 90 | if ui 91 | .add(Slider::new(&mut app.settings.trigger_area, 5.0..=100.0)) 92 | .changed() 93 | { 94 | app.update_trigger_area(); 95 | } 96 | }); 97 | 98 | ui.add_space(5.0); 99 | 100 | ui.horizontal(|ui| { 101 | ui.set_width(ui.available_width()); 102 | 103 | ui.label("Target Color:"); 104 | 105 | let labels = ["R", "G", "B"]; 106 | 107 | for i in 0..3 { 108 | ui.label(labels[i]); 109 | ui.add( 110 | DragValue::new(&mut app.settings.target_color[i]) 111 | .speed(1) 112 | .range(0..=255), 113 | ); 114 | } 115 | 116 | Frame::none() 117 | .fill(Color32::from_rgb( 118 | app.settings.target_color[0] as u8, 119 | app.settings.target_color[1] as u8, 120 | app.settings.target_color[2] as u8, 121 | )) 122 | .stroke(Stroke::new(1.0, Color32::WHITE)) 123 | .inner_margin(Vec2::new(6.0, 6.0)) 124 | .show(ui, |_| {}); 125 | }); 126 | 127 | ui.add_space(5.0); 128 | 129 | ui.horizontal(|ui| { 130 | ui.set_width(ui.available_width()); 131 | 132 | ui.label("Color Tolerance:"); 133 | ui.add(Slider::new(&mut app.settings.color_tolerance, 0..=255)); 134 | }); 135 | }); 136 | 137 | ui.add_space(5.0); 138 | 139 | ui.horizontal(|ui| { 140 | ui.set_width(ui.available_width()); 141 | 142 | let (button_text, button_color) = if app.enabled { 143 | ("Disable", Color32::from_rgb(180, 100, 100)) 144 | } else { 145 | ("Enable", Color32::from_rgb(100, 180, 100)) 146 | }; 147 | 148 | if ui 149 | .add_sized( 150 | [ui.available_width() / 2.0, 30.0], 151 | Button::new(RichText::new(button_text).color(Color32::WHITE)).fill(button_color), 152 | ) 153 | .clicked() 154 | { 155 | app.enabled = !app.enabled; 156 | }; 157 | 158 | let is_default = app.is_default_settings(); 159 | 160 | let reset_button_color = if is_default { 161 | Color32::DARK_GRAY 162 | } else { 163 | Color32::from_rgb(100, 100, 180) 164 | }; 165 | 166 | let reset_button = Button::new(RichText::new("Reset Settings").color(Color32::WHITE)) 167 | .fill(reset_button_color) 168 | .sense(if is_default { 169 | eframe::egui::Sense::hover() 170 | } else { 171 | eframe::egui::Sense::click() 172 | }); 173 | 174 | if ui 175 | .add_sized([ui.available_width(), 30.0], reset_button) 176 | .clicked() 177 | && !is_default 178 | { 179 | app.reset_settings(); 180 | } 181 | }); 182 | }); 183 | }); 184 | } 185 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![windows_subsystem = "windows"] 2 | 3 | mod app; 4 | mod gui; 5 | 6 | use app::Triggerbot; 7 | use eframe::{ 8 | egui::{IconData, ViewportBuilder}, 9 | NativeOptions, 10 | }; 11 | 12 | fn main() -> Result<(), eframe::Error> { 13 | let options = NativeOptions { 14 | viewport: ViewportBuilder::default() 15 | .with_resizable(false) 16 | .with_transparent(true) 17 | .with_maximize_button(false) 18 | .with_inner_size([350.0, 212.0]) 19 | .with_icon(IconData { 20 | rgba: image::load_from_memory(include_bytes!("../assets/icon.png")) 21 | .unwrap() 22 | .to_rgba8() 23 | .to_vec(), 24 | width: 128, 25 | height: 128, 26 | }), 27 | ..Default::default() 28 | }; 29 | 30 | eframe::run_native( 31 | "Valorant Triggerbot (v1.4.0)", 32 | options, 33 | Box::new(|_cc| Ok(Box::new(Triggerbot::default()))), 34 | ) 35 | } 36 | --------------------------------------------------------------------------------