Created
July 30, 2025 21:38
-
-
Save javrasya/68485be0c2a345b6e7b193b05b38bc2d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Generated by Zenith DSL Compiler | |
# DO NOT EDIT - This file is auto-generated | |
import textwrap | |
import time | |
from typing import Any, Dict, Iterable, List, Optional, Annotated, Literal | |
from pydantic import BaseModel, Field, model_validator | |
from src.backend.common import XButton | |
from src.backend.feature import Action, FeatureContext | |
from src.backend.feature.actions import ( | |
ButtonAction, ButtonClickAction, AxisAction, AxisOffsetAction, | |
KeyboardAction, KeyboardClickAction, ScheduledAction | |
) | |
from src.backend.featurev2.config import FeatureConfig | |
from src.backend.featurev2.feature import FeatureV2 | |
# User-defined imports (validated) | |
import random | |
class AutoPingConfig(FeatureConfig): | |
number_of_pings: int = Field( | |
title="# of Pings", | |
description="The number of pings to send once the firing starts. It might help to use more than 1 in situations where firing started before the aim is on the target. The reason is that ping on enemies will only be registered if the aim is on the target. Using some delays between pings will help to ensure that the aim is on the target more likely.", | |
default=1, | |
ge=1, | |
le=5, | |
changes_restart_backend=True | |
) | |
initial_delay_in_ms: int = Field( | |
title="Initial Delay", | |
description="The initial delay in milliseconds before the first ping is sent. This is to ensure that the aim is on the target more likely.", | |
default=100, | |
ge=0, | |
le=1000, | |
changes_restart_backend=True | |
) | |
min_delay_between_pings_ms: int = Field( | |
title="Min Delay", | |
description="The minimum delay between pings in milliseconds. The value is randomized between this and the max delay. The reason for randomizing is to make it less predictable to avoid detection.", | |
default=100, | |
ge=10, | |
le=3000, | |
changes_restart_backend=True | |
) | |
max_delay_between_pings_ms: int = Field( | |
title="Max Delay", | |
description="The maximum delay between pings in milliseconds. The value is randomized between this and the max delay. The reason for randomizing is to make it less predictable to avoid detection.", | |
default=150, | |
ge=10, | |
le=3000, | |
changes_restart_backend=True | |
) | |
ads_required: bool = Field( | |
title="ADS Required", | |
description="Whether the auto ping should only be activated when ADS is active. Checking this might help avoid unnecessary ping spam especially when driving a vehicle or when on menu.", | |
default=True, | |
changes_restart_backend=True | |
) | |
cooldown_in_ms: float = Field( | |
title="Cooldown", | |
description="The cooldown in milliseconds after the last ping is sent before the next ping action is activated upon a new firing event. This is to avoid removing the ping on the same target because there have been some intermitent firings by the player.", | |
default=500.0, | |
ge=100, | |
le=5000, | |
changes_restart_backend=True | |
) | |
@model_validator(mode="after") | |
def validate_rules(self): | |
if (self.min_delay_between_pings_ms >= self.max_delay_between_pings_ms): | |
raise ValueError("Minimum delay must be less than maximum delay") | |
return self | |
class AutoPingFeatureV2(FeatureV2[AutoPingConfig]): | |
@staticmethod | |
def name() -> str: | |
return "Auto Ping" | |
@staticmethod | |
def of(config: AutoPingConfig) -> "AutoPingFeatureV2": | |
return AutoPingFeatureV2(config=config) | |
def __init__(self, config: AutoPingConfig): | |
super().__init__() | |
self.config = config | |
self.current_pings: int = 0 | |
self.delay_between_pings_ms: int = None | |
self.last_ping_at: int = None | |
self.pinging: bool = False | |
def ping_with_delay(self): | |
if self.current_pings == 1: | |
# First ping with initial delay | |
yield ScheduledAction([ButtonClickAction(XButton.DPAD_UP)], run_at=int(time.time_ns() // 1_000_000) + self.config.initial_delay_in_ms) | |
else: | |
# Subsequent pings | |
yield ButtonClickAction(XButton.DPAD_UP) | |
def actions(self, context: FeatureContext, api_events: List[Dict[str, Any]]) -> Iterable[Action]: | |
current_ms = int(time.time_ns() // 1_000_000) | |
if not self.pinging and (self.last_ping_at is not None): | |
elapsed = (current_ms - self.last_ping_at) | |
if elapsed <= self.config.cooldown_in_ms: | |
return | |
is_firing = context.is_firing() | |
is_adsing = (context.is_adsing() if self.config.ads_required else True) | |
if (is_firing and is_adsing) and (self.current_pings < self.config.number_of_pings): | |
time_since_last = ((self.config.initial_delay_in_ms + 1) if (self.last_ping_at is None) else (current_ms - self.last_ping_at)) | |
if self.last_ping_at is None: | |
self.pinging = True | |
self.last_ping_at = current_ms | |
self.current_pings += 1 | |
self.delay_between_pings_ms = random.randint(self.config.min_delay_between_pings_ms, self.config.max_delay_between_pings_ms) | |
yield from self.ping_with_delay() | |
elif time_since_last > self.delay_between_pings_ms: | |
self.last_ping_at = current_ms | |
self.current_pings += 1 | |
self.delay_between_pings_ms = random.randint(self.config.min_delay_between_pings_ms, self.config.max_delay_between_pings_ms) | |
yield from self.ping_with_delay() | |
elif not is_firing and self.pinging: | |
self.pinging = False | |
self.current_pings = 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment