Попросили тут у меня консультацию по вопросу цифровых значений репутации в игре. Казалось бы, все просто: в игровых файлах достаточно четко сформулированы правила пересчета внутриигровых значений репутации в те, что показываются пользователю. Однако при пристальном рассмотрении вопросы полезли как червячки, в результате чего пришлось лезть глубже, чем предполагалось, а в итоге появилась эта статья.
Немного истории.
Ни для кого, наверное, не является секретом, что репутация внутри игры и значение, показываемое нам в интерфейсе - это разные величины, хотя и жестко связанные между собой. Внутриигровое значение линейно. Когда бы вы ни убили врага - вы всегда получите одинаковый прирост репутации. Выводимое же пользователю значение высчитывается из внутриигрового по логарифмической шкале. Что это значит? А то, что для того чтобы повысить показываемую вам репутацию с 10 до 20, вам придется повысить внутриигровую на значение, в 10 раз больше, чем когда вы поднимаете репутацию с 0 до 10. А с 20 до 30 - еще в 10 раз больше.
Это общепринятая практика, так было не только в "иксах", а чуть ли не в любой игре. Пусть и без логарифмической шкалы, но чем выше уровень - тем больше надо набрать очков до следующего. Так же было и в старых "иксах", только до третьих "иксов" внутриигровое значение имело достаточно большие, целые величины (от -1 000 000 до +1 000 000). Начиная же с X Rebirth внутриигровое значение изменяется от -1 до +1 и стало значением с плавающей точкой.
Вернемся к постхребтовым реалиям.
Итак, что нам пишут разработчики в игровых файлах? А пишут они вот что:
Прежде всего определимся с терминами:
uivalue - это значение репутации, которое мы видим в интерфейсе. Имеет целые значения от -30 до +30. А вот
relation - это внутриигровое значение репутации, которое мы в игре не видим, но игра работает только именно с ними. Значения - от -1 до +1, с плавающей точкой.
Итак, разработчики сообщают нам, что ими принято несколько жестко фиксированных значений соответствий между
relation и
uivalue. Между этими значениями соответствия рассчитываются либо линейно (на небольшом участке между -0.0032 и +0.0032), либо по приведенным ими формулам (во всем остальном диапазоне).
Ну, вроде бы и ясно все... Но это лишь на первый взгляд. До тех пор, пока мы не возьмем калькулятор и не посчитаем. Ну, со значениями 1, 0.1 и 0.01 вроде бы все просто: они даже под формулы ложатся идеально. Допустим, пересчитаем
relation = 0.1 в
uivalue.
Как там у них?
uivalue = 10 * log10(relation * 1000)Ну, подставляем:
uivalue = 10 * log10(0.1 * 1000) = 10 * log10(100) = 10 * 2 = 20
Сошлось, ура!
Погодите радоваться... На самом деле даже с этим значением мы потом обломаемся, но об этом позже.
А сейчас пока посчитаем для
relation = 0.32. Егософты утверждают, что у нас должно получиться 25. Ну, считаем:
uivalue = 10 * log10(0.32 * 1000) = 10 * log10(320) = 10 * 2.5051499783199059760686944736225 = 25.051499783199059760686944736225
Ну, если приблизительно... - скажете вы?
А ну-ка, обратно посчитаем: из
uivalue = 25 в
relation. Опять же, по их формуле
relation = 10^(
uivalue / 10) / 1000
relation = 10^(25 / 10) / 1000 = 10^(2.5) / 1000 = 316.22776601683793319988935444327 / 1000 = 0.31622776601683793319988935444327
Оппа! Вот оно как, Михалыч!
Нет, "на глазок" - это, конечно, здорово, но что будет происходить между этими "фиксированными точками" и реальными? Когда "по формуле" одно значение, а "по точкам" - другое? Ведь "по формуле", например, 0.318 - это уже +25, а "по точкам" - еще нет... И как с этим бардаком разбирается игра?
И понял я, что надо проверять это на практике, прямо в игре.
С командами преобразований в скриптах очень бедно, я вам скажу. Что в MD/AI, что в lua. Единственное, что нашлось - это получение в MD
uivalue из
relation. Черный ящик. Как считает - черт его знает. Кинул число - она в тебя кинула другое. Сделал простенький цикл - и вычислил "реальные точки". Поскольку в сейвах больше шести значащих разрядов я никогда не встречал - значения искал с точностью именно до 6 значащих цифр.
Вот что получилось:
relation | uivalue |
0.999998 | 30 |
0.796213 | 29 |
0.633956 | 28 |
0.504765 | 27 |
0.401901 | 26 |
0.32 | 25 |
0.253583 | 24 |
0.200951 | 23 |
0.159243 | 22 |
0.126192 | 21 |
relation | uivalue |
0.0999998 | 20 |
0.0796213 | 19 |
0.0633956 | 18 |
0.0504765 | 17 |
0.0401901 | 16 |
0.032 | 15 |
0.0253583 | 14 |
0.0200951 | 13 |
0.0159243 | 12 |
0.0126192 | 11 |
relation | uivalue |
0.00999998 | 10 |
0.00796213 | 9 |
0.00633956 | 8 |
0.00504765 | 7 |
0.00401901 | 6 |
0.0032 | 5 |
0.00256 | 4 |
0.00192 | 3 |
0.00128 | 2 |
0.00064 | 1 |
Заключение.
Что мы видим в результате? А то, что действительность абсолютно не соответствует написанному разработчиками, за исключением пары мелочей. Достоверна информация о точках 0.32, 0.032 и 0.0032, а также о линейности преобразования на участке -0.0032 - +0.0032. Даже с 1, 0.1 и 0.01 - не соответствует действительности. Предваряя возможные вопросы: да, я пробовал прописать в сейве
relation = 0.999998 и загрузить в игру. Она исправно написала мне +30...
Другие значения с "фирменными" формулами тоже не совпадают. Например, "по формуле" репа +28 соответствует значению 0,63095734448019324943436013662234. На самом деле в игре - 0.633956.
Вывод: информация в libraries/factions.xml не соответствует действительности, а лишь приблизительна. В реальности точный алгоритм пересчета другой и мне он неизвестен. Однако зная точные значения, приведенные в таблице, получить
uivalue из
relation (и наоборот) достаточно просто. Находим ближайшее значение по модулю (без знака)
relation, равное или меньшее нашему - и смотрим, какому значению
uivalue оно соответствует. При отрицательном исходном значении - добавляем минус. Пересчет в обратную сторону - тоже аналогично.