Skip to content
This repository was archived by the owner on Aug 16, 2025. It is now read-only.

Commit 83da980

Browse files
authored
modern ui
1 parent 93f7c35 commit 83da980

File tree

8 files changed

+459
-143
lines changed

8 files changed

+459
-143
lines changed

ChangeLog.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
### Summary
22

3-
- **Modularization:** The project is divided into logical modules.
3+
- **Modern Look:** A custom style sheet was added to improve the appearance of the application.
44

5-
- **Configuration Management:** The settings are loaded from and saved to `%LOCALAPPDATA%\Requests\ItsJesewe\esp_config.json`. The `_update_config` class method ensures that missing keys are added.
5+
- **Improved Error Handling:** More try/except blocks and error messages help catch and show errors clearly.
66

7-
- **Error Handling:** If the target game process (`cs2.exe`) is not found or another error occurs during initialization, an error signal is emitted. The GUI then displays a QMessageBox instead of crashing.
8-
9-
- **Global Hotkeys:** The `keyboard` module registers F6 and F7 as global hotkeys to start and stop the overlay even when the application is not active.
10-
11-
- **Enhanced Drawing:** The overlay displays the nickname above the box and a vertical health progress bar whose color changes with health.
7+
![Downloads](https://img.shields.io/github/downloads/Jesewe/cs2-esp/v1.0.1/total?style=for-the-badge&logo=github&color=D5006D) ![Platforms](https://img.shields.io/badge/platform-Windows-blue?style=for-the-badge&color=D5006D) ![License](https://img.shields.io/github/license/jesewe/cs2-triggerbot?style=for-the-badge&color=D5006D)

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252

5353
- **PyMeow Module:**
5454
PyMeow is a dependency for overlay drawing.
55-
1. Visit the [PyMeow GitHub Releases page](https://github.com/qb-0/pyMeow/releases) and download the latest `pyMeow*.zip` release.
56-
2. Install PyMeow using pip:
55+
Visit the [PyMeow GitHub Releases page](https://github.com/qb-0/pyMeow/releases) and download the latest `pyMeow*.zip` release.
56+
Install PyMeow using pip:
5757
```bash
5858
pip install pyMeow*.zip
5959
```

classes/config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from pyMeow import get_color, fade_color
44

55
# Define the current version of the application.
6-
CURRENT_VERSION = "1.0.0"
6+
CURRENT_VERSION = "v1.0.1"
77

88
# Define the configuration directory and file.
99
CONFIG_DIR = os.path.join(os.environ.get("LOCALAPPDATA", "."), "Requests", "ItsJesewe")
@@ -16,6 +16,7 @@
1616
"box_line_thickness": 1.2, # Default box line thickness
1717
"box_color_hex": "#FFA500", # Default enemy box outline (Orange)
1818
"text_color_hex": "#FFFFFF", # Default text color (White)
19+
"draw_health_numbers": False, # Whether to display health numbers
1920
"use_transliteration": True, # Whether to use transliteration for player names
2021
"draw_teammates": False, # Whether to display ESP for teammates
2122
"teammate_color_hex": "#00FFFF" # Default teammate box outline (Cyan)
@@ -28,6 +29,7 @@ def __init__(self):
2829
self.box_line_thickness = DEFAULT_CONFIG["box_line_thickness"]
2930
self.box_color_hex = DEFAULT_CONFIG["box_color_hex"]
3031
self.text_color_hex = DEFAULT_CONFIG["text_color_hex"]
32+
self.draw_health_numbers = DEFAULT_CONFIG["draw_health_numbers"]
3133
self.use_transliteration = DEFAULT_CONFIG["use_transliteration"]
3234
self.draw_teammates = DEFAULT_CONFIG["draw_teammates"]
3335
self.teammate_color_hex = DEFAULT_CONFIG["teammate_color_hex"]
@@ -48,6 +50,7 @@ def load(self) -> None:
4850
self.box_line_thickness = data.get("box_line_thickness", self.box_line_thickness)
4951
self.box_color_hex = data.get("box_color_hex", self.box_color_hex)
5052
self.text_color_hex = data.get("text_color_hex", self.text_color_hex)
53+
self.draw_health_numbers = data.get("draw_health_numbers", self.draw_health_numbers)
5154
self.use_transliteration = data.get("use_transliteration", self.use_transliteration)
5255
self.draw_teammates = data.get("draw_teammates", self.draw_teammates)
5356
self.teammate_color_hex = data.get("teammate_color_hex", self.teammate_color_hex)
@@ -64,6 +67,7 @@ def save(self) -> None:
6467
"box_line_thickness": self.box_line_thickness,
6568
"box_color_hex": self.box_color_hex,
6669
"text_color_hex": self.text_color_hex,
70+
"draw_health_numbers": self.draw_health_numbers,
6771
"use_transliteration": self.use_transliteration,
6872
"draw_teammates": self.draw_teammates,
6973
"teammate_color_hex": self.teammate_color_hex,

classes/cs2esp.py

Lines changed: 68 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
import logging
12
import requests
23
import pymem
34
import pyMeow as overlay
4-
from typing import Iterator, Optional, Dict, Any
5+
from typing import Iterator, Optional, Dict
56
from classes.utils import read_vec3, read_string, read_floats, transliterate
67
from classes.config import Offsets, Colors, overlay_settings
78
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
8-
import logging
99

1010
logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(message)s')
1111

12+
# Constants for entity iteration
13+
ENTITY_COUNT = 64
14+
ENTITY_ENTRY_SIZE = 120
1215

1316
class Entity:
1417
"""
@@ -28,34 +31,53 @@ def name(self) -> str:
2831

2932
@property
3033
def health(self) -> int:
31-
return self.mem.read_int(self.pawn_ptr + Offsets.m_iHealth)
34+
try:
35+
return self.mem.read_int(self.pawn_ptr + Offsets.m_iHealth)
36+
except Exception as e:
37+
logging.error("Failed to read health: %s", e)
38+
return 0
3239

3340
@property
3441
def team(self) -> int:
35-
return self.mem.read_int(self.pawn_ptr + Offsets.m_iTeamNum)
42+
try:
43+
return self.mem.read_int(self.pawn_ptr + Offsets.m_iTeamNum)
44+
except Exception as e:
45+
logging.error("Failed to read team: %s", e)
46+
return -1
3647

3748
@property
3849
def pos(self) -> Dict[str, float]:
39-
return read_vec3(self.mem, self.pawn_ptr + Offsets.m_vOldOrigin)
50+
try:
51+
return read_vec3(self.mem, self.pawn_ptr + Offsets.m_vOldOrigin)
52+
except Exception as e:
53+
logging.error("Failed to read position: %s", e)
54+
return {"x": 0.0, "y": 0.0, "z": 0.0}
4055

4156
@property
4257
def dormant(self) -> bool:
43-
return bool(self.mem.read_int(self.pawn_ptr + Offsets.m_bDormant))
58+
try:
59+
return bool(self.mem.read_int(self.pawn_ptr + Offsets.m_bDormant))
60+
except Exception as e:
61+
logging.error("Failed to read dormant flag: %s", e)
62+
return True
4463

4564
def bone_pos(self, bone: int) -> Dict[str, float]:
46-
game_scene = self.mem.read_longlong(self.pawn_ptr + Offsets.m_pGameSceneNode)
47-
bone_array_ptr = self.mem.read_longlong(game_scene + Offsets.m_pBoneArray)
48-
return read_vec3(self.mem, bone_array_ptr + bone * 32)
65+
try:
66+
game_scene = self.mem.read_longlong(self.pawn_ptr + Offsets.m_pGameSceneNode)
67+
bone_array_ptr = self.mem.read_longlong(game_scene + Offsets.m_pBoneArray)
68+
return read_vec3(self.mem, bone_array_ptr + bone * 32)
69+
except Exception as e:
70+
logging.error("Failed to get bone position for bone %d: %s", bone, e)
71+
return {"x": 0.0, "y": 0.0, "z": 0.0}
4972

5073
def world_to_screen(self, view_matrix: list) -> bool:
5174
try:
5275
self.pos2d = overlay.world_to_screen(view_matrix, self.pos, 1)
5376
self.head_pos2d = overlay.world_to_screen(view_matrix, self.bone_pos(6), 1)
77+
return True
5478
except Exception as e:
5579
logging.error("world_to_screen conversion failed: %s", e)
5680
return False
57-
return True
58-
5981

6082
class CS2Esp:
6183
"""
@@ -80,32 +102,36 @@ def load_offsets(self) -> None:
80102
Loads game offsets and field mappings from remote JSON resources.
81103
"""
82104
try:
83-
offsets_url = "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/offsets.json"
84-
with requests.get(offsets_url) as offsets_response:
105+
# Use a session for improved performance and timeout handling
106+
with requests.Session() as session:
107+
offsets_url = "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/offsets.json"
108+
offsets_response = session.get(offsets_url, timeout=10)
85109
offsets_response.raise_for_status()
86110
offsets_data = offsets_response.json()
87-
keys = ["dwViewMatrix", "dwEntityList", "dwLocalPlayerController", "dwLocalPlayerPawn"]
88-
for key in keys:
89-
setattr(Offsets, key, offsets_data["client.dll"][key])
90111

91-
client_dll_url = "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/client_dll.json"
92-
with requests.get(client_dll_url) as client_dll_response:
112+
# Load required offset keys
113+
keys = ["dwViewMatrix", "dwEntityList", "dwLocalPlayerController", "dwLocalPlayerPawn"]
114+
for key in keys:
115+
setattr(Offsets, key, offsets_data["client.dll"].get(key))
116+
117+
client_dll_url = "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/client_dll.json"
118+
client_dll_response = session.get(client_dll_url, timeout=10)
93119
client_dll_response.raise_for_status()
94120
client_dll_data = client_dll_response.json()
95121

96-
mapping = {
97-
"m_iIDEntIndex": "C_CSPlayerPawnBase",
98-
"m_hPlayerPawn": "CCSPlayerController",
99-
"m_fFlags": "C_BaseEntity",
100-
"m_iszPlayerName": "CBasePlayerController",
101-
"m_iHealth": "C_BaseEntity",
102-
"m_iTeamNum": "C_BaseEntity",
103-
"m_vOldOrigin": "C_BasePlayerPawn",
104-
"m_pGameSceneNode": "C_BaseEntity",
105-
"m_bDormant": "CGameSceneNode",
106-
}
107-
for field, cls in mapping.items():
108-
setattr(Offsets, field, client_dll_data["client.dll"]["classes"][cls]["fields"][field])
122+
mapping = {
123+
"m_iIDEntIndex": "C_CSPlayerPawnBase",
124+
"m_hPlayerPawn": "CCSPlayerController",
125+
"m_fFlags": "C_BaseEntity",
126+
"m_iszPlayerName": "CBasePlayerController",
127+
"m_iHealth": "C_BaseEntity",
128+
"m_iTeamNum": "C_BaseEntity",
129+
"m_vOldOrigin": "C_BasePlayerPawn",
130+
"m_pGameSceneNode": "C_BaseEntity",
131+
"m_bDormant": "CGameSceneNode",
132+
}
133+
for field, cls in mapping.items():
134+
setattr(Offsets, field, client_dll_data["client.dll"]["classes"][cls]["fields"].get(field))
109135
except Exception as e:
110136
raise Exception(f"Error loading offsets: {e}")
111137

@@ -120,10 +146,6 @@ def iterate_entities(self) -> Iterator[Entity]:
120146
logging.error("Error reading entity list or local controller pointer: %s", e)
121147
return iter([])
122148

123-
# Constants used for entity list indexing
124-
ENTITY_COUNT = 64
125-
ENTITY_ENTRY_SIZE = 120
126-
127149
for i in range(1, ENTITY_COUNT + 1):
128150
try:
129151
list_index = (i & 0x7FFF) >> 9
@@ -164,7 +186,7 @@ def draw_entity(self, entity: Entity, view_matrix: list, is_teammate: bool = Fal
164186
overlay_settings.teammate_color_hex if is_teammate else overlay_settings.box_color_hex
165187
)
166188
text_color = overlay.get_color(overlay_settings.text_color_hex)
167-
189+
# Optionally draw snaplines
168190
if overlay_settings.draw_snaplines:
169191
screen_width = overlay.get_screen_width()
170192
screen_height = overlay.get_screen_height()
@@ -235,6 +257,16 @@ def draw_entity(self, entity: Entity, view_matrix: list, is_teammate: bool = Fal
235257
fill_height,
236258
fill_color
237259
)
260+
# Optionally draw health numbers
261+
if getattr(overlay_settings, 'draw_health_numbers', False):
262+
health_text = f"{entity.health}"
263+
overlay.draw_text(
264+
health_text,
265+
int(bar_x - 25),
266+
int(bar_y + bar_height / 2 - 5),
267+
10,
268+
text_color
269+
)
238270
except Exception as e:
239271
logging.error("Error drawing entity: %s", e)
240272

@@ -290,7 +322,6 @@ def stop(self) -> None:
290322
"""Stops the overlay loop."""
291323
self.running = False
292324

293-
294325
class OverlayWorker(QObject):
295326
"""
296327
A Qt worker class for running the CS2 ESP overlay in a separate thread.

0 commit comments

Comments
 (0)