Как работает заточка в RF Online (и могут ли админы «подкрутить» её кому-то)
Интро
English version:
Привет. Продолжаем разбирать ZoneServer (ZoneServerUD_x64.exe из сборки 2232). В прошлый раз был общий , а сегодня самая мистическая тема: заточка. Также ответим на вопрос: могут ли админы подкрутить шанс отдельным людям, например стримерам? Разберём по коду, с формулами и цифрами, а в конце отметим на этот вопрос.
Содержание:
Что вообще кладётся в заточку
Формула шанса (с примерами)
Что происходит при провале
Что при этом видит игрок
Заточка модификатором у «Героя»
Так можно ли «подкрутить» стримеру?
Если коротко
Часть 1. Что вообще кладётся в заточку
Когда вы жмёте «заточить», клиент шлёт серверу пакет (7,17), который на сервере разбирает обработчик UpgradeItemRequest и передаёт в CPlayer::pc_UpgradeItem. В заточку идёт вот такой набор:
сам предмет, который точим. Оружие (код 6) или броня (коды 0 - 7);
Предметы в RF разложены по таблицам-типам, и у каждого типа свой номер, табличный код: оружие = 6, талик = 18, инструмент = 11, куски брони это коды 0-7 и так далее. По этому номеру сервер и понимает, что за предмет ему подсунули. Поэтому в коде талик проверяется как «код 18», а инструмент как «код 11».
Клиент не шлёт предметы целиком, он шлёт ссылки на них: где предмет лежит и какой у него серийник. Структура запроса (7,17) (_upgrade_item_request_clzo, 29 байт):
Код:
_STORAGE_POS_INDIV m_posUpgItem; // предмет, который точим
_STORAGE_POS_INDIV m_posTalik; // талик
_STORAGE_POS_INDIV m_posToolItem; // инструмент
uint8_t byJewelNum; // сколько камней приложено (0..4)
_STORAGE_POS_INDIV m_posUpgJewel[4]; // сами камни
где каждая «позиция» это 4 байта: в каком «хранилище» предмет, его серийник и количество:
Пример: точим меч из сумки (серийник 5), таликом (серийник 12), с инструментом (серийник 20) и двумя камнями (серийники 30 и 31). Тогда пакет заполнен так:
Талик и камни при попытке расходуются (сгорают независимо от результата). Дальше сервер проверяет кучу условий: предмет не залочен, у него есть свободные сокеты, талик вообще подходит к этому предмету, и так далее. Если что-то не так, приходит код ошибки и попытка отменяется.
Часть 2. Формула шанса (с примерами)
Шанс считается по формуле. Вот она целиком:
Код:
итоговое число = базовое[грейд][сокет] x (fRate / 4) x 100 x (30 / уровень предмета)
где fRate это вклад камней (разберём в Шаге 2). Итоговое число это «сколько шансов из 100000»: сервер бросает случайное число 0..99999, и если оно меньше итогового, засчитывается успех. А теперь по шагам, откуда каждый множитель.
Шаг 1. Базовое число из таблицы, зашитой прямо в сервер (не конфиг, не файл, а константы в бинарнике). Индекс по грейду предмета и по номеру сокета (сколько уже вставлено).
Код:
грейд | 1-й 2-й 3-й 4-й 5-й 6-й 7-й | что это
------+------------------------------------------+------------------------------
0..3 | 1000 750 500 250 100 50 0 | тип-N, тип-B, тип-A, тип-C
4 | 328 246 164 82 49 16 0 | реликт
5 | 640 480 320 160 96 32 0 | розовое (сет лидера гильдии)
6 | 512 384 256 128 77 26 0 | Элан-оружие
7 | 410 307 205 102 61 20 0 | оружие Баала?, прем-броня
8 | 800 600 400 200 120 40 0 | Леон
9 | 262 197 131 66 39 13 0 | PvP-оружие
10 | 210 157 105 52 31 10 0 | не используется
Грейды 0-3 делят одну строчку с одинаковыми числами, дальше у каждого грейда своя. Грейд 10 в игре не носит ни один предмет (либо я не нашел), он живёт только в этой таблице.
Шаг 2. Камни дают множитель (fRate). Сервер складывает 4 слота под камни: занятый слот = сила камня, пустой считается за 0.125. Реальные значения камней (вытащено из ItemUpgrade.dat):
Шаг 3. Штраф за уровень предмета. Итог умножается ещё на 30 / уровень предмета: чем выше требуемый уровень шмотки, тем ниже шанс. А на низкоуровневой шмоте это, наоборот, жирный бонус (оружие 5 ур. -> x6), поэтому мелочь точится легко.
Как именно бросается кубик (по шагам)
посчитали итоговое число (например, 54545);
бросок кубика: случайное число от 0 до 99999;
если кубик меньше итогового числа -> успех. Иначе -> провал.
Если итоговое = 54545, выигрышных вариантов кубика ровно 54545 из 100000, значит шанс успеха 54.5%. Выпал кубик 30000 (меньше) -> успех. Выпал 70000 (больше) -> провал. Если итоговое больше или равно 100000 -> гарантированный успех.
Шкала броска кубика при заточке.
А вот тот же расчёт кодом (из pc_UpgradeItem, слегка причёсано):
Код:
// сумма 4 слотов под камни: занятый слот = сила камня, пустой = 0.125
float fRate = 0.0f;
for (int i = 0; i < 4; ++i)
fRate += pJewelFld[i] ? pJewelFld[i]->m_fJewelFieldValue : 0.125f;
byItemGrade = GetItemGrade(item); // грейд предмета 0..10
byUgrLv = GetItemUpgedLv(item->m_dwLv); // сколько таликов уже вставлено (наш "+N")
// базовое из таблицы * (fRate / 4) * 100
dwTotalRate = (int)( (float)s_dwItemUpgSucRate[byItemGrade][byUgrLv] * fRate / 4.0f * 100.0f );
// штраф/бонус за уровень предмета
byEquipLv = GetItemEquipLevel(item);
if (byEquipLv)
dwTotalRate = (int)( (float)dwTotalRate * (30.0f / byEquipLv) );
// одно большое случайное число из двух вызовов rand()
dwRand = rand() + (rand() << 16);
if (m_bCheat_100SuccMake) // GM-чит "всегда успех" (см. Часть 5)
dwTotalRate = 0xFFFFFFFF;
if (dwTotalRate > dwRand % 100000)
// === УСПЕХ: вставляем талик в сокет ===
else
// === ПРОВАЛ: рулетка потерь (см. Часть 3) ===
(pJewelFld[i] тут это запись камня в i-м слоте, или пусто, если слот не занят.)
Конкретные примеры
Возьмём броню грейда 1 (это Тип-B, в народе «инт»), требуемый уровень 55, первый сокет (базовое = 1000):
без камней (fRate = 4 x 0.125 = 0.5): 1000 x (0.5/4) x 100 x (30/55) ~ 6818 -> шанс ~6.8%;
+4 камня т3 (по 1.0, fRate = 4.0): 1000 x (4.0/4) x 100 x (30/55) ~ 54545 -> шанс ~54.5%;
тот же предмет, но уровень 30, +4 камня т3: 1000 x 1.0 x 100 x 1.0 = 100000 -> гарантия.
При заточке на +5 того же предмета (базовое = 100), даже с 4 топ-камнями (fRate = 12): 100 x (12/4) x 100 x (30/55) ~ 16363 -> всего ~16%.
Про +7: в старых версиях да, в 2.2.3.2 нет
Обратите внимание: 7-й столбец таблицы = 0 у всех грейдов. Ноль в базовом шансе даёт итог = 0 x ... = 0, а «кубик меньше 0» невозможен. То есть на 2.2.3.2 заточить на +7 руками, таликом из инвентаря, нельзя вообще, потолок +6.
На старых апдейтах это было можно: там таблица была проще, и 7-й шаг имел микрошанс, а не ноль. Это разбирали ещё в 2008 на примере версии Giga3, где 7-й столбец был 1, а не 0 — руками +7 было сделать можно, хоть и очень маловероятно. В 2.2.3.2 +7 ставится только модификатором через комбинацию у НПС «Герой».
Часть 3. Что происходит при провале
Провалить бросок это ещё не всё: дальше сервер отдельно решает, что именно ты теряешь. Вот эта логика кодом (ветка провала в pc_UpgradeItem):
Код:
else // основной бросок не прошёл - заточка не удалась
{
// Бросок 1: уничтожается ли сам предмет?
if (s_dwItemMissRate[byItemGrade][byUgrLv] <= rand() % 10000)
{
// предмет уцелел. Бросок 2: сбросить ли уже вставленные талики?
if (s_dwTalikMissRate[byItemGrade][byUgrLv] <= rand() % 10000)
byErrCode = 100; // ничего не потеряно (сгорели только талик + камни)
else {
Emb_ItemUpgrade(item, RESET); // все сокеты обнуляются
byErrCode = 101; // заточка слетела в ноль
}
}
else {
Emb_DelStorage(item); // предмет уничтожен
byErrCode = 102;
}
}
То есть при неудаче бросается ещё до двух кубиков, каждый по своей зашитой таблице:
Бросок 1 — уничтожение предмета. Берётся число s_dwItemMissRate[грейд][сокет] (из 10000) и сравнивается со случайным rand() % 10000. Если табличное число больше случайного — предмет уничтожается, иначе уцелел. Простыми словами: шанс уничтожения = s_dwItemMissRate / 100 %.
Бросок 2 — сброс заточки (только если предмет уцелел). Точно так же, но со второй таблицей: шанс обнуления сокетов = s_dwTalikMissRate / 100 %. Если не сбросилось — теряешь только талик и камни, а предмет и вся уже набитая заточка целы.
Итого три исхода: предмет цел (код 100), заточка обнулилась (101), предмет уничтожен (102).
Вот обе таблицы уже в процентах, по грейду и номеру сокета.
Грейд 8 (Леон) уничтожается при любом провале со 100% (вся строка первой таблицы). Без права на ошибку.
Грейды 0-3 на первых сокетах не ломаются вовсе (нули слева в первой таблице), риск копится к последним.
Обнуление заточки к поздним сокетам почти гарантировано (95%): провалил высокую точку и предмет уцелел — почти наверняка сокеты слетят в ноль.
Первый сокет во второй таблице везде 0 — логично, обнулять ещё нечего.
Всё выше описаное можно выразить блок-схемой:
Блок-схема попытки заточки.
Часть 4. Что при этом видит игрок
А почти ничего. В ответ на попытку клиенту прилетает пакет (7,18) ровно в один байт: код результата. Ни шанса, ни бросков кубика, ни промежуточных рулеток клиент не знает и в принципе не видит. Он показывает вам анимацию и итог, а вся математика остаётся на сервере.
Зато сервер про каждую попытку помнит всё. Каждая заточка пишется в лог-файл истории предметов игрока строкой вида:
То есть у держателя сервера есть полный аудит: кто, что, когда точил и чем закончилось. У игрока такого доступа нет.
Часть 5. Заточка модификатором у «Героя»
Комбинация у «Героя» устроена совсем иначе, чем ручная заточка: тут нет броска на успех и нельзя сломать предмет. Модификатор просто выбирает один из своих готовых результатов — например +5, +6 или +7, — как лотерея, где у каждого варианта своя доля шанса.
Рулетка выбора результата модификатора.
Проще всего представить рулетку, разбитую на сектора: чем больше шанс у варианта, тем шире его сектор. Сервер её «крутит» (бросает число от 0 до 9999) и смотрит, в чей сектор попало — тот вариант и выпадает. Пример (доли условные, настоящие лежат в CombineTable.dat):
Выпало, скажем, 7200 — это сектор +6, предмет становится +6. Заточка каждого варианта заранее прописана в рецепте, поэтому сервер просто ставит её на предмет: гарантированно, без всяких «сгорит / уцелеет».
Если совсем коротко кодом, ядро выбора выглядит так:
Код:
int roll = rand() % 10000; // "крутим рулетку"
int acc = 0;
for (каждый вариант рецепта) {
acc += вариант.шанс; // накапливаем доли секторов
if (roll < acc) { // число попало в сектор этого варианта
выбрали его;
break;
}
}
// заточка выбранного варианта уже готова в рецепте - сервер просто ставит её на предмет
Разберём по шагам тот же пример (+5 вес 6000, +6 вес 3000, +7 вес 1000):
Первый вариант +5 (вес 6000): acc = 0 + 6000 = 6000. Проверка 7200 < 6000? — нет, идём дальше.
Второй вариант +6 (вес 3000): acc = 6000 + 3000 = 9000. Проверка 7200 < 9000? — да -> выпал +6, стоп.
Готово: предмет становится +6. Смысл в том, что числа 0-5999 достаются +5, 6000-8999 -> +6, 9000-9999 -> +7; наш 7200 попал во второй кусок. Чем больше вес, тем шире кусок и тем чаще вариант выпадает.
Ещё пара бросков для наглядности: roll = 300 -> сразу 300 < 6000 -> +5; roll = 9500 -> мимо +5 и +6, 9500 < 10000 -> +7.
Часть 6. Так можно ли «подкрутить» стримеру?
Да, можно.
Мы уже видели: шанс считает обработчик на сервере, по таблицам, зашитым в его же бинарник. Всё это целиком под контролем того, кто держит сервер. Вот, что лежит в том же самом обработчике заточки, за пару строк до броска кубика:
Код:
if (m_bCheat_100SuccMake)
dwTotalRate = 0xFFFFFFFF; // -> итоговое число огромное, кубик всегда меньше -> 100% успех
Это готовый встроенный флаг «всегда успех». В оригинальной игре он включается GM-командой (%god hand включить, %chicken hand выключить) и используется и для крафта, и для заточки. То есть механизм «сделать 100%» уже есть в коде из коробки, но только для GM-аккаунтов.
На практике исходников зон-сервера ни у кого нет: все серверы крутят один и тот же оригинальный бинарник, когда-то давно утёкший в сеть. Но модифицировать его легко и без исходников — через хук.
Хук (от англ. hook, «крючок») это способ вклиниться в чужую функцию на лету: перехватить вызов и подсунуть свою логику до или вместо оригинальной, не трогая сам код программы. Поведение игр так правят сплошь и рядом, это стандартная и несложная операция.
Схема хука на функцию заточки.
Дальше дело техники: держишь список нужных ников (в файле, в базе, в каком-нибудь кэше) и в хуке для них подкручиваешь исход — включаешь тот самый флаг m_bCheat_100SuccMake (всегда успех) или просто подменяешь переменную с результатом броска на нужную. Так отдельным людям можно увеличить шанс, а с клиента это выглядит просто как «ну повезло». Проверить это со стороны игрока невозможно: клиент видит один байт результата, а шанс, флаги и логика живут на сервере.
Цитата:
Суть.Со стороны игрока нельзя на 100% проверить, что творится во внутрянке сервера. Клиент видит один байт результата, а шанс, флаги и вся логика живут в закрытом бинаре у держателя сервера, где он волен менять что угодно хуком или патчем. «У всех одинаковый шанс» это не проверяемый факт, а обещание, в которое можно только верить.
Если коротко
Формула для расчета успеха: базовое[грейд][сокет] x fRate/4 x 100 x 30/уровень = «итоговое число» (fRate = сумма 4 слотов под камни), потом кубик из 100000, и успех если кубик меньше итогового.
Каждый следующий сокет труднее, а 7-й шаг = 0%: руками на 2.2.3.2 потолок +6. +7 ставится только модификатором через комбинацию у Героя: там результат (+5/+6/+7) выпадает по «рулетке» из рецепта.
Камни умножают шанс (сила от 0.25 у т1 до 3.0 у топового; пустой слот 0.125), уровень предмета шанс снижает (x 30/уровень, а на низком уровне наоборот бонус).
При провале бросается ещё до двух кубиков: сначала на уничтожение предмета, потом (если уцелел) на обнуление заточки. Сколько первых сокетов безопасны зависит от грейда (грейд 0 — четыре, грейд 3 — только первый); грейд 8 уничтожается при любом провале со 100%.
Клиент видит один байт результата, сервер пишет полный лог каждой попытки себе.
Подкрутить отдельному человеку технически очень просто (хук на функцию заточки + список ников), а со стороны игрока внутрянку нельзя проверить. Поэтому «у всех честно» на закрытом сервере это вопрос доверия, а не проверки.
Числа взяты из сборки 2232: формула и таблицы взяты напрямую из бинаря ZoneServerUD_x64.exe (pc_UpgradeItem), значения камней из ItemUpgrade.dat, механизм комбинации из ItemCombineMgr. Независимое подтверждение алгоритма (старая версия Giga3, 2008): разбор на rf-cheats. Названия грейдов это клиентская условность, сервер оперирует номерами 0-10; на другой сборке/версии детали могут отличаться.
Спасибо!!! буду изучать.
Ты написал что если будет интересно то продолжишь писать и затронешь тему об уроне и о логике попадания... Сколько челов должно подписаться чтобы ты решил что интересно?)
Последний раз редактировалось SlGMA; 05.08.2026 в 22:35.
Tempus fugit, carpe momentum et memento te mortalem esse.
Спасибо!!! буду изучать.
Ты написал что если будет интересно то продолжишь писать и затронешь тему об уроне и о логике попадания... Сколько челов должно подписаться чтобы ты решил что интересно?)
А прости конечно,
Но что именно ты собирался изучать?
Нормальные игроки руофа...кто не пьянь и не бомж-студент
Всё что выше +4 точили модами всегда
-
Это имеется ввиду 2232 - до приколов Савельева с 70 уровнем реликтов и леонов
Когда создали никогда не существовавшую линейку оружия с собственными % заточки и правилами
-
Клоуны которые с т2 точили до +2 - остались в 215 апе и 2007 году
Просто игра то ебанутая была от Корейцев
На любом официальном сервере
т4 комплект стоил практически как т5 конверт если в шопе купить
Да, от старости сервера и в процессе накопления бесполезных ресов
цены на т4 комплекты могли уйти вниз
Но именно то как эти камни добывались - через жопу и совсем не как глю
Делало процесс заточки +5 руками с т4 - абсолютно не эффективным занятием
============================
А на счёт - админы могут крутить
Ну там джейды ещё можно интересные делать которые в сумке полежат незаметно
PPS:
просто когда общаешься даже со старыми* игроками - очень многие из них, были слишком молоды в те времена, когда игра официально начиналась в России
Они просто бегали мясом и им было весело
Они не понимали что эта игра про +7 предметы
И всё что +4+5 - это вообще другие вещи и имело мало смысла; чем они заточены и как.
[QUOTE=Педро;3105236]А прости конечно,
Но что именно ты собирался изучать?
Друже, я изучаю все что только могу накопать в любых некропостах и просто инфу от неравнодушных людей, которые видят мои потуги и идут навстречу) за что всем спасибо большое!
Диантро затронул давно погибший раздел, и это внушает надежду)) может что то и получится из этого. как говорится в знаменитой присказке:
- будем посмотреть
Tempus fugit, carpe momentum et memento te mortalem esse.
Комбинация у «Героя» устроена совсем иначе, чем ручная заточка: тут нет броска на успех и нельзя сломать предмет. Модификатор просто выбирает один из своих готовых результатов — например +5, +6 или +7, — как лотерея, где у каждого варианта своя доля шанса.
предметы из рецепта таки можно сломать.
разбери кейс когда сумма шансов в слотах результатов меньше 10к и попадёшь как раз в обработку FailOutItem, который и рулит тем чёж там сгорит.
ps: если на дефолтные скрипты посмотришь, то обнаружишь скам модики, где результат на +7 прописан, но никогда не выпадет из-за реализации круток.