Ровно 20 лет назад, 8 июня 2004 года, в корейской компании NCSoft был скомпилирован файл L2Server.exe - основной компонент игрового сервера новейшей на тот момент ММО игры Lineage II The chaotic chronicle: Chronicle 1 - Harbingers of War. В результате произошедших затем событий, всех подробностей которых мы вероятно никогда не узнаем, этот файл, вместе с сопутствующими компонентами, данными и скриптами стал, так скажем, "достоянием общественности", дав начало эре неофициальных серверов, а также огромной популярности Lineage 2 в СНГ, и не только. В этой, и последующих, статьях мы познакомимся с техническими подробностями и секретами как клиента, так и сервера этой игры, некоторые из которых не были широко известны не только игрокам, но и администраторам серверов.

Дисклеймер: Вся информация предоставляется исключительно в ознакомительных целях и получена из открытых источников. Автор не является, и никогда не являлся, сотрудником компании NCSoft или её партнёров, не заключал с ними никаких соглашений, и не имеет никакого отношения и никакой информации касательно произошедших сливов.

В качестве подопытного будем использовать клиент и сервер C1, как в те времена, а также инструментарий тех времён: отладчик OllyDbg с плагином ODbgScript и дизассемблер IDA. Несмотря на то, что некоторую информацию и инструменты сейчас можно просто нагуглить, пройдем весь путь с нуля, как если бы мы оказались в 2004 году, так что никаких питонов, гидр, и прочего новодела.

Начнём с изучения клиента. В корне клиента лежит файл LineageII.exe - но это лаунчер, нам он не нужен. Можно удалить, чтоб не мешался. Настоящий exe клиента, вместе с dll и конфигами, находится в System и называется l2.bin. Переименуем его в l2.exe и убедимся что клиент нормально запускается.

Экран логина клиента
Экран логина клиента

Настраиваем клиент

Итак, свежеустановленный оригинальный клиент стартует в полноэкранном режиме, а при попытке логина будет пытаться залогиниться на официальный сервер. Нужно разобраться с этими недоразумениями - сделать так, чтоб клиент запускался в окне и логинился на локальный сервер. Клиент основан на модифицированном движке UnrealEngine. В System находится много ini файлов, однако они зашифрованы или запакованы:

l2.ini - виден заголовок, а дальше - ничего не понятно
l2.ini - виден заголовок, а дальше - ничего не понятно

Разберёмся с этим. Загрузим клиент под дебаггером, поставим брейкпоинт на CreateFileA и CreateFileW, запустим, проскипаем до места, где будет открываться l2.ini. Выйдя из функции kernel32 попадаем сюда:

После срабатывания брейкпоинта на CreateFileW и выхода из функции
После срабатывания брейкпоинта на CreateFileW и выхода из функции

Теперь поставим брейкпоинт на ReadFile. После брейка видим такой стек:

Стек после срабатывания брейкпоинта на ReadFile
Стек после срабатывания брейкпоинта на ReadFile

Поставим брейкпоинт на доступ к памяти по адресу Buffer + 0x20 (пропускаем заголовок файла), запускаем, срабатывает брейк в core.dll. Выходим из функции, попадаем сюда:

После срабатывания брейкпоинта на доступ к памяти и выхода из функции шифрования
После срабатывания брейкпоинта на доступ к памяти и выхода из функции шифрования

Функция шифрования оказалась в экспорте dll-ки, так что даже не нужно гадать чем зашифровано. Добрые корейцы делают всё для людей :) Выйдя еще на уровень выше, попадаем сюда:

Функция шифрования с захардкоженным ключом имеет криптостойкость равную нулю
Функция шифрования с захардкоженным ключом имеет криптостойкость равную нулю

А вот и ключ шифрования. Теперь можно написать дешифровщик и шифровщик, реализацию алгоритма BlowFish возьмём из OpenSSL.

#define La2IniHeaderSize 0x1C

const unsigned char l2_ini_enc_key[] = "[;'.]94-&@%!^+]-31==";

void La2IniDecryptVer212(uint8_t * buf, size_t buf_size) {
	BF_KEY key;

	BF_set_key(&key, sizeof(l2_ini_enc_key), l2_ini_enc_key);

	for (size_t offs = La2IniHeaderSize; offs + BF_BLOCK < buf_size; offs += BF_BLOCK) {
		BF_decrypt((unsigned int *)(buf + offs), &key);
	}
}

Впрочем, все давно сделано за нас, так что можно воспользоваться тулзой dstuff l2encdec. В расшифрованном l2.ini пропишем:

ServerAddr=127.0.0.1
StartupFullscreen=False

Затем зашифруем обратно и положим файл в System. Теперь клиент стартует в безрамочном окне и логинится на 127.0.0.1:2106. Можно запустить локальный сервер и начать развлекаться. Запуск сервера - это отдельная большая тема, которую я не буду рассматривать в этой статье, отмечу лишь что большинство экспериментов проводилось на самописном минималистичном сервере, на который можно только зайти и соло побегать, так что не удивляйтесь отсутствию мобов и НПЦ.

Находим аргументы командной строки

Теперь посмотрим, принимает ли клиент какие-то аргументы командной строки. Ставим брейкпоинт на GetCommandLineA и GetCommandLineW, запускаем. Срабатывает брейк на GetCommandLineW. Трейсим до выхода из функции, ставим брейк на доступ к памяти по адресу EAX. Брейк срабатывает в функции:

Core.?ParseParam@@YAHPBG0@Z ; ParseParam(ushort const *,ushort const *)

Поскольку она вызывается много раз, воспользуемся скриптом для ODbgScript чтобы сдампить все аргументы:

cycle:
log [esp+4]
log [esp+8]
run
jmp cycle

В результате получаем вот такой список:

Hidden text

STRICT
CONFLICTS
NOGC
NOMMX
NOSSE
SERVER
LAZY
LOG
server
BENCHMARK
320x240
512x384
640x480
800x600
1024x768
1280x960
1280x1024
1600x1200
FirstRun
safe
defaultres
nodeviceid
lanplay
nomusic
NOSOUND
nomusic
windowed
RECORDMOVIE
MEMSTAT

А декомпилировав в IDA функцию ParseParam выясняем, что аргументы должны быть с префиксом '-' или '/':

int __cdecl ParseParam(const unsigned __int16 *a1, wchar_t *Str)
{
  ...
  if ( !v2 )
  {
    while ( 1 )
    {
      v3 = appStrfind(v3 + 1, Str);
      if ( !v3 )
        break;
      if ( v3 > a1 )
      {
        v4 = *(v3 - 1);
        if ( v4 == '-' || v4 == '/' )
          return 1;
      }
    }
  }
  return 0;
}

Настало время воспользоваться полученными знаниями. В первую очередь интересен аргумент LOG, который запускает клиент с открытой игровой консолью:

Клиент запущен с открытой консолью
Клиент запущен с открытой консолью

Из прочих команд:

  • windowed - по идее должна включать оконный режим но не работает, вероятнее StartupFullscreen из l2.ini приоритетнее;

  • RECORDMOVIE - таки записывает видео, но в виде кучи скриншотов;

  • MEMSTAT - пишет в лог статистику при закрытии клиента.

Добываем список консольных команд

Исследуем что же можно сделать через игровую консоль. Подбором обнаруживаем что работают команды exit и quit. Эти строки встречаются в файлах Engine.dll и Core.dll. Грузим Engine.dll и находим где используются эти строки:

.text:104D14A2                 lea     edx, [ebp+arg_0]
.text:104D14A5                 push    offset aExit    ; "EXIT"
.text:104D14AA                 push    edx
.text:104D14AB                 call    edi ; ParseCommand(ushort const * *,ushort const *) ; ParseCommand(ushort const * *,ushort const *)
.text:104D14AD                 add     esp, 8
.text:104D14B0                 cmp     eax, ebx
.text:104D14B2                 jnz     loc_104D17C6
.text:104D14B8                 lea     eax, [ebp+arg_0]
.text:104D14BB                 push    offset aQuit    ; "QUIT"
.text:104D14C0                 push    eax
.text:104D14C1                 call    edi ; ParseCommand(ushort const * *,ushort const *) ; ParseCommand(ushort const * *,ushort const *)

ParseCommand - это функция ?ParseCommand@@YAHPAPBGPBG@Z из Core.dll.

Теперь запустим клиент под дебаггером и поставим брейкпоинт на ParseCommand. Введя произвольную команду, обнаруживаем что команды действительно парсятся этой функцией. Теперь можно сдампить список похожим скриптом:

cycle:
log [[esp+4]]
log [esp+8]
run
jmp cycle

В итоге получаем такой список:

Hidden text

OPEN
START
SERVERTRAVEL
DISCONNECT
RECONNECT
EXIT
QUIT
GETCURRENTTICKRATE
GETMAXTICKRATE
GSPYLITE
SAVEGAME
CANCEL
SOUND_REBOOT
SHOWEXTENTLINECHECK
SHOWLINECHECK
SHOWPOINTCHECK
KDRAW
KSTEP
KSTOP
KSAFETIME
MEMSTAT
CONFIGHASH
EXIT
QUIT
RELAUNCH
DEBUG
DIR
MEM
DUMPNATIVES
GET
SET
OBJ
GTIME
DUMPCACHE
SHOWLOG
TakeFocus
EditDefault
EditActor
CopyToClipboard
HideLog
Preferences
BRIGHTNESS
CONTRAST
GAMMA
PAUSESOUNDS
UNPAUSESOUNDS
STOPSOUNDS
WEAPONRADIUS
ROLLOFF
GRAPH
L2Debug
L2DebugWindow
FLUSH
STAT
CRACKURL
PACKETCOUNTSTART
PACKETCOUNTSTOP

Введя команду PACKETCOUNTSTART, получаем такую статистику:

Человеческие названия пакетов - как удобно, спасибо корейцам.
Человеческие названия пакетов - как удобно, спасибо корейцам.

Нужно больше команд!

Известно, что существуют команды, отдаваемые через чат клиента, например /loc - показывает текущие координаты персонажа. Поэкспериментировав с разными префиксами обнаруживаем, команды с префиксом /// исполняются аналогично введенным в консоли. Кроме того, список xrefs на ParseCommand в IDA намекает, что команд может быть больше, чем мы обнаружили. Еще есть префикс //, используемый для административных команд, и оба эти префикса работают только если у персонажа статус GM-а.

Попробуем аналогично сдампить список команд, введенных с префиксом. Правда оказывается, что ParseCommand также используется движком для обработки команд PlayerPawnMoveTo, CameraYaw и прочих, так что придется помучиться с этим спамом прежде чем получить искомый результат. В итоге получаем вот такой список:

Hidden text

BUTTON
PULSE
TOGGLE
AXIS
JOYPAD
COUNT
KEYNAME
LOCALIZEDKEYNAME
KEYBINDING
L2Restart
Warp
rwarp
MoveWarp
L2WaterInfo
L2WaterReflect
EnterChat
L2EVENTON
L2EVENTOFF
GETITEM
TARGETCHANGE
SHOWCOMPASS
HIDECOMPASS
SCENE0
SCENE1
ANTIPORTAL
TELEPORT
WAITMODECHANGE
MOVEMODECHANGE
CONTROLLERVIEW
PAWNVIEW
SPAWNPLAYERPAWN
DeletePlayer
SPAWNACTOR
SPAWNNPCS
SPAWNPCS
AUTOSPAWNPC
PlayerMove
DumpActor
SPAWNVEHICLES
SPAWNITEM
SPAWNEDPAWNMOVETO
STOPPAWNMOVING
DEFAULTCAMERA
FIXEDDEFAULTCAMERA
TURNBACK
MESHCHANGE
TEXTURECHANGE
DISTANCEFOG
DISTANCEFOGRANGE
PERSPECTIVE
GROUNDSPEEDUP
GROUNDSPEEDDOWN
CAMERAVIEWHEIGHTADJUST
ZOOMINHOLD
ZOOMOUTHOLD
ZOOMINPRESS
ZOOMOUTPRESS
SELECTINGCANCEL
TextCapture
Crash
PLAYERPAWNMOVETO
KEYBOARDBACKMOVESTART
KEYBOARDBACKMOVEFINISH
KEYBOARDMOVESTART
KEYBOARDMOVEFINISH
JOYSTICKMOVE
LEFTTURNINGSTART
LEFTTURNINGFINISH
RIGHTTURNINGSTART
RIGHTTURNINGFINISH
STEPMOVE
COMBOANIMPLAY
CHANGEANIM
CheckGrp
Addabnormal
deleteabnormal
Lodchange
fh
shake
Env Reload
SETTIME
SETTIMERATIO
CancelMAGICTEST
DeleteSelectedActor
pv
PawnViewer
nv
NpcViewer
sv
SkillViewer
Cast
SkillRemain
addcubic
decubic
cubicskill
ATTACKSPEEDDOWN
ATTACKSPEEDUP
setwyvern
SVS
BoneSim
ReduceLOD
KeepMinFrame
SkipAnim
Hitwater
SHADOW
DEFAULTSHADOW
RIDE
UNRIDE
ANIMPLAY
CAMERAPITCH
CAMERAYAW
YAWTURN
TRANSFER
BuildZone
LoadPath
Limit
C_TELEPORT
C_RMODE
GEODATA
SEAMLESS
MAPLOC
SHOWBORDERLINE
SHOWSECTORS
SaveMemInfo
CacheTexture
DUMPRESOURCEHASH
FIRSTCOLOREDMIP
NEARCLIP
D3DRESOURCES
SUPPORTEDRESOLUTION
ISFULLSCREEN
GETPING
INJECT
NETSPEED
LANSPEED
SHOWALL
REPORT
SHOT
SHOWACTORS
HIDEACTORS
RMODE
REND
SHOW
CINEMATICS
CINEMATICSRATIO
FIXEDVISIBILITY
TOGGLEREFRAST
EXEC
SHOWEXTENTLINECHECK
SHOWLINECHECK
SHOWPOINTCHECK
KDRAW
KSTEP
KSTOP
KSAFETIME
OPEN
START
SERVERTRAVEL
DISCONNECT
RECONNECT
EXIT
QUIT
GETCURRENTTICKRATE
GETMAXTICKRATE
GSPYLITE
SAVEGAME
CANCEL
SOUND_REBOOT
SHOWEXTENTLINECHECK
SHOWLINECHECK
SHOWPOINTCHECK
KDRAW
KSTEP
KSTOP
KSAFETIME
MEMSTAT
CONFIGHASH
EXIT
QUIT
RELAUNCH
DEBUG
DIR
MEM
DUMPNATIVES
GET
SET
OBJ
GTIME
DUMPCACHE
SHOWLOG
TakeFocus
EditDefault
EditActor
CopyToClipboard
HideLog
Preferences
BRIGHTNESS
CONTRAST
GAMMA
PAUSESOUNDS
UNPAUSESOUNDS
STOPSOUNDS
WEAPONRADIUS
ROLLOFF
GRAPH
L2Debug
L2DebugWindow
FLUSH
STAT
CRACKURL
PACKETCOUNTSTART
PACKETCOUNTSTOP
STOPMOUSE
MOVEMOUSE
ENDFULLSCREEN
TOGGLEFULLSCREEN
GETCURRENTRES
GETCURRENTCOLORDEPTH
GETCOLORDEPTHS
GETCURRENTRENDERDEVICE
SETRES
TEMPSETRES

Оказывается через клиент доступно гораздо больше команд: 222 из клиента, и только 57 - из консоли! Настало время посмотреть, что же они делают.

Проверяем найденные команды

В списке есть 2 команды телепорта - TELEPORT и C_TELEPORT, очевидно у них должны быть аргументы. Находим в IDA как они парсятся:

.text:104E667E                 mov     ecx, [ebp+arg_0]
.text:104E6681                 lea     eax, [ebp+var_164]
.text:104E6687                 push    eax
.text:104E6688                 push    offset asc_10791768 ; "X="
.text:104E668D                 push    ecx
.text:104E668E                 call    ds:?Parse@@YAHPBG0AAM@Z ; Parse(ushort const *,ushort const *,float &)
.text:104E6694                 add     esp, 0Ch
.text:104E6697                 cmp     eax, esi
.text:104E6699                 jz      loc_104E5DC0
.text:104E669F                 mov     eax, [ebp+arg_0]
.text:104E66A2                 lea     edx, [ebp+var_160]
.text:104E66A8                 push    edx
.text:104E66A9                 push    offset aY       ; "Y="
.text:104E66AE                 push    eax
.text:104E66AF                 call    ds:?Parse@@YAHPBG0AAM@Z ; Parse(ushort const *,ushort const *,float &)
.text:104E66B5                 add     esp, 0Ch
.text:104E66B8                 cmp     eax, esi
.text:104E66BA                 jz      loc_104E5DC0
.text:104E66C0                 mov     edx, [ebp+arg_0]
.text:104E66C3                 lea     ecx, [ebp+var_15C]
.text:104E66C9                 push    ecx
.text:104E66CA                 push    offset aZ       ; "Z="
.text:104E66CF                 push    edx
.text:104E66D0                 call    ds:?Parse@@YAHPBG0AAM@Z ; Parse(ushort const *,ushort const *,float &)

В принципе это было очевидно - аргументы для телепорта: X=<float> Y=<float> Z=<float>, обе команды работают идентично. Разумеется, нормальный сервер не даст игроку просто так телепортироваться куда угодно - сразу откинет назад, однако на сервере, который не проверяет координаты - все работает.

SHOWLOG, HideLog - открывает и закрывает окно консоли. Альтернатива аргументу /LOG.

Preferences - открывает вот такие настройки:

Preferences открывает гораздо более богатые настройки, чем те, которые доступны в клиенте.
Preferences открывает гораздо более богатые настройки, чем те, которые доступны в клиенте.

SPAWNNPCS Num=<int> - спавнит указанное число рандомных мобов вокруг персонажа:

Результат команды SPAWNNPCS
Результат команды SPAWNNPCS

SPAWNPCS Num=<int> - аналогично предыдущей, но спавнит игроков в рандомном шмоте:

Результат команды SPAWNPCS
Результат команды SPAWNPCS

RIDE TYPE=<int> - 0 - садимся на страйдера, 1 - на виверну, 2 - на виверну - альбиноса

А вы знали, что страйдеры были уже в C1?
А вы знали, что страйдеры были уже в C1?
И неправильные виверны
И неправильные виверны

Правда работает кривовато - после этого клиент практически зависает. Забегая вперед скажу, что маунты есть и в сетевом протоколе, и оно работает!

RMODE, C_RMODE <int> - изменяет режим рендеринга, например на такой

RMODE 1 - можно видеть сквозь стены
RMODE 1 - можно видеть сквозь стены

или такой:

RMODE 7 - текстуры не завезли
RMODE 7 - текстуры не завезли

SHOWBORDERLINE, SHOWSECTORS - включает это:

SHOWBORDERLINE, SHOWSECTORS - вероятно, оно зачем-то нужно
SHOWBORDERLINE, SHOWSECTORS - вероятно, оно зачем-то нужно

SEAMLESS ON/OFF - включает/выключает подгрузку соседних фрагментов карты. Если выключить - соседние фрагменты не будут подгружаться, можно дойти до края земли и упасть:

Земля не только плоская, но и квадратная
Земля не только плоская, но и квадратная

MAPLOC - выводит в консоль X Y текущего фрагмента карты, например MapX=21, MapY=19 - эльфятник.

GEODATA - пытается грузить файл по пути формата: .\GeoData%d_%d_conv.dat, где числа вместо %d соответствуют координатам MAPLOC. Очевидно, это серверная геодата. Дадим клиенту то, что он хочет - скопируем геодату в System\GeoData. Теперь мы можем взглянуть на мир LA2 глазами сервера:

Серверная геодата
Серверная геодата

Видно, что "разрешение" тут гораздо ниже, чем в клиенте - мир состоит из клеток примерно с ширину персонажа, а если точнее - 16x16 координатных единиц (которые отображаются по /loc). Зеленые стрелочки показывают проходимые направления, а красные - непроходимые. А если участок 8x8 клеток не содержит больших перепадов высот и непроходимых направлений - он объединяется в одну большую клетку:

Разные типы геодаты
Разные типы геодаты

Заключение

Мы познакомились лишь с частью скрытого в клиенте LA2 функционала, часть из которого очевидно была предназначена для тестирования и разработки игры, однако могла пригодиться и игрокам. Однако в клиенте есть ещё кое-что очень интересное. В следующей статье мы выясним, что же делает команда BuildZone.

Комментарии (35)


  1. Belking
    07.06.2024 03:27
    +2

    Так и от WAD'а статью на хабре увидим!


  1. N1X
    07.06.2024 03:27
    +5

    Прям ностальгией захлестнуло =) Да, было много часов на "линейку" потрачено...

    Помню были еще веселые инструменты вроде Hlapex для модификации трафика с помощью скриптов и HGuard для защиты неофициальных серверов от ботов, при этом автор один и тот же, но первый инструмент позволял обойти второй, правда с некоторыми костылями )


    1. Hint
      07.06.2024 03:27
      +7

      Пример скрипта для hLaPEx
      var
          pck48: String;
          hidden: Boolean;
          i, x, y: Integer;
      
      procedure Init;
      begin
          hidden := False;
          pck48 := '';
          Randomize;
      end;
      
      procedure SendMsg(msg: String);
      begin
          buf := #$4A;
          WriteD(0);
          WriteD(2);
          WriteS('hLaPEx');
          WriteS(msg);
          SendToClient;
      end;
      
      begin
          if FromServer then Exit;
          
          case Ord(pck[1]) of
              $1B: case Ord(pck[2]) of
                  $05:
                      begin
                          SendMsg('Here I am ;)');
                          pck := #$30;
                          hidden := False;
                      end;
                  $06:
                      begin
                          if pck48 = '' then Exit;
                          SendMsg('Invisible mode');
                          hidden := True;
                          pck := pck48;
                          i := 2;
                          x := ReadD(i);
                          y := ReadD(i);
                          x := x + 1000 + Round(Random * 200) - 100;
                          y := y + 1000 + Round(Random * 200) - 100;
                          buf := pck;
                          WriteD(x, 2);
                          WriteD(y, 6);
                          pck := buf;
                      end;
                  end;
              $48: pck48 := pck;
              $30: if hidden then pck := '';
          end;
      end.

      Позволял в том числе в режиме боя исчезнуть на любое время при нажатии одной кнопки, а потом появиться при нажатии другой. В нужный момент отправляем серверу пакет ValidatePosition с неверными координатами. Сервер думает, что произошел рассинхрон, говорит клиенту переместить персонажа в правильную позицию, скрывает персонажа на время прогрузки. Клиент поправляет позицию и шлет пакет Appearing, который мы блокируем. И сервер начинает ждать нас бесконечно долго, держа невидимыми. Когда готовы, шлем Appearing и появляемся.

      Я тогда названия всех программ начинал с буквы h :) Подглядел вроде бы у hd, который так делал (hdGeoEditor и пр.).


      1. XenRE Автор
        07.06.2024 03:27

        У моей версии был авто режим, активирующий локальный телепорт при попытке атаки, и практически дающий бессмертие, если пинг позволяет вовремя реагировать. А еще так можно было замки в соло отжимать.


      1. N1X
        07.06.2024 03:27
        +1

        Офигеть, я когда ник увидел на несколько секунд завис: совпадение, или нет )


  1. gruzoveek
    07.06.2024 03:27
    +2

    У нас играли в нее в компьютерном клубе, причем я честно пытался, наслушавшись восторгов друга. Но не осилил тупо гриндить бегать. Быстро надоело. Переключился на ВОВку.


    1. AgentFire
      07.06.2024 03:27

      Гриндить на х1-х3 было куда менее скучно, одна ошибка и ты ошибся, бегай потом без эсэсок на синих мобах бабло с нуля поднимать. Я уж молчу про возможные ПК из кустов против тебя за место фарма и по фану.


  1. selenzorn
    07.06.2024 03:27

    В 2005 линейка казалась очень крутой: огромные пространства, пвп, куча игроков, торговля, а дома еще не было нормального интернета, но когда первый раз заходишь вов и понимаешь, насколько он ушел вперед — линейку больше не запускаешь


    1. Revertis
      07.06.2024 03:27
      +5

      У ВОВа графика вырвиглазная по сравнению с Lineage II.


      1. Tsimur_S
        07.06.2024 03:27
        +12

        Дело не только в мультяшной графике но еще и в реализме мира. Как там в Матрице было? Сначала сделали виртуальный рай но большинство людей в него просто не поверило. Аукцион вместо трейда, какое-то противостояние Орды и Альянса вместо возможности грохнуть кого угодно и за что угодно, инстансы вместо конкуренции за споты и РБ, ПвП на арене ради строчки в рейтинге ПвП на арене, отсутствие полноценной политики и тд.

        Я бы не сказал что ВоВ ушел вперед линейки, скорее линейка деградировала свои сильные стороны до ВоВ. Впрочем, на вкус и цвет фломастеры разные. Линейка получила свою популярность, кроме очевидной Кореи, на просторах СНГ, стран LATAM. Видимо было нечто общее в менталитете.


        1. Revertis
          07.06.2024 03:27

          Согласен.


        1. QtRoS
          07.06.2024 03:27
          +3

          вместо возможности грохнуть кого угодно и за что угодно

          Перед глазами проносятся флэшбеки ПКшников рядом с Gludio ...


          1. Tsimur_S
            07.06.2024 03:27
            +3

            Ну они не зря так назывались, Руины Отчаяния.


            1. AgentFire
              07.06.2024 03:27

              They knew.


        1. XenRE Автор
          07.06.2024 03:27
          +3

          Видимо было нечто общее в менталитете.

          Я так не думаю. Не забывайте, что мало на каких фришках были рейты x1 - как правило от x3, и вплоть до x1000+. Там, где корейцы задротили - мы получали фан. Ну и как я уже сказал в статье - слив C1 сервера сделал гигантский вклад в популярность именно LA2 - ведь практически все официальные MMO в то время были по схеме pay to play.

          Что касаемо мира - до EVE online как до луны. Вот где действительно жестокая галактика и можно всё. А онлайн трейд - очень стрёмное решение, сделанное скорее "на отвали". Особенно если вспомнить, что мало у кого в то время был безлимитный интернет, да и гонять клиент даже на фоне - это такое себе, но тут хоть ог волкер помогал.

          Но графика в ВоВ стрёмноватая, тут я согласен. Причем она вроде и сейчас особо лучше не стала.


          1. vanxant
            07.06.2024 03:27

            Не, на ранних фришках было наоборот. Я начинал с рейтов 0.6 (уж очень ГМы хотели денег)


            1. Belking
              07.06.2024 03:27

              А еще когда тебе соклановец на 6 часов идет ману заливать, не вступая в пати, а чтобы ты быстрее прокачался и все это время подбадривает, чтобы ты сам не сдавался. А еще когда отправляешь свою пачку биться с одной из лучших конст топового клана, теряя нафармленный опыт за последние два дня, но потому что нельзя иначе. А еще когда все знают логины-пароли друг друга, и тем кто не может позволить себе ПА можно и скинуться совместно выфармленным. И смиряешься с периодическими крысами, которые считают недельный фарм адены всей пачки украсть себе за радость, а всем и пофиг - ведь лучше когда такие люди себя раньше раскрывают....

              Эх, именно в сложности достижения и балансе трат достигнутого и был смысл - что любое действие сопровождалось реальными эмоциями и изменениях во взаимоотношениях...


      1. dartraiden
        07.06.2024 03:27

        Наоборот, у линейки графика какая-то чрезмерно резкая.

        Видимо, дело привычки, потому что я вовер с 18-летним стажем, мультяшный стиль привычен и число полигонов у луговой собачки не режет глаз.


        1. Revertis
          07.06.2024 03:27

          Ужас какой!


      1. SystemOutPrintln
        07.06.2024 03:27

        Не знаю, что в ней такого вырвиглазного.

        Благодаря тому же богатству и качеству анимаций мир ВоВа выглядел гораздо живее уже тогда. Тогда как в линеаге 2 и по сей день деревянные болванчики.


      1. daggert
        07.06.2024 03:27

        Не все любят анимешный стиль. Меня это всегда отворачивало от линейки. Ну и огромные пустые пространства…


  1. Firemoon
    07.06.2024 03:27

    Спасибо, что вы не отложили написание статьи в долгий ящик! Всегда интересно заглянуть за кулисы.


  1. Hint
    07.06.2024 03:27

    В те времена таким делиться не любили )


  1. 0xdead926e
    07.06.2024 03:27
    +5

    как-то давненько пробовала порендерить карты линейки и столько странноватых решений там увидела... и BSP в режиме "все видят всех" (а потом у них тои/пещера гигантов лагают), и координаты со странными смещениями, и не очень хорошо склеенные тайлы

    причем в режиме BSP там только горизонтальные плоские полы, насколько помню. и еще что-то около катакомб/некрополей. та же лесенка перед храмом в гиране- не бсп, а просто моделька.

    сопсна результат тех попыток

    весь мир целиком в одну сцену тож запихивала, но скринов сходу не нашлось.


    1. XenRE Автор
      07.06.2024 03:27
      +2

      а потом у них тои/пещера гигантов лагают

      Сервер LA2 при определении зоны видимости вокруг персонажа вообще не учитывал координату Z, например с земли можно определить отреспился ли Баюм. По этому естественно все 100500 мобов и игроков в ТОИ, и их взаимодействия, рендерились на клиенте, и особенно осчасливливали тех, у кого был тариф с оплатой за трафик.

      причем в режиме BSP там только горизонтальные плоские полы

      На сколько я знаю, такова особенность движка Unreal - сначала рендерится однослойный ландшафт - я так понимаю это даже не модель, а просто карта высот, а всё прочее - это уже модельки на нем, т.е. по другому движок не позволяет.


      1. 0xdead926e
        07.06.2024 03:27

        сначала рендерится однослойный ландшафт - я так понимаю это даже не модель, а просто карта высот

        да, но я не про это. олсо хоть это и не про то, но слоев текстур в ландшафте достаточно много. даже запеченные тени есть, по одной текстуре на каждые два чтоль часа ингейм времени.

        еще там есть просто статические модельки и есть отдельно брашмодели. кваки-халфлайфы ковырял? там так же. у брашмоделей есть собственно BSP и флажки видимости какие поверхности видно с текущей.. типа чтоб не рендерить то, что игрок впринципе никак не увидит с текущей позиции. вот, visibility во всех брашмоделях л2- пустая, все видно отовсюду. и технически если бы она была правильной- тои бы это пофиксило даже без изменения сервера.

        пример работающей pvs в bsp

        камера игрока находится где-то около черной доски слева, и все, что он потенциально не видит- не рендерится вовсе.


        1. XenRE Автор
          07.06.2024 03:27

          Я подробно не исследовал рендеринг, но очевидно, что даже если бы невидимые модельки не рендерились бы, они все равно бы обрабатывались движком - все взаимодействия, проверки на столкновения, движения и скрипты, а еще подгрузка текстур. И самое паршивое, что когда игрок попадает в грид со всей этой пачкой, к нему от сервера прилетает неслабый берст трафика, и клиент начинает все это прогружать, вызывая неслабый фриз. Особенно это радует когда убегаешь от толпы врагов.

          Ну и например та же обработка консольных команд - делается тупо сравнением строк. Ни бинарного поиска, ни хешей. А ведь оно не только консольные команды обрабатывает, игровые функции тоже, и используется постоянно.

          А касаемо рендеринга ландшафта - кстати визуально работало вполне неплохо, например в вышедшем несколько лет спустя Аионе часто встречается откровенное мыло в ландшафтах в 3 пикселя на метр, а вот в ЛА2 я такого не припоминаю. И я подозреваю тут как раз все делал сторонний движок, так что надо сравнивать с другими играми на UE1.


          1. 0xdead926e
            07.06.2024 03:27
            +1

             даже если бы невидимые модельки не рендерились бы

            одно это дало бы очень много. особенно учитывая, что моделька персонажа- на самом деле несколько моделек с разными шейдерами (там отдельно торс, отдельно ноги, отдельно лицо, отдельно волосы...), и канонично для корейских ммо- в модельках персонажей полигонов больше, чем во всем окружении и вот это все. хотя да, пальцы только с камаэлями завезли xD

            ну и никто не мешал например ходить по бсп-дереву дважды-трижды (они обычно крайне неглубокие) и нпрмр отсекать все, что после третьего баунса не будет видно. и вообще не просчитывать никак это все. правда да, та же арена баюма была бы невидимой отовсюду и был бы лаг при телепорте туда.. ох вейт, он и так был.

            и еще немножко кеков.

            вот это- экран логина high five part 4. xD

            с другими играми на UE1

            емнип в л2 был уе2.5


            1. XenRE Автор
              07.06.2024 03:27

              вообще не просчитывать никак это все

              Так нельзя - ведь то, что невидимое сейчас, может стать видимым через секунду. А сервер же не послыалет всю инфу об объектах каждую секунду, т.е. даже нивидимые объекты должны быть загружены и просчитываться, как минимум позиция и состояние.

              был бы лаг при телепорте туда.. ох вейт, он и так был.

              Любой телепорт, в т.ч. локальный, сопровождается удалением всех объектов и созданием заново, даже если это одни и те же объекты. Т.е. опять все завязано на логику сервера.

              емнип в л2 был уе2.5

              Возможно.


  1. iRusher
    07.06.2024 03:27
    +2

    Спасибо большое за статью, отдал этой игре 6 лет, было приятно почитать и однозначно надеюсь что будет цикл статей как запустить свой серв)) это интересно.

    Понял что больше наверное не смогу играть в ММО, пока может не выйдет что то достойное на VR, опыт игры л2 стал бременем, после которого все другие онлайн ММО видятся мусором. В каждой игре есть какой то бред, где тебя за ручку водят или ограничивают, где так заботятся что бы не дай бог тебе или кому-то кто-нибудь помешал качаться, или ты расстроился от чего-то. Разработчики выстраивают вокруг тебя забор и контролируют всё что в твоей игре происходит, от такого геймплея несёт стерильностью.

    L2 была живым миром, реалистичной моделью общества, суровой и жестокой, но иногда и прекрасной, там можно было встретить как разводил, так и добрых людей, ремесленников, торгашей, мошенников, там можно было нажить врагов которых ненавидишь, и друзей с которыми общаешься по сей день, а часто бывало и так что бывшие враги становятся крепкими друзьями. А политика в линейке это вообще отдельный мир. Это феномен, такой уровень погружения и внедрения в социальную составляющую сервера не даст ни одна игра пока что, ну я по крайней мере пробовал играть в многие проекты, искал замену но ничего из этого не вышло. Так как линейка первая моя ММО, ты постоянно сравниваешь и смотришь на новые игровые миры через призму пережитого в ней опыта.


    1. SystemOutPrintln
      07.06.2024 03:27

      В каждой игре есть какой то бред, где тебя за ручку водят или ограничивают, где так заботятся что бы не дай бог тебе или кому-то кто-нибудь помешал качаться, или ты расстроился от чего-то.

      В этом и плюс, что современные ММО стараются дать увлекательный игровой опыт и оградить от всяких неадекватов, цель которых не поиграть, а надоедать другим игрокам грифингом и оскорблениями.

      Какие-то ММО идут дальше и предоставляют каждому игроку свой изолированный игровой мир, где невозможно встретить других игроков, пока ты сам этого не захочешь и не пригласишь их. Это просто идеально, никаких тебе малолеток с ником ХХХнагибаторХХХ, которые стилят босса, которого ты бьёшь, и пытаются тебя заПКшить. Никаких малолеток в глобальном чате игры, которые угрожают добраться до чужих мамок.

      L2 была живым миром, реалистичной моделью общества, суровой и жестокой

      ...прямо как реальный мир. А теперь объясните мне, вот зачем уходить в виртуальный мир, который такой же жестокий, токсичный и суровый, как и реальный? Чтобы что?

      Напоминает мем "наконец-то моя смена шахтёра закончилась, сейчас приду домой и отдохну, буду копать шахты и добывать алмазы в майнкрафте".

      п.с. это я к тому, что вы зря говорите, что "стерильность" геймплея -- это что-то априори плохое.


      1. AgentFire
        07.06.2024 03:27
        +3

        Плохое плохое. Это как резиновая женщина без отверстий. Это как друг, которого нельзя подкалывать. Это как американские горки, но в VR в мягком кресле дома. Мамкоебы, ПКшеры и лутстилеры - это неотъемлимая часть реализма (не путать с реальностью!). Это необходимый негатив, который увеличивает ценность остального позитива.


      1. Rive
        07.06.2024 03:27
        +1

        Какие-то ММО идут дальше и предоставляют каждому игроку свой изолированный игровой мир, где невозможно встретить других игроков, пока ты сам этого не захочешь и не пригласишь их.

        Впрочем, это уже не ММО, а игра с кооперативным режимом.


    1. Turgere
      07.06.2024 03:27

      Попробуй EVE online. Там песочница ещё глубже и это даёт ещё больше взаимодействия и политики между игроками. Вот там начинается настоящая драма из-за отношений и их последствий, а правила близки к линейке по сути.


  1. norlin
    07.06.2024 03:27
    +2

    Ууу, спасибо за ностальгию!

    После La2 никакие другие типа-ММОшки не заходили вообще, выглядели унылими и скучными. Да и до сих пор разве что Eve Online в плане ммошности лучше реализована, а всё остальное скатилось в сингл-плеер или сессионный ко-оп.