Автор Тема: Альтернатива скриптингу  (Прочитано 6298 раз)

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #15 : Апрель 17, 2014, 07:22:50 pm »
Я предполагал, что адреса до 0xA10BA1 статические, точнее так и есть, сдвига не должно быть, просто тут какая-то особенность заполнения, какая связь со звуком пока не понятно. И куда девается этот участок, я его нигде больше не обнаружил.

Оффлайн былтаков

  • Призрак
  • Сообщений: 23
  • Репутация: +2/-0
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #16 : Апрель 17, 2014, 09:57:49 pm »
удаление папки аудио - это самый легкий способ NO CD

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #17 : Июль 23, 2014, 05:28:32 pm »
Можно еще прототипами объявлять функции и методы классов и писать вообще как говориться на голом C++. Но сложность в другом, надо объявлять много и правильно, а там не мало всего.

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

Опкод 02CE, вычисляющий z-координату поверхности под заданной точкой:
Код: C++
  1. //.h
  2. auto GroundZ = (float  (__cdecl*)(float x,float y,float z,BYTE))0x4D53A0;
  3.  
  4. //.cpp
  5. z = GroundZ(100.0, 100.0, 15.0, 0); // 0x4558D1 @@opcode_02CE: %4d% = ground_z %1d% %2d% %3d%

Опкоды 0213, 032B и др., создающие пикапы:
Код: C++
  1. //.h
  2. auto CreatePickup = (int (__cdecl*)(float x, float y, float z, int id, int type, int ammo, int, char, int))0x4418C0;
  3.  
  4. //.cpp
  5. CreatePickup(100.0, 100.0, 15.0, 280, 2, 500, 0, 0, 0); // 0x45B7D7 @@opcode_032B: %7d% = create_weapon_pickup %1t% %2d% ammo %3d% at %4d% %5d% %6d%

Связка опкодов 014B, 014C - парковка машин (с одновременным увеличением их лимита с 185 до 1000):
Код: C++
  1. //.h
  2. #pragma pack (push, 1)
  3. struct  CCarGenerator
  4. {
  5.         DWORD mi;
  6.         RwV3d pos;
  7.         DWORD angle;
  8.         WORD  color1;
  9.         WORD  color2;
  10.         BYTE  alarm;
  11.         BYTE  doorLock;
  12.         BYTE  field_1A;
  13.         BYTE  field_1B;
  14.         WORD  field_1C;
  15.         WORD  field_1E;
  16.         DWORD time;
  17.         DWORD ProcessedVehicleHandle;
  18.         WORD  field_28;
  19.         BYTE  field_2A;
  20.         BYTE  __padding;
  21. };
  22. #pragma pack (pop)
  23. CCarGenerator   *CarGenerator;
  24. auto AddParkedGenerator = (int (__cdecl*)(float x,float y,float z,float angle,int id,int color1,int color2,char alarm,char locked,char,int,int))0x5A6C10;
  25.  
  26. //.cpp
  27. DWORD *dwParkedCarLimit = (DWORD *) 0x5A6C16;
  28. DWORD *dwParkedCarCount = (DWORD *) 0x97F2A8;
  29. DWORD *dwCurrentTime = (DWORD *) 0x974B2C;
  30.  
  31. CarGenerator = new CCarGenerator[1000]; // original 185
  32. WriteDWORD(dwParkedCarLimit,1000); // original 185
  33. WriteDWORD((DWORD*)0x4537A9,(DWORD)CarGenerator);
  34. WriteDWORD((DWORD*)0x5A6C5F,(DWORD)CarGenerator);
  35. WriteDWORD((DWORD*)0x5A6CC3,(DWORD)CarGenerator);
  36. WriteDWORD((DWORD*)0x5A69DB,(DWORD)CarGenerator);
  37. WriteDWORD((DWORD*)0x5A6B16,(DWORD)CarGenerator);
  38. WriteDWORD((DWORD*)0x5A69E6,(DWORD)&CarGenerator->pos.x);
  39. WriteDWORD((DWORD*)0x5A6B22,(DWORD)&CarGenerator->pos.x);
  40. WriteDWORD((DWORD*)0x5A69F1,(DWORD)&CarGenerator->pos.y);
  41. WriteDWORD((DWORD*)0x5A6B2A,(DWORD)&CarGenerator->pos.y);
  42. WriteDWORD((DWORD*)0x5A69FC,(DWORD)&CarGenerator->pos.z);
  43. WriteDWORD((DWORD*)0x5A6B35,(DWORD)&CarGenerator->pos.z);
  44. WriteDWORD((DWORD*)0x5A6A07,(DWORD)&CarGenerator->angle);
  45. WriteDWORD((DWORD*)0x5A6B40,(DWORD)&CarGenerator->angle);
  46. WriteDWORD((DWORD*)0x5A6A14,(DWORD)&CarGenerator->color1);
  47. WriteDWORD((DWORD*)0x5A6B4C,(DWORD)&CarGenerator->color1);
  48. WriteDWORD((DWORD*)0x5A6A21,(DWORD)&CarGenerator->color2);
  49. WriteDWORD((DWORD*)0x5A6B5C,(DWORD)&CarGenerator->color2);
  50. WriteDWORD((DWORD*)0x5A6A2A,(DWORD)&CarGenerator->alarm);
  51. WriteDWORD((DWORD*)0x5A6B65,(DWORD)&CarGenerator->alarm);
  52. WriteDWORD((DWORD*)0x5A6A33,(DWORD)&CarGenerator->doorLock);
  53. WriteDWORD((DWORD*)0x5A6B6E,(DWORD)&CarGenerator->doorLock);
  54. WriteDWORD((DWORD*)0x5A6A3C,(DWORD)&CarGenerator->field_1A);
  55. WriteDWORD((DWORD*)0x5A6B77,(DWORD)&CarGenerator->field_1A);
  56. WriteDWORD((DWORD*)0x5A6A49,(DWORD)&CarGenerator->field_1C);
  57. WriteDWORD((DWORD*)0x5A6B85,(DWORD)&CarGenerator->field_1C);
  58. WriteDWORD((DWORD*)0x5A6A56,(DWORD)&CarGenerator->field_1E);
  59. WriteDWORD((DWORD*)0x5A6B95,(DWORD)&CarGenerator->field_1E);
  60. WriteDWORD((DWORD*)0x5A6A61,(DWORD)&CarGenerator->time);
  61. WriteDWORD((DWORD*)0x5A6BA1,(DWORD)&CarGenerator->time);
  62. WriteDWORD((DWORD*)0x5A6A6C,(DWORD)&CarGenerator->ProcessedVehicleHandle);
  63. WriteDWORD((DWORD*)0x5A6BAC,(DWORD)&CarGenerator->ProcessedVehicleHandle);
  64. WriteDWORD((DWORD*)0x5A6A79,(DWORD)&CarGenerator->field_28);
  65. WriteDWORD((DWORD*)0x5A6BB8,(DWORD)&CarGenerator->field_28);
  66. WriteDWORD((DWORD*)0x5A6A85,(DWORD)&CarGenerator->field_2A);
  67. WriteDWORD((DWORD*)0x5A6BC1,(DWORD)&CarGenerator->field_2A);
  68.  
  69. // 0x4536DE @@opcode_014B: %13d% = init_parked_car_generator %5t% %6d% %7d% %8d% alarm %9d% door_lock %10d% %11d% %12d% at %1d% %2d% %3d% angle %4d%
  70. AddParkedGenerator(100.0,100.0,15.0,90.0,162,-1,-1,1,0,0,0,0); // rhino
  71. // 0x45378A @@opcode_014C: set_parked_car_generator %1d% cars_to_generate_to %2d%
  72. CarGenerator[0].time = *dwCurrentTime+4;
  73. CarGenerator[0].field_28 = 0xFFFF;
  74. (*dwParkedCarCount)++;
  75.  
  76. // 0x4536DE @@opcode_014B: %13d% = init_parked_car_generator %5t% %6d% %7d% %8d% alarm %9d% door_lock %10d% %11d% %12d% at %1d% %2d% %3d% angle %4d%
  77. AddParkedGenerator(200.0,100.0,15.0,180.0,155,-1,-1,1,0,0,0,0); // hunter
  78. // 0x45378A @@opcode_014C: set_parked_car_generator %1d% cars_to_generate_to %2d%
  79. CarGenerator[1].time = *dwCurrentTime+4;
  80. CarGenerator[1].field_28 = 0xFFFF;
  81. (*dwParkedCarCount)++;
  82.  

Можно и в точности выписать опкод, например 01EC, увеличивающий массу машины:
Код: C++
  1. //.cpp
  2. void SetVehicleHeavy(CVehicle *Vehicle, bool Heavy)
  3. {
  4.         if (Heavy)
  5.         {
  6.                 Vehicle->field_11A = Vehicle->field_11A & 254 | 1;
  7.                 Vehicle->fMass = Vehicle->HandlingData->fMass * 3;
  8.                 Vehicle->fTurnMass = Vehicle->HandlingData->fTurnMass * 5;
  9.         }
  10.         else
  11.         {
  12.                 Vehicle->field_11A = Vehicle->field_11A & 254;
  13.                 Vehicle->fMass = Vehicle->HandlingData->fMass;
  14.                 Vehicle->fTurnMass = Vehicle->HandlingData->fTurnMass;
  15.         }
  16. }
  17.  
  18. //.cpp
  19. SetVehicleHeavy(PlayerPed->ped.m_pVehicle,1); // 0x453516 @@opcode_01EC: make_car %1d% very_heavy %2h%
  20.  

Оффлайн Sektor

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 512
  • Репутация: +33/-0
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #18 : Июль 23, 2014, 08:02:14 pm »
Цитировать
Опкоды 0213, 032B и др., создающие пикапы:

И кроме того, можно сразу получить доступ к полям объектов, что существенно круто, например как:


Код: C++
  1.  
  2. CPed * myPed = new CPed;
  3. myPed->health = 100.0;
  4.  
  5.  


Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #19 : Июль 24, 2014, 05:40:43 am »
Глядя на все это многообразие функций и классов, придуманных R*, с которыми думаю им было удобно работать, становится непонятным, зачем было оборачивать все это еще и в скрипты, ведь они намного "деревяннее" и не включают всего, почему бы напрямую не писать миссии. Или один разработчик сделал скриптовый движок, а второй скриптер писал на нем миссии, но наверняка он постоянно пинал первого, чтобы тот добавлял какие-то недостающие опкоды, под которые приходилось опять создавать новые функции. А пока второй скриптил миссии, первому приходилось напрямую программить геймплэй, типа копов, траффика и т.д. По сути они делали одно и то же разными путями и уверен, что main.scm был закончен в то же время, когда откомпилися последний раз gta-vc.exe. Ладно бы если R* выложила свой интрумент для скриптинга, чтобы мы могли писать аддоны, или сами бы раз в год выпускали дополнительный скриптовый контент, тогда был бы смысл. На мой взгляд вместо скриптов лучше бы писали dll-плагин с миссиями. А так лишняя трата времени, не люблю я скриптинг.

Оффлайн Sektor

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 512
  • Репутация: +33/-0
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #20 : Июль 24, 2014, 09:18:13 am »
Не совсем так. Как раз миссии писать на C++ чистом, очень не благородное дело, там ты не каких вайтов не сделаешь, и лишишься массу удобств. Именно скриптовая система, это самая гибкая система. Имеет ряд значительных преимуществ и как правило теперь каждые разработчики игр, ее используют. Особое преимущество, что гигантский проект не нужно каждый раз перекомпелировать,в скриптах язык может быть абсолютно любой на вкус, а также появляется масса мощнейших возможностей.

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #21 : Июль 24, 2014, 01:24:43 pm »
Но ведь скрипт это последовательность опкодов, а каждый опкод уже расписан в exe через какие-то функции, поля объектов и методы классов. Это то же самое, если завернуть не в опкоды, а в нормальные си-функции, половина из которых уже готовы в том же виде, что и опкод. Тогда не нужно придумывать кучу ненужных опкодов, описывающих присвоение значений, условные операторы, нечитаемые циклы и т.д. Тот же Wait можно посмотреть как описан через currentTime, так почему бы сразу не обращаться к функции через какой-нибудь Wait(1000); если он уже описан на си самими разработчиками при создании опкодов. Как может скрипт быть более гибким, чем тот си-код, который его описывает. Повторюсь, что гибкость могла бы быть, если бы скиптовать можно было дополнительно, но сами разработчики такого инструмента не предоставили.
Не знаю, чем плохо сразу писать миссию, грубо говоря так:

void MainThread()
{
    Wait(0);
    Player::CreatePlayerPed(x,y,z);
    Player::SetHealth(100);
    SetTime(12,0);
    SetWeather(5);
    SetTrafficDensity(100);
.......
}

При этом можно на ходу придумывать новые функции, а не ограничиваться набором опкодов, захотелось какой-нибудь:
void Player::GetTaxi()
{
    Wait(0);
    CVehicle *Taxi = FindRandomCar(x,y,z);
    if (Taxi)
        Player::SetAsPassenger(Taxi);
.......
}

По поводу компиляции, в exe это конечно заворачивать не нужно, я бы наоборот вынес оттуда многое, но что мешает сделать mission.dll как аналог main.scm
Я так понимаю, этот сайт к тому и подталкивает. Я например научился запускать игру без main.scm, но пока с некоторыми багами.

Оффлайн Sektor

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 512
  • Репутация: +33/-0
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #22 : Июль 24, 2014, 01:39:31 pm »
Код: C++
  1.   Wait(0);
  2.     CVehicle *Taxi = FindRandomCar(x,y,z);
  3.     if (Taxi)
  4.         Player::SetAsPassenger(Taxi);

Вот именно, что не выйдет, приостановить поток. Если его приостановить, то полностью будет замирание типа как sleep. И самое печально, сохранения/загрузка игры, например в скриптовой машине, можно сохранить позиции скриптовых, потоков, состояние переменных и много масса рутиных вещей и затем это все загрузить.

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #23 : Июль 24, 2014, 01:48:51 pm »
Ну да, ты прав, так в лоб конечно не получится, следующия по коду команда пойдет сразу же, но думаю можно придумать свою систему потоков через SetTimer(0,0, wait, (TIMERPROC)...), а внутри них незачем приостанавливать, просто проверять условия, и срабатывать "в холостую", ожидая проверки условия на следующем по таймеру запуске. Да думаю, все это решаемо при желании.

Оффлайн Sektor

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 512
  • Репутация: +33/-0
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #24 : Июль 24, 2014, 02:33:49 pm »
Цитировать
SetTimer(0,0, wait, (TIMERPROC)...)

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

Оффлайн Jak łaska za praca

  • Прохожий
  • *
  • Сообщений: 58
  • Репутация: +1/-0
  • Как украшение на торт
    • aktel999
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #25 : Июль 24, 2014, 02:48:14 pm »
А кто думает про мою идею с входами и выходами.

Например у нас есть описана для своих целей сущность gamerules у неё есть вход MissionBigFail.
И автомобиль с выходом OnDeath по имененам мы можем активировать gamerules->MissionBigFail провалив миссию например.
Это хорошо тем что мы можем разделить миссии по файлам и переключаться между ними прошли миссию старый в помойку загружаем новый.
А также появляется побочная фишка которая может дать возможность сохранения миссий восстановив стадии сушностей.
Украшаю торты на своих вечеринках, классных вечеринках.

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #26 : Июль 24, 2014, 02:53:57 pm »
А может для тренировки мозгов сделать что-то вот такое, т.е. описать wait и систему условных операторов так, чтобы происходили прыжки "в холостую", пока каждый не отработает со своего места, потом прыжок на следующую за ним инструкцию. Что-то больше на асм уже похоже.

Код: C++
  1. --> void Thread()                            10 раз -->        100 раз -->     // остальные -->
  2. |   {                                                  |                  |    // wait-ы       |
  3. |   ........                                           |                  |                    |
  4. |           Wait(100);   // 10 x 10 ms              <--                   |                    |
  5. |   ........                                        -->                   |                    |
  6. |   ........                                           |                  |                    |
  7. |           Wait(1000);  // 100 x 10 ms                |               <--                     |
  8. |   ........                                           |               -->                     |
  9. |   ........                                           |                  |                   ..
  10. <-- }                                        <---------         <---------           <---------
  11.  
  12. SetTimer(0,0, 10, (TIMERPROC)Thread); // 10 ms

Оффлайн Jak łaska za praca

  • Прохожий
  • *
  • Сообщений: 58
  • Репутация: +1/-0
  • Как украшение на торт
    • aktel999
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #27 : Июль 24, 2014, 03:11:24 pm »
А моя идея с файликами *.ent пригодна для применения?
Украшаю торты на своих вечеринках, классных вечеринках.

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 500
  • Репутация: +43/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #28 : Июль 24, 2014, 03:17:17 pm »
Цитировать
SetTimer(0,0, wait, (TIMERPROC)...)

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

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

Оффлайн Sektor

  • Администратор
  • Постоялец
  • *****
  • Сообщений: 512
  • Репутация: +33/-0
    • Просмотр профиля
Re: Альтернатива скриптингу
« Ответ #29 : Июль 24, 2014, 03:34:13 pm »
Разницы в этом нет, не что не загружается, так как HUD и прочии процедуры, все в главном игровом цикле обрабатывается. Более того, в таймере не выйдет делать Рендер сцен...