В клиенте ESP собран из элементов: свечение, боксы, неймтеги, стрелки. У каждого в меню свои галочки по целям: игроки, мобы, животные, предметы, а у игроков ещё и по видам: я, друзья, пользователи Rockstar, остальные. Скрипт может добавить туда свой элемент и рисовать что угодно, а весь отбор целей останется на клиенте.
То есть тебе не нужно самому обходить мир, проверять типы сущностей и заводить настройки включения. Ты получаешь готовую цель и рисуешь.
el = Esp("esp.mybox", targets=["players", "mobs"], enable=["others"])
@el.render
def draw(entity, event):
render3d.box(event, entity, Color(255, 80, 80))Элемент появляется в меню ESP рядом со встроенными, со своими галочками и биндом на каждую цель, и сохраняется в конфиг вместе с ними.
Список targets говорит, какие вкладки меню элемент поддерживает. Игрок сам решит, что включить, а enable задаёт, что включено сразу после установки скрипта.
| Цель | Кто это |
|---|---|
players | Игроки. Делятся на виды: local, friends, rockstar_users, others |
mobs | Враждебные мобы |
animals | Мирные существа |
items | Лежащие на земле предметы |
el = Esp("esp.mybox", targets=["players", "mobs", "animals", "items"])
el.enable_for("local", "friends") # включить сразу для себя и друзейИногда галочек мало: рисовать только близких, только с малым здоровьем, только с определённым ником. Для этого есть filter. Он получает цель, которая уже прошла галочки, и решает, показывать её или нет.
el = Esp("esp.close", targets=["players"], enable=["others"])
@el.filter
def only_close(entity):
return entity.distanceTo(mc.player) < 20
@el.render
def draw(entity, event):
render3d.marker(event, [entity.getX(), entity.getY() + entity.getHeight(), entity.getZ()])Настройки объявляются так же, как у модуля, только первым аргументом идёт элемент. Они появятся в меню ESP под элементом.
el = Esp("esp.mybox", targets=["players"], enable=["others"])
color = ColorSetting(el, "esp.mybox.color")
filled = Checkbox(el, "esp.mybox.filled")
@el.render
def draw(entity, event):
if filled.get():
render3d.filled_box(event, entity, color.get())
else:
render3d.box(event, entity, color.get())render зовёт твою функцию на каждую цель каждый кадр. Когда целей десятки, дешевле получить их одним списком: render_all вызывается один раз за кадр и приносит всё, что прошло отбор.
el = Esp("esp.lines", targets=["players"], enable=["others"])
@el.render_all
def draw(entities, event):
me = [mc.player.getX(), mc.player.getEyeY(), mc.player.getZ()]
for entity in entities[:20]:
render3d.line(event, me, [entity.getX(), entity.getY(), entity.getZ()])Элемент рисует в мире. Если нужна плоская подпись у сущности, посчитай её место на экране через esp.to_screen и нарисуй в обычном render_2d. Метод вернёт None, если точка за спиной.
el = Esp("esp.labels", targets=["players"], enable=["others"])
seen = []
@el.render_all
def collect(entities, event):
seen.clear()
seen.extend(entities)
@events.render_2d
def draw(event):
for entity in seen:
point = esp.to_screen(entity.getX(), entity.getY() + entity.getHeight() + 0.4, entity.getZ())
if point is None:
continue
ctx = event.getContext()
ctx.drawText(font("medium", 7), entity.getName().getString(),
point[0], point[1], Color(255, 255, 255))| Вызов | Что делает |
|---|---|
Esp(name, targets, enable) | Новый элемент. targets и enable можно строкой или списком |
@el.render | Рисование одной цели: fn(entity, event) |
@el.render_all | Все цели кадра разом: fn(entities, event) |
@el.filter | Своя проверка: вернёт False, цель пропускается |
el.enable_for("players", "friends") | Что включено сразу после установки |
el.enabled() | Рисует ли элемент прямо сейчас |
el.remove() | Убрать элемент из ESP |
esp.enabled() | Включён ли сам модуль ESP |
esp.elements() | Имена всех элементов, своих и встроенных |
esp.to_screen(x, y, z) | Точка мира в координатах экрана или None |