- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 445
- Реакции
- 10
Народ, кто плотно сидит в RuneScape и ищет способ автоматизировать рутину без моментального бана — нашел обновленный скрипт от NOM. Автор PilgrimMites допилил базу, добавив вменяемую хуманизацию. Теперь мышь не просто прыгает по координатам, а имитирует движение живого игрока с рандомизацией траекторий и задержек.
Что умеет этот скрипт:
Позволяет размечать до 4 цветовых групп точек, по 28 позиций на каждый цвет. Этого за глаза хватит для большинства задач по скиллингу или фарму.
Основные фичи апдейта:
Управление и хоткеи:
Скрипт поставляется "как есть". Для легитной игры на мейне — самое то, так как нет прямого вмешательства в память игры, всё работает через имитацию ввода. Но не забывайте про адекватные паузы, чтобы не словить репорт за 24/7 онлайн.
Кто уже гонял этот билд на жирных аккаунтах, как по детектам?
Что умеет этот скрипт:
Позволяет размечать до 4 цветовых групп точек, по 28 позиций на каждый цвет. Этого за глаза хватит для большинства задач по скиллингу или фарму.
Основные фичи апдейта:
- Улучшенная логика Humanization: мышь возвращается в исходную точку с небольшим разбросом.
- Рандомизированные клики и задержки (RandomDelay).
- Добавлены функции Click Box и Mouse Move для плавности.
- Всплывающие подсказки (ToolTip) с актуальными биндами.
- Возможность скрытия GUI-точек прямо во время работы.
Управление и хоткеи:
- CTRL + Numpad 1/2/3/4 — Поставить точку для соответствующей группы.
- Numpad 1/2/3/4 — Начать прокликивание по отмеченным точкам.
- ALT + Numpad 1/2/3/4 — Очистить точки группы.
- F5 — Показать/скрыть маркеры на экране.
- F6 — Полный выход из скрипта.
Код:
#NoEnv
SetWorkingDir %A_ScriptDir%
SendMode Input
#SingleInstance Force
#WinActivateForce
CoordMode, mouse, Screen
SetTimer, RemoveToolTip, -10000
ToolTip, Script Created by Nom`nUpdated By PilgrimMites`nCtrl+Numpad1-4 Add point`nAlt+Numpad1-4 Clear points`nNumpad1-4 Click points`nF6 to exit`nF5 toggle display,0,0
class JSON
{
class Load extends JSON.Functor
{
Call(self, ByRef text, reviver:="")
{
this.rev := IsObject(reviver) ? reviver : false
this.keys := this.rev ? {} : false
static quot := Chr(34), bashq := "\" . quot
, json_value := quot . "{[01234567890-tfn"
, json_value_or_array_closing := quot . "{[]01234567890-tfn"
, object_key_or_object_closing := quot . "}"
key := ""
is_key := false
root := {}
stack := [root]
next := json_value
pos := 0
while ((ch := SubStr(text, ++pos, 1)) != "") {
if InStr(" `t`r`n", ch)
continue
if !InStr(next, ch, 1)
this.ParseError(next, text, pos)
holder := stack[1]
is_array := holder.IsArray
if InStr(",:", ch) {
next := (is_key := !is_array && ch == ",") ? quot : json_value
} else if InStr("}]", ch) {
ObjRemoveAt(stack, 1)
next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"
} else {
if InStr("{[", ch) {
static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
(ch == "{")
? ( is_key := true
, value := {}
, next := object_key_or_object_closing )
: ( value := json_array ? new json_array : []
, next := json_value_or_array_closing )
ObjInsertAt(stack, 1, value)
if (this.keys)
this.keys[value] := []
} else {
if (ch == quot) {
i := pos
while (i := InStr(text, quot,, i+1)) {
value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")
static tail := A_AhkVersion<"2" ? 0 : -1
if (SubStr(value, tail) != "\")
break
}
if (!i)
this.ParseError("'", text, pos)
value := StrReplace(value, "\/", "/")
, value := StrReplace(value, bashq, quot)
, value := StrReplace(value, "\b", "`b")
, value := StrReplace(value, "\f", "`f")
, value := StrReplace(value, "\n", "`n")
, value := StrReplace(value, "\r", "`r")
, value := StrReplace(value, "\t", "`t")
pos := i
i := 0
while (i := InStr(value, "\",, i+1)) {
if !(SubStr(value, i+1, 1) == "u")
this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))
uffff := Abs("0x" . SubStr(value, i+2, 4))
if (A_IsUnicode || uffff < 0x100)
value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
}
if (is_key) {
key := value, next := ":"
continue
}
} else {
value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)
static number := "number", integer :="integer"
if value is %number%
{
if value is %integer%
value += 0
}
else if (value == "true" || value == "false")
value := %value% + 0
else if (value == "null")
value := ""
else
this.ParseError(next, text, pos, i)
pos += i-1
}
next := holder==root ? "" : is_array ? ",]" : ",}"
}
is_array? key := ObjPush(holder, value) : holder[key] := value
if (this.keys && this.keys.HasKey(holder))
this.keys[holder].Push(key)
}
}
return this.rev ? this.Walk(root, "") : root[""]
}
ParseError(expect, ByRef text, pos, len:=1)
{
static quot := Chr(34), qurly := quot . "}"
line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
, (expect == "") ? "Extra data"
: (expect == "'") ? "Unterminated string starting at"
: (expect == "\") ? "Invalid \escape"
: (expect == ":") ? "Expecting ':' delimiter"
: (expect == quot) ? "Expecting object key enclosed in double quotes"
: (expect == qurly) ? "Expecting object key enclosed in double quotes or object closing '}'"
: (expect == ",}") ? "Expecting ',' delimiter or object closing '}'"
: (expect == ",]") ? "Expecting ',' delimiter or array closing ']'"
: InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
: "Expecting JSON value(string, number, true, false, null, object or array)"
, line, col, pos)
static offset := A_AhkVersion<"2" ? -3 : -4
throw Exception(msg, offset, SubStr(text, pos, len))
}
Walk(holder, key)
{
value := holder[key]
if IsObject(value) {
for i, k in this.keys[value] {
v := this.Walk(value, k)
if (v != JSON.Undefined)
value[k] := v
else
ObjDelete(value, k)
}
}
return this.rev.Call(holder, key, value)
}
}
class Dump extends JSON.Functor
{
Call(self, value, replacer:="", space:="")
{
this.rep := IsObject(replacer) ? replacer : ""
this.gap := ""
if (space) {
static integer := "integer"
if space is %integer%
Loop, % ((n := Abs(space))>10 ? 10 : n)
this.gap .= " "
else
this.gap := SubStr(space, 1, 10)
this.indent := "`n"
}
return this.Str({"": value}, "")
}
Str(holder, key)
{
value := holder[key]
if (this.rep)
value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)
if IsObject(value) {
static type := A_AhkVersion<"2" ? "" : Func("Type")
if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
if (this.gap) {
stepback := this.indent
this.indent .= this.gap
}
is_array := value.IsArray
if (!is_array) {
for i in value
is_array := i == A_Index
until !is_array
}
str := ""
if (is_array) {
Loop, % value.Length() {
if (this.gap)
str .= this.indent
v := this.Str(value, A_Index)
str .= (v != "") ? v . "," : "null,"
}
} else {
colon := this.gap ? ": " : ":"
for k in value {
v := this.Str(value, k)
if (v != "") {
if (this.gap)
str .= this.indent
str .= this.Quote(k) . colon . v . ","
}
}
}
if (str != "") {
str := RTrim(str, ",")
if (this.gap)
str .= stepback
}
if (this.gap)
this.indent := stepback
return is_array ? "[" . str . "]" : "{" . str . "}"
}
} else
return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value)
}
Quote(string)
{
static quot := Chr(34), bashq := "\" . quot
if (string != "") {
string := StrReplace(string, "\", "\\")
, string := StrReplace(string, quot, bashq)
, string := StrReplace(string, "`b", "\b")
, string := StrReplace(string, "`f", "\f")
, string := StrReplace(string, "`n", "\n")
, string := StrReplace(string, "`r", "\r")
, string := StrReplace(string, "`t", "\t")
static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
while RegExMatch(string, rx_escapable, m)
string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
}
return quot . string . quot
}
}
Undefined[]
{
get {
static empty := {}, vt_empty := ComObject(0, &empty, 1)
return vt_empty
}
}
class Functor
{
__Call(method, ByRef arg, args*)
{
if IsObject(method)
return (new this).Call(method, arg, args*)
else if (method == "")
return (new this).Call(arg, args*)
}
}
}
Class JSONFile {
static Instances := []
__New(File) {
FileExist := FileExist(File)
JSONFile.Instances[this] := {File: File, Object: {}}
ObjRelease(&this)
FileObj := FileOpen(File, "rw")
if !IsObject(FileObj)
throw Exception("Can't access file for JSONFile instance: " File, -1)
if FileExist {
try
JSONFile.Instances[this].Object := JSON.Load(FileObj.Read())
catch e {
this.__Delete()
throw e
} if (JSONFile.Instances[this].Object = "")
JSONFile.Instances[this].Object := {}
} else
JSONFile.Instances[this].IsNew := true
return this
}
__Delete() {
if JSONFile.Instances.HasKey(this) {
ObjAddRef(&this)
JSONFile.Instances.Delete(this)
}
}
__Call(Func, Param*) {
if JSONFile.Instances[this].HasKey(Func)
return JSONFile.Instances[this][Func]
if (Func = "JSON")
return StrReplace(JSON.Dump(this.Object(),, Param.1 ? A_Tab : ""), "`n", "`r`n")
if (Func = "Save") {
try
New := this.JSON(Param.1)
catch e
return false
FileObj := FileOpen(this.File(), "w")
FileObj.Length := 0
FileObj.Write(New)
FileObj.__Handle
return true
}
if (Func = "Fill") {
if !IsObject(Param.2)
Param.2 := []
for Key, Val in Param.1 {
if (A_Index > 1)
Param.2.Pop()
HasKey := Param.2.MaxIndex()
? this.Object()[Param.2*].HasKey(Key)
: this.Object().HasKey(Key)
Param.2.Push(Key)
if IsObject(Val) && HasKey
this.Fill(Val, Param.2), Param.2.Pop()
else if !HasKey
this.Object()[Param.2*] := Val
} return
}
return Obj%Func%(this.Object(), Param*)
}
__Set(Key, Val) {
return this.Object()[Key] := Val
}
__Get(Key) {
return this.Object()[Key]
}
}
guiCount:=1
width:=30
height:=30
display := True
hoverColor := "Red"
points1:= []
points2:= []
points3:= []
points4:= []
init_points(points1,"Red")
init_points(points2,"Blue")
init_points(points3,"Green")
init_points(points4,"Teal")
SetTimer, hover, 1
return
Numpad1::
click_points(points1)
return
Numpad2::
click_points(points2)
return
Numpad3::
click_points(points3)
return
Numpad4::
click_points(points4)
return
^Numpad1::
hoverColor := "Red"
add_point(points1, "Red")
return
^Numpad2::
hoverColor := "Blue"
add_point(points2, "Blue")
return
^Numpad3::
hoverColor := "Green"
add_point(points3, "Green")
return
^Numpad4::
hoverColor := "Teal"
add_point(points4, "Teal")
return
!Numpad1::
clear_points(points1)
return
!Numpad2::
clear_points(points2)
return
!Numpad3::
clear_points(points3)
return
!Numpad4::
clear_points(points4)
return
F5::
display := !display
if (!display) {
hide_gui()
} else {
display_gui()
}
return
hover:
if (display) {
MouseGetPos, currx, curry
overlay_rect(currx, curry, width, height, 3, hoverColor, False)
}
return
init_points(ByRef points,color) {
global width, height, guiCount, js
tempPoints := []
For index, p In points
{
num := overlay_rect(p.currx, p.curry, width, height, 3, color, True)
tempPoints.push({"currx":p.currx,"curry":p.curry,"x1":p.x1,"y1":p.y1,"x2":p.x2,"y2":p.y2,"gui":p.num})
}
points := tempPoints
}
clear_points(ByRef points) {
For index, p In points
{
num := p.gui
Gui %num%: Destroy
}
points := []
}
add_point(ByRef points, color) {
global width, height, guiCount, js
if (points.MaxIndex() > 28) {
return
}
MouseGetPos, currx, curry
num := overlay_rect(currx, curry, width, height, 3, color)
x1 := currx - width/2
x2 := currx + width/2
y1 := curry - height/2
y2 := curry + height/2
points.push({"currx":currx,"curry":curry,"x1":x1,"y1":y1,"x2":x2,"y2":y2,"gui":num})
js.save()
}
click_points(ByRef points) {
MouseGetPos, currx, curry
For index, p In points
{
click_box(p.x1, p.y1, p.x2, p.y2)
Sleep, RandomDelay(40,60)
}
X1 := currx + Rand(10), Y1 := curry + Rand(10)
MouseMove(X1, Y1)
}
overlay_rect(X:=0, Y:=0, W:=0, H:=0, T:=3, cc:="Red", incr:=True) {
global guiCount
X -= W/2
Y -= H/2
w2:=W-T
h2:=H-T
txt := abs(mod(guiCount,99)+1)
Gui %txt%: +LastFound +AlwaysOnTop -Caption +ToolWindow +E0x08000000 +E0x80020
Gui %txt%: Color, %cc%
Gui %txt%: Show, w%W% h%H% x%X% y%Y% NA
WinSet, Transparent, 150
WinSet, Region, 0-0 %W%-0 %W%-%H% 0-%H% 0-0 %T%-%T% %w2%-%T% %w2%-%h2% %T%-%h2% %T%-%T%
if (incr) {
guiCount += 1
}
return txt
}
hide_gui() {
loop, 99 {
Gui %A_Index%: Hide
}
}
display_gui() {
loop, 99 {
Gui %A_Index%: +LastFound +AlwaysOnTop -Caption +ToolWindow +E0x08000000 +E0x80020
Gui %A_Index%: Show
}
}
click_box(x1, y1, x2, y2) {
ToolTip
x += PilgrimMites(x1,x2)
y += PilgrimMites(y1,y2)
MouseMove(x,y)
Click()
}
MouseMove(xTarget, yTarget, ErrorThreshold := 5, MinRandomDelay := 6, MaxRandomDelay := 8, PreMoveDelayMin := 20, PreMoveDelayMax := 30) {
Speed := PilgrimMites(.80,2.35)
MouseGetPos, xCurrent, yCurrent
xOffset := xTarget - xCurrent, yOffset := yTarget - yCurrent
distance := Sqrt(xOffset * xOffset + yOffset * yOffset) / Speed
xStep := xOffset / distance, yStep := yOffset / distance
Loop, % distance {
MouseMove, xCurrent += xStep, yCurrent += yStep, % RandomDelay(MinRandomDelay, MaxRandomDelay)
MouseGetPos, xNew, yNew
xError := xTarget - xNew, yError := yTarget - yNew
if (Sqrt(xError * xError + yError * yError) < ErrorThreshold) {
Sleep, 1
}
}
Sleep, PilgrimMites(PreMoveDelayMin, PreMoveDelayMax)
}
Rand(range=30) {
Random, r, -%range%, +%range%
Return R
}
RandRange(min, max) {
if (min > max) {
MsgBox, RandRange %ErrorLevel%
return -1
}
Random, rand, %min%, %max%
return rand
}
RandomDelay(min, max) {
return RandRange(min, max)
}
Click(Delay_Min:=35.0, Delay_Max:=60.0,SpamPrevent_Min:=35.0,SpamPrevent_Max:=60.0) {
DllCall("user32.dll\mouse_event", uint, 0x0002, int, 0, int, 0, uint, 0, int, 0)
Sleep, PilgrimMites(Delay_Min, Delay_Max)
DllCall("user32.dll\mouse_event", uint, 0x0004, int, 0, int, 0, uint, 0, int, 0)
Sleep, PilgrimMites(SpamPrevent_Min, SpamPrevent_Max)
return
}
PilgrimMites(M, H) {
Middle := ( M + H ) / 2
Random, r1, 0, Middle - M, %A_Now% . %A_IsCritical% . %A_TickCount%
Random, r2, 0, H - Middle, %A_Now% . %A_IsCritical% . %A_TickCount%
Anchor := M + r1 + r2
if (Anchor < M || Anchor > H) {
MsgBox, 49, Anchor Error, % "Invalid anchor: " . Anchor . "`nRestarting`nPlease contact PilgrimMites if this message appears."
Reload
} else {
Return Anchor
}
}
RemoveToolTip:
ToolTip
return
F6::ExitApp
Скрипт поставляется "как есть". Для легитной игры на мейне — самое то, так как нет прямого вмешательства в память игры, всё работает через имитацию ввода. Но не забывайте про адекватные паузы, чтобы не словить репорт за 24/7 онлайн.
Кто уже гонял этот билд на жирных аккаунтах, как по детектам?