Ответ

Внимание! Пока вы просматривали тему, появилось 37 новых ответа. Возможно, вы захотите изменить свое сообщение.
Имя:
E-mail:
Тема:
Иконка:

Вложение:
(Удалить вложение)
(Добавить ещё)
Ограничения: максимум вложений в сообщении — 4, максимальный размер всех файлов — 192 Кбайт, максимальный размер одного файла — 128 Кбайт
Визуальная проверка:
Наберите символы, которые изображены на картинке
Прослушать / Запросить другое изображение

Наберите символы, которые изображены на картинке:
О какой игре форум? (три буквы заглавные):
Сколько будет (5*5 + 2) ответ цифрой.:

подсказка: нажмите alt+s для отправки или alt+p для предварительного просмотра сообщения


Сообщения в этой теме

Автор: kenking
« : Июнь 18, 2019, 02:27:30 pm »

Цитировать
Скажите, пожалуйста, у вас есть список типа для каждого педа
\GTA Vice City\data\default.ide раздел peds Default pedtype

в sdk есть enum ePedType
https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_vc/game_vc/ePedType.h
Автор: egor230
« : Июнь 18, 2019, 03:36:46 am »

kenking рад, искреннему ответу, удалось реализовать отключение lua скриптов через триггер, также несколько новых функций.
 Есть список моделей машин и педов,  можно в lua создавать  авто car = createcar(model, x,y,z)- создает машину на координатах.
 Но при создание педов,  нужно указать его тип
ped = createped(model, 4, x, y, z) – создает педа на координатах, принимает модель, тип пед, координаты.

Скажите, пожалуйста, у вас есть список типа для каждого педа, хочу с помощью массива, определять  тип пед  автоматический.

в moonloader делал так.
Код: Text
  1.  
  2. function mymod.createped(m,x,y,z) -- создать педа
  3. list = {["BMYBE"]= {4,18}, ["HMYDRUG"]= {18,30}, ["SWMOCD"]= {4,234}, ["WMYLG"]= {4,97}, ["OMORI"]= {4,57}, ["HMYBE"]= {4,45}, ["WFYBU"]= {5,150},
  4. ["DWMOLC1"]= {4,32}, ["WFYCLOT"]= {5,211}, ["OMYKARA"]= {4,203}, ["WMYBE"]= {4,154}, ["WMYGOL1"]= {4,36}, ["CWFOFR"]= {5,196}, ["BFYBU"]= {5,148},
  5. ["BMORI"]= {4,14}, ["BMYDRUG"]= {18,28}, ["WMYKARA"]= {4,204}, ["SBMYST"]= {4,142}, ["SWMOST"]= {4,236}, ["BMYPIMP"]= {4,249}, ["FAM3"]= {8,107},
  6. ["MAFFA"]= {18,111}, ["ARMY"]= {6,287}, ["WFYRO"]= {5,92}, ["SBMYTR3"]= {4,136}, ["DNFYLC"]= {5,131}, ["VWFYWA2"]= {5,263}, ["SWMYRI"]= {4,240},
  7. ["DNFOLC2"]= {5,130}, ["WMOMIB"]= {4,165}, ["SOFOST"]= {5,225}, ["SOFORI"]= {5,224}, ["BMYPOL2"]= {4,67}, ["LSV3"]= {9,110}, ["MECGRL3"]= {5,192},
  8. ["SFFD1"]= {17,279}, ["SFR1"]= {10,173}, ["HFOST"]= {5,39}, ["OFOST"]= {5,54}, ["SWMOTR2"]= {4,135}, ["OMONOOD"]= {4,209}, ["WFOST"]= {5,89},
  9. ["BMYMIB"]= {4,166}, ["SWMYST"]= {4,188}, ["WMORI"]= {4,94}, ["BALLAS2"]= {7,103}, ["SWMYCR"]= {4,250}, ["VWMOTR2"]= {4,213}, ["WMYVA"]= {4,189},
  10. ["BMYCG"]= {18,144}, ["VHMYELV"]= {4,82}, ["WMYCLOT"]= {4,217}, ["SWMOTR3"]= {4,137}, ["VLA3"]= {14,116}, ["WMYCH"]= {4,255}, ["WMYVA2"]= {4,252},
  11. ["LSV2"]= {9,109}, ["SPECIAL03"]= {4,292}, ["WFYBURG"]= {5,205}, ["BMOCD"]= {4,262}, ["SBFYRI"]= {5,219}, ["WMYPLT"]= {4,61}, ["WMYRO"]= {4,99},
  12. ["VMAFF2"]= {12,125}, ["SPECIAL09"]= {4,298}, ["SBFYSTR"]= {5,256}, ["VWMYCD"]= {4,206}, ["VWMYBJD"]= {4,171}, ["DWFOLC"]= {5,31}, ["WMYJG"]= {4,96},
  13. ["MAFFB"]= {18,112}, ["SBMORI"]= {4,221}, ["TRIADB"]= {13,118}, ["SWFYSTR"]= {5,257}, ["BMYMOUN"]= {4,51}, ["DWFYLC1"]= {5,151}, ["OMOST"]= {4,58},
  14. ["TRIADA"]= {13,117}, ["BIKERB"]= {4,248}, ["SBMYRI"]= {4,185}, ["WFYST"]= {5,93}, ["HMOST"]= {4,44}, ["WMYCON"]= {4,27}, ["SOMORI"]= {4,228},
  15. ["BMYDJ"]= {4,19}, ["CWFYHB"]= {5,157}, ["SPECIAL02"]= {4,291}, ["WMOST"]= {4,95}, ["DWMYLC2"]= {4,202}, ["SWFYRI"]= {5,216}, ["DNFOLC1"]= {5,129},
  16. ["BFYST"]= {5,13}, ["SPECIAL10"]= {4,299}, ["BALLAS3"]= {7,104}, ["VIMYELV"]= {4,84}, ["CWMOHB1"]= {4,159}, ["WFYLG"]= {5,251}, ["OFYST"]= {5,56},
  17. ["DNMOLC2"]= {4,133}, ["BMOST"]= {4,15}, ["SHMYCR"]= {18,223}, ["HFYST"]= {5,41}, ["MALE01"]= {4,7}, ["LAFD1"]= {17,277}, ["SOMYBU"]= {4,187},
  18. ["WFORI"]= {5,88}, ["HECK1"]= {4,258}, ["SBMOTR2"]= {4,134}, ["SOFYBU"]= {5,141}, ["HFYBE"]= {5,140}, ["OFORI"]= {5,53}, ["VBMYCR"]= {18,183},
  19. ["WMYBOUN"]= {4,164}, ["WMOICE"]= {4,264}, ["BMYAP"]= {4,16}, ["HFORI"]= {5,38}, ["BFORI"]= {5,9}, ["BFYBE"]= {5,139}, ["SBFYST"]= {5,69},
  20. ["SOMOST"]= {4,229}, ["WFYBE"]= {5,138}, ["BIKDRUG"]= {4,254}, ["GUNGRL3"]= {5,191}, ["MAFBOSS"]= {18,113}, ["DNMOLC1"]= {4,132}, ["SOFYST"]= {5,226},
  21. ["FBI"]= {6,286}, ["DSHER"]= {6,288}, ["VBFYCRP"]= {5,11}, ["WMOPJ"]= {4,62}, ["CWFYFR1"]= {5,198}, ["VMAFF1"]= {12,124}, ["SWFOST"]= {5,232},
  22. ["CWMYHB2"]= {4,200}, ["DNB1"]= {11,121}, ["DWMOLC2"]= {4,33}, ["CSHER"]= {6,283}, ["DWFYLC2"]= {5,201}, ["SWFORI"]= {5,231}, ["VWMYBOX"]= {4,81},
  23. ["WMYBP"]= {4,26}, ["VWFYST1"]= {5,87}, ["FAM1"]= {8,105}, ["BMYBU"]= {4,17}, ["WMOTR1"]= {4,78}, ["DNMYLC"]= {4,128}, ["WFYSTEW"]= {5,76},
  24. ["COPGRL3"]= {5,190}, ["VHMYCR"]= {18,184}, ["VWMYCR"]= {18,181}, ["SBMYCR"]= {18,143}, ["BMYBOUN"]= {4,163}, ["WMYDRUG"]= {18,29}, ["BMYCR"]= {18,21},
  25. ["WMYCONB"]= {4,153}, ["LVFD1"]= {17,278}, ["SFEMT1"]= {16,276}, ["SWMOTR1"]= {4,77}, ["VWMOTR1"]= {4,212}, ["LAEMT1"]= {16,274}, ["LVEMT1"]= {16,275},
  26. ["BFOST"]= {5,10}, ["SWMORI"]= {4,235}, ["VLA1"]= {14,114}, ["TRIBOSS"]= {13,120}, ["VWFYWAI"]= {5,214}, ["SBFOST"]= {5,218}, ["VMAFF4"]= {12,127},
  27. ["HMYRI"]= {4,46}, ["BMYCON"]= {4,260}, ["WMYPIZZ"]= {4,155}, ["SPECIAL05"]= {4,294}, ["WMOPREA"]= {4,68}, ["DNB3"]= {11,123}, ["WMYGOL2"]= {4,37},
  28. ["OMYRI"]= {4,59}, ["BMOTR1"]= {4,79}, ["DNB2"]= {11,122}, ["VHFYST3"]= {5,246}, ["SBMOCD"]= {4,220}, ["GANGRL3"]= {5,195}, ["SFR3"]= {10,175},
  29. ["SFR2"]= {10,174}, ["WMYRI"]= {4,98}, ["LSV1"]= {9,108}, ["FAM2"]= {8,106}, ["SBFORI"]= {5,215}, ["WFYJG"]= {5,90}, ["SWAT"]= {6,285},
  30. ["LAPDM1"]= {6,284}, ["LVPD1"]= {6,282}, ["SPECIAL07"]= {4,296}, ["WBDYG1"]= {4,24}, ["NURGRL3"]= {5,193}, ["LAPD1"]= {6,280}, ["SPECIAL08"]= {4,297},
  31. ["HMYST"]= {4,48}, ["SOMOBU"]= {4,227}, ["SWMYHP1"]= {4,72}, ["WMYCD1"]= {4,261}, ["VMAFF3"]= {12,126}, ["HECK2"]= {4,259}, ["BMOSEC"]= {4,253},
  32. ["BIKERA"]= {4,247}, ["SMYST2"]= {4,242}, ["OFYRI"]= {5,55}, ["SBMOST"]= {4,222}, ["SWMOTR4"]= {4,239}, ["WMYMECH"]= {4,50}, ["VLA2"]= {14,115},
  33. ["OMYST"]= {4,60}, ["SWMOTR5"]= {4,230}, ["HFYRI"]= {5,40}, ["SPECIAL04"]= {4,293}, ["SMYST"]= {4,241}, ["BALLAS1"]= {7,102}, ["SOMYRI"]= {4,186},
  34. ["CROGRL3"]= {5,194}, ["VBMOCD"]= {4,182}, ["HMYCR"]= {4,47}, ["BMYTATT"]= {4,180}, ["BMOBAR"]= {4,156}, ["WMYAMMO"]= {4,179}, ["WMYBAR"]= {4,177},
  35. ["BMYPOL1"]= {4,66}, ["BMYBAR"]= {4,176}, ["BMYRI"]= {4,20}, ["SOMYST"]= {4,170}, ["BMOCHIL"]= {4,168}, ["WFYRI"]= {5,91}, ["WMYBELL"]= {4,167},
  36. ["BMYST"]= {4,22}, ["WMYCR"]= {18,100}, ["WMYST"]= {4,101}, ["CWMYFR"]= {4,161}, ["CWMOHB2"]= {4,160}, ["CWMOFR"]= {4,158}, ["WMYBU"]= {4,147},
  37. ["SPECIAL06"]= {4,295}, ["CWMYHB1"]= {4,162}, ["WFYSEX"]= {5,178}, ["VBMYELV"]= {4,83}, ["CWFOHB"]= {5,197}, ["VBMYBOX"]= {4,80}, ["WMYMOUN"]= {4,52},
  38. ["SPECIAL01"]= {4,290}, ["WMYSGRD"]= {4,71}, ["OMOBOAT"]= {4,210}, ["SWMYHP2"]= {4,73}, ["WFYCRK"]= {5,145}, ["BFYRI"]= {5,12}, ["SOFYRI"]= {5,169},
  39. ["OMOKUNG"]= {4,49}, ["HMYCM"]= {4,146}, ["HMORI"]= {4,43}, ["HMOGAR"]= {4,35}, ["DWMYLC1"]= {4,34}, ["SFPD1"]= {6,281}, ["WMYBMX"]= {4,23},
  40. ["VBFYST2"]= {5,244}, ["SWFYST"]= {5,233},["CWFYFR2"]= {5,199}, ["VWFYCRP"]= {5,172}, ["WMOSCI"]= {4,70}}
  41. for k,v in pairs(list) do
  42. if m == k
  43. then t = v[1] -- тип педа
  44.      m1 =v[2] -- модель педа
  45. end end
  46. m = m1
  47. requestModel(m) -- запрос модели
  48. while not isModelAvailable(v) do wait(0) end-- проверка на загруженность модели
  49. ped = createChar(t, m, x,y,z) -- 009A: 2@ = create_actor_playerPedtype 4 model #MALE01 at 0.0 0.0 0.0
  50. return ped
  51. end
  52.  

это упрощало создания педов, вот lua плагин https://vk.com/gtabuilder?w=wall-56513456_510

очень помогли скриптовые команды.

Автор: kenking
« : Июнь 15, 2019, 08:13:12 am »

К сожалению, по работе с lua скриптами ничего подсказать не могу.
Автор: egor230
« : Июнь 14, 2019, 04:11:12 pm »


 kenking, Бесконечно Вам благодарен. Потихоньку начинаю понимать, как это устроено.  Есть тестовой плагин, где экспериментирую.  Выходит маркер имеет свой id.
 Спасибо,  что Вы показали  как работает скриптовая комманда,  бывает привычнее использовать их, они похожи на опкоды cleo.
 Очень признательный, что вы  показали  как выводить целые числа на экран.

 Всегда хотел, написать плагин, позволяющий запускать lua скрипты для vc.
sdk имеет свой основный поток, который является  бесконечным циклом,  В каком-то роде. Если  там поставить задержу, например,  10 секунд, то на это время остановится игра.  Поэтому  запускаем  новый Независимый поток с флагом, для того,  чтобы  он был один.
Ищем  все lua файлы в папке,  запускаем в новом потоке с новым lua состоянием. Потоки и lua состояния  добавляются в вектора.
 Идет проверка на ошибки, счетчик запущенных скриптов увеличивается,  запускаем скрипт,  получаем в стек функцию main,  запускаем её.

В lua  находится функция main. она  имеет бесконечный цикл.  Всё работает, но есть одно но.  Как сделать перезагрузку всех скриптов?
 Нажимаем ctrl, проходим циклом for  вектор  c lua  состояниями,  снимаем со стека  функции, закрываем lua состоянием.
  Но к сожалению,  всё зависает.  Подскажите пожалуйста,  как правильно написать реализацию перезагрузке скриптов.
Код: C++
  1. void second(bool& reload) {
  2. vector<thread>t;//вектор для lua потоков.
  3. vector<lua_State*>luastate;// вектор для lua состояний.
  4.         for (auto const& de : fs::recursive_directory_iterator{ fs::current_path() / "lualoader" }) { // папка для поиска
  5.                 if (de.path().extension() == ".lua" || de.path().extension() == ".LUA") {
  6.                         string res = de.path().string();// перевод имя файла в строку.
  7.                         t.push_back(move((std::thread(search, res, std::ref(luastate)))));// добавить поток в вектор.
  8.                 }
  9.         };
  10.        
  11.         while (true) {
  12.                 if (KeyPressed(VK_CONTROL)) {// перезагрузка скрипта        
  13.                         this_thread::sleep_for(chrono::milliseconds(1));
  14.                         static unsigned int time = 0;// обнулить таймер.
  15.                         if (CTimer::m_snTimeInMilliseconds - time > 500) {
  16.                                 time = 0;// обнулить таймер
  17.         for (auto L : luastate) { lua_pop(L, lua_gettop(L));// снять со стека функцию main.
  18.         counts--;// уменьшить счетчик.
  19.                 lua_close(L);// закрыть состояние.
  20. };
  21.                                 for (auto& i : t) {
  22.                                         i.detach(); // все потоки независимы.
  23.                                 };
  24.                                 break;
  25.  
  26.                         };
  27.                 };
  28.         };
  29.  
  30.         if (counts == 0){// если нет запущенных скриптов.
  31.                 reload = false; // флаг, что можно запускать новый поток.
  32.  
  33.         };                     
  34. };
  35.  
  36. class Message {//имя класса
  37. public: Message() {
  38.         Events::gameProcessEvent += [] {//обработчик событий игры
  39.                 CPed* player = FindPlayerPed();// найти игрока
  40.                 if (!player) return;// проверка найден игрок
  41.                 if (reload == false) {  reload = true;// флаг, что уже запущен поток.
  42.                         thread th(second, std::ref(reload)); th.detach();// независимый поток.         
  43.                 }
  44.         };
  45. }
  46. } message;
  47.  
  48.  
Автор: kenking
« : Июнь 08, 2019, 08:25:44 pm »

Цитировать
Не думал, что маркер, это int.  Предполагал,  что мы должны передать  структуру.
Это ID маркера.

Цитировать
Конечно, как всегда столкнулся с трудностями,  как использовать скриптовую команду в качестве проверки?
Цитировать
Так же интересная ситуация с выводом целых чисел на экран, они не выводится.
Цитировать
Разобрался с проверками.
Цитировать
Только не получается дать оружие игроку через скриптовую команду.
Код: C++
  1. #include "plugin.h"
  2. #include "extensions\KeyCheck.h"
  3. #include "CMessages.h"
  4. #include "extensions\ScriptCommands.h"
  5. #include "eScriptCommands.h"
  6. #include "CWorld.h"
  7. #include "eWeaponModel.h"
  8. #include "eWeaponType.h"
  9. #include "CStreaming.h"
  10.  
  11. using namespace plugin;
  12.  
  13. class Test {
  14. public:
  15.     static int m_test;
  16.  
  17.     Test() {
  18.         Events::gameProcessEvent += [] {
  19.             CPed *player = FindPlayerPed();
  20.             KeyCheck::Update();
  21.             if (KeyCheck::CheckWithDelay('B', 1000)) {
  22.                 static char message[256];
  23.                 snprintf(message, 256, "test = %d", m_test);
  24.                 CMessages::AddMessageJumpQ(message, 1000, false);
  25.             }
  26.             if (player) {
  27.                 if (KeyCheck::CheckWithDelay('N', 1000)) {
  28.                     //if (player->m_bInVehicle)
  29.                     if (Command<COMMAND_IS_PLAYER_IN_ANY_CAR>(CWorld::PlayerInFocus))
  30.                         CMessages::AddMessageJumpQ(L"in car", 1000, 0);
  31.                     else
  32.                         CMessages::AddMessageJumpQ(L"not in car", 1000, 0);
  33.                 }
  34.                 if (KeyCheck::CheckWithDelay('M', 1000)) {
  35.                     //CWorld::Players[CWorld::PlayerInFocus].m_nMoney += 1000;
  36.                     Command <COMMAND_ADD_SCORE>(CWorld::PlayerInFocus, 1000);
  37.  
  38.                     /*CStreaming::RequestModel(MODEL_COLT45, 2);
  39.                     CStreaming::LoadAllRequestedModels(false);
  40.                     player->GiveWeapon(WEAPONTYPE_PISTOL, 100, true);
  41.                     player->SetCurrentWeapon(WEAPONTYPE_PISTOL);
  42.                     CStreaming::SetModelIsDeletable(MODEL_COLT45);*/
  43.                     Command<COMMAND_REQUEST_MODEL>(MODEL_COLT45, 2);
  44.                     Command<COMMAND_LOAD_ALL_MODELS_NOW>(false);
  45.                     if (Command<COMMAND_HAS_MODEL_LOADED>(MODEL_COLT45)) {
  46.                         Command<COMMAND_GIVE_WEAPON_TO_PLAYER>(CWorld::PlayerInFocus, WEAPONTYPE_PISTOL, 100, true);
  47.                         Command<COMMAND_SET_CURRENT_PLAYER_WEAPON>(CWorld::PlayerInFocus, WEAPONTYPE_PISTOL);
  48.                         Command<COMMAND_MARK_MODEL_AS_NO_LONGER_NEEDED>(MODEL_COLT45);
  49.                     }
  50.                 }
  51.             }
  52.         };
  53.     }
  54. } test;
  55.  
  56. int Test::m_test = 3;

Цитировать
Это очень удобно использовать скриптовые команды.
Скриптовые команды надо использовать в случае отсутствия в sdk нужных функций и классов (ну для тестов ещё, чтобы поучиться). В остальном надо писать код с  разобранными функциями. В примере такой альтернативный код закомментирован.
Пример с оружием есть в sdk, ты же уже про это спрашивал.
Автор: egor230
« : Июнь 08, 2019, 01:51:01 pm »

 Спасибо большое уважаемый kenking за ваш ответ. Это очень удобно использовать скриптовые команды. Благодаря им наметился  определенный прогресс, что радует.
Не думал, что маркер, это int.  Предполагал,  что мы должны передать  структуру.
Вот примеры, может кому-то облегчать путь.
Код: C++
  1. Command<COMMAND_ADD_BLIP_FOR_CHAR>(CPools::GetPedRef(ped), &blip);// стрелка над педом.
  2. Command <COMMAND_SET_CHAR_MONEY>(CPools::GetPedRef(ped), 1000);// дать денег педу, но почему-то выходит 1006, может это прибавка?.
  3.  

 Конечно, как всегда столкнулся с трудностями,  как использовать скриптовую команду в качестве проверки?
 Пробовал разные варианты, получал  только вылет.
Код: C++
  1.         bool mod;
  2. class Test {//имя класса
  3. public:
  4.  
  5.         Test() {
  6.                 Events::gameProcessEvent += [] {
  7.                         CPed* player = FindPlayerPed();
  8.                         KeyCheck::Update();
  9.  
  10.                         if (KeyCheck::CheckWithDelay('M', 1000)){
  11.                        
  12.                         Command<COMMAND_IS_PLAYER_IN_ANY_CAR>(CPools::GetPedRef(player), mod);
  13.                         if(mod == true){ CMessages::AddMessageJumpQ(L"in car", 1000, 0);
  14.                         }
  15.                         }
  16.                 };
  17.         }
  18. } test;
  19.  
  20.  

 Так же интересная ситуация с выводом целых чисел на экран, они не выводится.
Код: C++
  1. class Test {//имя класса
  2. public:
  3.  
  4.         Test() {
  5.                 Events::gameProcessEvent += [] {
  6.                         CPed* player = FindPlayerPed();
  7.                         KeyCheck::Update();
  8.  
  9.                         if (KeyCheck::CheckWithDelay('M', 300)){
  10.                                 int numb = 3;
  11.                                 static char x[256];
  12.                                 snprintf(x, 256, "x = %.d", numb);
  13.  
  14.                         }
  15.                 };
  16.         }
  17. } test;
  18.  

Все сделал по правилам форматирования сделал в с++, может, что-то упустил? Подскажите, пожалуйста.

Разобрался с проверками.
Код: C++
  1.  
  2.                         mod = Command<COMMAND_IS_PLAYER_IN_ANY_CAR>();
  3.                         if(mod== true){
  4.                         CMessages::AddMessageJumpQ(L"in car", 1000, 0);
  5.                 }
  6.                         else{
  7.                                 CMessages::AddMessageJumpQ(L"not in car", 1000, 0);
  8.                         }
  9.                 }
  10.  

Создать машину.
Код: C++
  1.                         if (KeyCheck::CheckWithDelay('M', 300)){
  2.                                 Command<COMMAND_REQUEST_MODEL>(MODEL_COMET);
  3.                                 bool f = Command<COMMAND_HAS_MODEL_LOADED>(MODEL_COMET);
  4.                         if ( f== true) {
  5.                                 CVector pos = player->GetPosition();
  6.                                 CVehicle* v = nullptr;
  7.                                 Command<COMMAND_CREATE_CAR>(MODEL_COMET, pos.x, pos.y+10, pos.z, &v);
  8.                 }
  9. }
  10.                 };
  11.  


Только не получается дать оружие игроку через скриптовую команду.

Код: Text
  1.                         if (KeyCheck::CheckWithDelay('M', 300)){
  2.                        
  3.                                 Command<COMMAND_REQUEST_MODEL>(MODEL_COLT45);
  4.                         if (Command<COMMAND_HAS_MODEL_LOADED>(MODEL_COLT45)) {
  5.                                
  6.                                 CMessages::AddMessageJumpQ(L"model load", 1000, 0);
  7. Command<COMMAND_GIVE_WEAPON_TO_PLAYER>(CPools::GetPedRef(player), WEAPONTYPE_PISTOL, 100);
  8.                 }
  9.  

Автор: kenking
« : Июнь 03, 2019, 09:37:28 am »

Цитировать
Как использовать эту скриптовую команду?
Скриптовая команда - это опкод, смотришь в eScriptCommands какому номеру опкода соответствует эта команда. Открываешь поиск опкодов в SB, находишь нужный опкод: 0162: tie_marker $2344 to_actor $2320 4 2
Смотришь параметры этого опкода.
Код: C++
  1. #include "plugin.h"
  2. #include "extensions\KeyCheck.h"
  3. #include "extensions\ScriptCommands.h"
  4. #include "eScriptCommands.h"
  5.  
  6. using namespace plugin;
  7.  
  8. class Test {
  9. public:
  10.     static int blip;
  11.    
  12.     Test() {
  13.         Events::gameProcessEvent += [] {
  14.             CPed *player = FindPlayerPed();
  15.             KeyCheck::Update();
  16.             if (player && KeyCheck::CheckWithDelay('M', 1000))
  17.                 Command<COMMAND_ADD_BLIP_FOR_CHAR_OLD>(CPools::GetPedRef(player), 4, 2, &blip);
  18.             if (player && KeyCheck::CheckWithDelay('N', 1000))
  19.                 Command<COMMAND_REMOVE_BLIP>(blip);
  20.         };
  21.     }
  22. } test;
  23.  
  24. int Test::blip;
Автор: egor230
« : Июнь 02, 2019, 12:41:45 am »

 Здравствуйте уважаемый kenking. Был  уверен,  что вы досконально знаете все функции в sdk. Вы же понимаете хочется всё и сразу.
Пока непонятно как это задержка работает.
Несколько лет это долго.
Советы и подсказки от других людей это конечно хорошо, в час по чайной ложке, а желание всё горит внутри. Например, учил с++ - посмотрел видеокурсы, переписал код, с ним поэкспериментировал, прочитал несколько книг, так учебный процесс прошел быстро.
А тут прямо буксую. Сегодня нашел вот что
Код: C++
  1. ped->SetObjective(OBJECTIVE_HASSLE_CHAR, player); // пед идет к игроку.
  2. ped->SetAttack(player);//пед бьет
  3. ped->Attack();// правой рукой.
  4.  
  5.  
Спасибо большое за ваше объяснение. Очень не хочется,чтобы такой гениальный проект забросили.

Как использовать эту скриптовую команду?
Код: C++
  1.  
  2.                                         CPed* ped = randomfindped(player, 30.0);
  3.                                         CObject *p;
  4.                                         Command<COMMAND_ADD_BLIP_FOR_CHAR_OLD>(CPools::GetPedRef(ped), p);
  5.  
Автор: kenking
« : Июнь 01, 2019, 09:40:13 am »

Цитировать
Иногда явного  эффекта от функции нет.  Например, что даёт  функция
ped->SetObjectiveTimer(60000);
 Да это таймер,  но никакой задержка  вы действиях педа не наблюдается.
Задержки и не должно быть. По-идеи это установка максимального времени на какое-то действие педа (как я это понимаю).

Цитировать
Скажите пожалуйста, когда завершится работа над  sdk plugin?  чтобы можно было  приступить к   документации всех функций,   тогда новичкам будет легче освоится.
Думаю, что ещё несколько лет.

Цитировать
Допустим, CLEO которая является хуком  знаю,  где посмотреть ее исходник на с++. Может  это поможет разобраться?  Посоветуйте, пожалуйста, книгу,  которая помогла вам стать  таким крутым специалистом??
Я учусь разбираться в классах игры также, как и ты и крутым специалистом себя не считаю. В некоторых случаях, чтобы ответить на твой вопрос, мне приходится самому его сначала разобрать. Никакой такой книги я не знаю. Мне помогли подсказки и советы DK и других пользователей, которые они писали в этой теме, в целом на этом форуме и других форумах.

Вот немного пояснений, которые я для себя сохранил:
Цитировать
Если есть IDA и idb-база, то для "распутывания ниточек" можно использовать такие приёмы:

Как определить, откуда вызывается данная функция?
1.Открываем код функции в основной вкладке.
2.Далее выбираем в меню пункт View - Open Subviews - Function calls - список Caller.

Как определить, откуда происходит обращение к данному адресу?
1.Вставляем курсор между буквами названия адреса. Например здесь
Code:

.data:00B7CB84 _currentTime dd ? ; DATA XREF: _sub_406E50r

вставляем курсор между любыми буквами _currentTime.
2.Жмём X. Открывается список ссылок на данный адрес.


Очень часто случается такое, что декомпилятор (hex-rays) выдаёт ошибку "switch analysis failed".
Случается это в функциях, где используется конструкция switch.
Случается это потому что (моё предположение) разные версии декомпилятора по-разному работают с этой
конструкцией.
В официальных доках рекомендуют вручную настроить эту конструкцию, но есть более простое решение:
пересобрать функцию.
Для этого надо преобразовать функцию в обычные данные, преобразовать данные в код, и создать функцию.

1. Нажимаем U на названии функции (Undefine function).
2. Нажимаем C на первом байте (Code)
3. Нажимаем P (Create function).

В exe есть 2 основных типа адресов - data и text (есть и другие типы). Если проводить аналогию со
скриптами, то адреса типа data можно сравнить с глобальными переменными - в них хранятся различные
значения (например, 0xB7CB84 - [dword] Глобальный таймер в ms, 0x8D2530 - [float] Плотность движения
пешеходов). В ходе игры отдельные процедуры exe читают эти значения или записывают в эти адреса новые
значения. Эти адреса (не все) можно читать/перезаписывать и в скрипте с помощью опкодов 0A8C/0A8D.
Назначение некоторых часто употребляемых data-адресов, а также смещений в структурах можно найти тут:
http://gtamodding.ru...еса_Памяти_(SA)
Что касается адресов типа text, то в них записаны отдельные команды, из которых в свою очередь
состоят процедуры exe. Сами по себе значения этих адресов во время игры не меняются, но их, как и
адреса data, можно (не все) менять скриптом - в этом случае в опкодах 0A8C/0A8D следует ставить
значение параметра virtual protect, равное 1. Понятно, что в случае изменения значения text-адреса,
процедура, которой он принадлежит, станет работать уже по новому алгоритму.
Для поиска нужных адресов и процедур незаменима idb-база от listener. Открыть её можно с помощью
IDA 5. В окне программы есть несколько вкладок, которые представляют код exe в различном виде.
Основные из них: "IDA View-A" - основной вид. Если текущий участок exe состоит из адресов типа data,
то они отображаются в виде списка, а если текущий участок является какой-то
процедурой (text-адреса), то она отобразится в виде блок-схемы. "Hex View-A" - побайтовое отображение
кода. Многие data-адреса и процедуры в базе проименованы, при активной вкладке "IDA View-A" можно
осуществлять их поиск по названию (Search - Text).
Есть ещё полезная вкладка Functions - список всех процедур exe. Если эта вкладка активна, то можно
осуществить поиск процедуры по названию (Search). Например, осуществив поиск по слову train, можно
найти процедуры, имеющие отношение к поездам. При щелчке по названию процедуры, активируется вкладка
"IDA View-A" и появится блок-схема этой процедуры, по которой можно исследовать, как она
работает (какие процедуры вызывает, со значениями каких адресов оперирует и т.д.).


Автор: egor230
« : Май 31, 2019, 08:46:39 pm »

Спасибо вам огромное уважаемый kenking за исключительно подробный ответ. Вы столько времени на него потратили. за это я вам очень благодарен. Примерно, понимаю какие параметры передавать в  функцию.  Вот нашел список  https://zredix.com/index.php?title=GTA_VC_Functions(1.0)

  Долго копался тестировал, может кому поможет.

Код: Text
  1. //ped->SetObjective(OBJECTIVE_KILL_CHAR_ANY_MEANS, player);// пед хочет убить игрока.
  2. //ped->SetObjective(OBJECTIVE_SPRINT_TO_AREA, point);// пед делает спринт к точке.
  3. //CMessages::AddMessage(L"ok", 2000, 0);// 0 текст белого цвета.
  4. //CMessages::AddBigMessage(L"ok", 2000, 0);/*0 большими, розовые как миссии пройдена, 1 надпись как названия миссии, 2 зеленым большими,
  5. // в правом нижним углу, 3 синим в центре, 4 зеленным в центре.*/
  6. //ped->SetObjective(OBJECTIVE_SOLICIT_VEHICLE, v);// ЦЕЛЬ.ПРОСИТЬ.ТРАНСПОРТ пед подходит к авто.
  7. //ped->SetObjective(OBJECTIVE_ENTER_CAR_AS_PASSENGER, v);// пед садится как пассажир.
  8. //ped->SetObjective(OBJECTIVE_DESTROY_CAR, v);// пед ударит авто.
  9. ped->SetDead();// как будь-то пед умер под ним кровь.
  10.  
  11.                                         Проверка пед не в воздухе, а на земле.
  12.                                         if(!ped->CheckIfInTheAir()){
  13.  
  14.                                                 CMessages::AddMessageJumpQ(L"ped not in air", 1000, 0);
  15.                                         }
  16.  
  17.  

 Иногда явного  эффекта от функции нет.  Например, что даёт  функция
ped->SetObjectiveTimer(60000);

 Да это таймер,  но никакой задержка  вы действиях педа не наблюдается.
или Idle(). псевкоду что-то перерисовывает.

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

 Допустим, CLEO которая является хуком  знаю,  где посмотреть ее исходник на с++. Может  это поможет разобраться?  Посоветуйте, пожалуйста, книгу,  которая помогла вам стать  таким крутым специалистом??
Автор: kenking
« : Май 29, 2019, 08:12:16 pm »

Цитировать
теперь  допустим берём emun OBJECTIVE_SOLICIT_VEHICLE,  какие параметры передать в функцию SetObjective.
Код: C++
  1. CPed *ped;
  2. CVehicle *vehicle;
  3. ped->SetObjective(OBJECTIVE_SOLICIT_VEHICLE, vehicle);

Цитировать
Пытаюсь разобрать функции  в псевдокоде, иногда псевкод простой функции отражается так.  Может, он не так должен отображается?
Учиться разбирать надо с маленьких функций.
Возьмём для примера функцию CPed::SetObjectiveTimer
Нажимаем F5 и получаем такой псевдокод:
Код: C++
  1. unsigned int __thiscall CPed::SetObjectiveTimer(int this, int a2)
  2. {
  3.   unsigned int result; // eax@2
  4.  
  5.   if ( a2 )
  6.   {
  7.     result = *(_DWORD *)(this + 1360);
  8.     if ( CTimer::m_snTimeInMilliseconds > result )
  9.     {
  10.       result = CTimer::m_snTimeInMilliseconds + a2;
  11.       *(_DWORD *)(this + 1360) = CTimer::m_snTimeInMilliseconds + a2;
  12.     }
  13.   }
  14.   else
  15.   {
  16.     *(_DWORD *)(this + 1360) = 0;
  17.   }
  18.   return result;
  19. }

Это метод класса CPed, значит первым параметром передаётся указатель на этот класс.
Ставим курсор мышки на this, нажимаем Y и вводим вместо int CPed* (или можно нажать правую клавишу мыши и в контекстном меню выбрать Convert to struct* и выбрать из списка имеющихся в базе структур CPed)
Получается так:
Код: C++
  1. unsigned int __thiscall CPed::SetObjectiveTimer(CPed *this, int a2)
Смотрим тип второго аргумента, там должен быть unsigned int, а у нас int, исправляем (курсор мыши на a2, нажимаем Y и добавляем unsigned перед int):
Код: C++
  1. unsigned int __thiscall CPed::SetObjectiveTimer(CPed *this, unsigned int a2)
Переменную a2 переименуем в time, курсор мыши на a2, нажимаем N и вводим time:
Код: C++
  1. unsigned int __thiscall CPed::SetObjectiveTimer(CPed *this, unsigned int time)
Смотрим в тех функциях, где вызывается эта функция есть ли возвращаемое значение (клавиша X и переход в место, где эта функция вызывается).
В данном случае возвращаемого значения нет. Меняем тип возвращаемого значения на void, курсор на названии функции и Y, воодим void вместо unsigned int:
Код: C++
  1. void __thiscall CPed::SetObjectiveTimer(CPed *this, unsigned int time)

Можно было все вышеперечисленные правки сделать в этом последнем действии (Y на названии функции и ввод нужных данных и изменение названий переменных), показал отдельно для наглядности.
В итоге получилось так:
Код: C++
  1. void __thiscall CPed::SetObjectiveTimer(CPed *this, unsigned int time)
  2. {
  3.   if ( time )
  4.   {
  5.     if ( CTimer::m_snTimeInMilliseconds > this->m_nObjectiveTimer )
  6.       this->m_nObjectiveTimer = CTimer::m_snTimeInMilliseconds + time;
  7.   }
  8.   else
  9.   {
  10.     this->m_nObjectiveTimer = 0;
  11.   }
  12. }

Всё стало ясно и понятно, не так ли?
Ну это простая функция и разбирать её легко, но начинать надо именно с таких простых функций.
Изменения надо сохранить в базе (нажать на иконку сохранения).


Возьмём для второго примера ещё одну небольшую функцию CPed::Teleport
Нажимаем F5 и получаем такой псевдокод:
Код: C++
  1. char __thiscall CPed::Teleport(CEntity *this, float a2, int a3, int a4)
  2. {
  3.   CEntity *v4; // ebx@1
  4.  
  5.   v4 = this;
  6.   CWorld::Remove(this);
  7.   v4->m_placement.m_matrix.pos.x = a2;
  8.   v4->m_placement.m_matrix.pos.y = *(float *)&a3;
  9.   v4->m_placement.m_matrix.pos.z = *(float *)&a4;
  10.   LOBYTE(v4[3].m_placement.m_matrix.pad1) &= 0xFEu;
  11.   v4[5].m_pRwObject = 0;
  12.   v4[5].m_placement.m_matrix.pAttached = 0;
  13.   v4[5].m_placement.m_matrix.bDeleteOnDetach = 0;
  14.   v4[2].m_placement.m_matrix.pad4 = 0;
  15.   return CWorld::Add((CPhysical *)v4);
  16. }

Это метод класса CPed, но сейчас в псевдокоде почему-то класс CEntity, вместо второго параметра CVector одна переменная типа float и две типа int, возвращаемое значение стоит char, хотя функция ничего не должна возвращать. Будем исправлять.
Нажимаем Y на названии функции и водим нужные данные:
Код: C++
  1. void __thiscall CPed__Teleport(CPed *this, CVector point)
Переименовываем переменную v2 в ped.
Получаем такой псевдокод:
Код: C++
  1. void __thiscall CPed::Teleport(CPed *this, CVector point)
  2. {
  3.   CPed *ped; // ebx@1
  4.  
  5.   ped = this;
  6.   CWorld::Remove(&this->physical.entity);
  7.   ped->physical.entity.m_placement.matrix.pos = point;
  8.   ped->bfFlagsA &= 0xFEu;
  9.   ped->m_nActionTimer = 0;
  10.   ped->fActionX = 0;
  11.   ped->fActionY = 0;
  12.   ped->physical.m_pPhysColliding = 0;
  13.   CWorld::Add(&ped->physical);
  14. }

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

 
Автор: egor230
« : Май 29, 2019, 09:52:23 am »

Здравствуйте, уважаемый kenking.   Спасибо большое я ваш  ответ. сделал плагин для тестов,  изучаю  Assembler  идёт очень тяжело.

 Пытаюсь разобрать функции  в псевдокоде, иногда псевкод простой функции отражается так.  Может, он не так должен отображается?

  Благодарю благодарю Вас за объяснения функций телепорта,  буду изучать как это работает на практике.
 Выходит это проверка сделан ли прыжок.
 Насчёт функции player->SetObjective(OBJECTIVE_RUN_TO_AREA, point);// заставить педа бежать в точку.  А функция ped->SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, point);// пед идет.

 Вообще  функция SetObjective  имеет 5  перегрузки.
    void SetObjective(eObjective objective);// emun.
    void SetObjective(eObjective objective, CVector arg1);// emun и вектор.
    void SetObjective(eObjective objective, float arg1, CVector const& arg2);// emun, float, вектор.
    void SetObjective(eObjective objective, short arg1, short arg2);// emun, int, int.
    void SetObjective(eObjective objective, void* arg1);// emun, функция.

 Это понятно,  теперь  допустим берём emun OBJECTIVE_SOLICIT_VEHICLE,  какие параметры передать в функцию SetObjective. Поймите меня правильно,  Очень хочу разобраться в этом.  Например, более- менее  понимаю в api lua,  вот написал  небольшую  подсказку новичкам
код https://pastebin.com/8f9UH56W

 Мне бы хотелось в будущем  написать  статьи,  Как создавать плагины.
 Посоветуйте пожалуйста,  какую литературу прочитать,  чтобы  понимать основы работы движка игры?
Автор: kenking
« : Март 29, 2019, 12:39:32 pm »

Цитировать
Вы пишите- надо смотреть как устроен в базе.
хорошо, что нужно изучить?  Чтобы в ней разбираться.
Отрыть базу в IDA. Взять простой опкод или простую функцию и попытаться понять, разобрать как он  устроен (как работает функция). Мне легче разбирать в псевдокоде (F5).

Цитировать
Не всегда название функции, помогают понять как они работают.
Поэтому я и написал, что надо смотреть в базе, где вызываются эти функции.

Цитировать
// чем отличается способы получение вектора?
CVector pos = player->GetPosition(); 
//CVector pos = player->m_placement.pos;
Ничем.
Код: C++
  1. inline CVector &GetPosition() {
  2.     return m_placement.pos;
  3. }

Цитировать
// телепорт чем отличает 2 функции телепорта?
Если в названии функции есть приставка Only, то при вращении (например, компонента транспорта) не придётся сохранять координаты позиции компонента, компонент просто повернётся на указанный градус и останется в той же позиции. Если использовать "похожую" функцию без этой приставки в названии, то надо перед вращением считывать координаты позиции компонента, после вращения их восстанавливать, так как координаты сбросятся в ноль после вращения. Аналогично для функций перемещения, только для значений углов поворота.

 
Цитировать
// v->CanPedJumpThis(player, pos.x);//?? прыжок?.
Это проверка может ли сделать прыжок. Смотри в базе, где вызывается
Код: C++
  1. if ( CPed::CanPedJumpThis(ped, pedTwo, &ped->physical.m_vecCollisionPower) )
  2.     CPed::SetJump(ped);
Обращай внимание на параметры.

Цитировать
//v->SetObjective(player, OBJECTIVE_RUN_TO_AREA, &pos);//не получается заставить идти педа в координаты.
Код: C++
  1. CVector offset = { 0.0f, 20.0f, 0.0f };
  2. CVector point = player->m_placement * offset;
  3. player->m_nPedFlags.bHasObjectiveCompleted = 0;
  4. player->SetObjective(OBJECTIVE_RUN_TO_AREA, point);

Что касается других функций. Сделай какой-нибудь простой плагин для тестов, например, так.
Код: C++
  1. #include "plugin.h"
  2. #include "CPed.h"
  3. #include "extensions\KeyCheck.h"
  4.  
  5. using namespace plugin;
  6.  
  7. class Test {
  8. public:
  9.     static CPed *GetRandomPed(CVector const &posn, float radius) {
  10.         std::vector<CPed *> peds;
  11.         for (auto ped : CPools::ms_pPedPool) {
  12.             if (DistanceBetweenPoints(ped->GetPosition(), posn) <= radius)
  13.                 peds.push_back(ped);
  14.         }
  15.         return peds.empty() ? nullptr : peds[plugin::Random(0, peds.size() - 1)];
  16.     }
  17.    
  18.     Test() {
  19.         Events::gameProcessEvent += [] {
  20.             KeyCheck::Update();
  21.             if (KeyCheck::CheckWithDelay('M', 500)) {
  22.                 CPed *player = FindPlayerPed();
  23.                 if (player) {
  24.                     CPed *ped = GetRandomPed(player->GetPosition(), 15.0f);
  25.                     if (ped) {
  26.                         CVector offset = { 0.0f, 2.0f, 0.0f };
  27.                         CVector point = player->m_placement * offset;
  28.                         ped->m_nPedFlags.bHasObjectiveCompleted = 0;
  29.                         ped->SetObjective(OBJECTIVE_RUN_TO_AREA, point);
  30.                     }
  31.                 }
  32.             }
  33.         };
  34.     }
  35. } test;

и проверяй нужные тебе функции (не забывай про правильную передачу параметров).


Автор: egor230
« : Март 28, 2019, 07:56:34 pm »

благодарю Вас за помощь kenking. пытаюсь разобраться. Вы пишите- надо смотреть как устроен в базе.
хорошо, что нужно изучить?  Чтобы в ней разбираться.  Было бы здорово к каждой функции иметь  комментарий, для лучшего понимания.
 Не всегда название функции, помогают понять как они работают.
 Всё это время вникал в класс cped,  Вот, Может это кому-то облегчить путь.
Код: C++
  1.  
  2.                                 // v->ClearInvestigateEvent();// пед уходит, опустить педа.
  3.                                 // v->ReactToAttack(player);// временно атакует
  4.                                 // CVector pla = player->m_placement.pos;
  5.                                 // CVector ped = v->m_placement.pos;
  6.                                  //v->FightHitPed(player,ped,pla,1);// как бы получает удар и теряет хп.
  7.  
  8.                                  
  9.                                  // чем отличается способы получение вектора?
  10.                                   CVector pos = player->GetPosition(); 
  11.                                    //CVector pos = player->m_placement.pos;                            
  12.  
  13.                                   // телепорт чем отличает 2 функции телепорта?                                                                                     
  14.                                  //player->m_placement.SetTranslate(pos.x, pos.y, pos.z + 13.0f);
  15.                                  //player->m_placement.SetTranslateOnly(pos.x, pos.y, pos.z + 13.0f);
  16.                                  
  17.                                  //v->m_placement.RotateX(45.0);// перемещение, поворот.
  18.                                  //player->m_placement.SetRotate(pos.x, pos.y, pos.z + 13.0f);// телепорт.
  19.                                  //player->m_placement.Rotate(pos.x, pos.y, pos.z + 13.0f);// телепорт в разные места.
  20.                
  21.                                  // v->CanPedJumpThis(player, pos.x);//?? прыжок?.
  22.                                 //v->Mug();//?
  23.                                  //v->DeadPedMakesTyresBloody();//?? может быть кровавые следы педа.
  24.  
  25.                                   //v->SetObjective(player, OBJECTIVE_RUN_TO_AREA, &pos);//не получается заставить идти педа в координаты.
  26.  
Автор: kenking
« : Март 21, 2019, 10:01:02 am »

Цитировать
как заставить педа бежать к координатам?
В который раз объясняю, что надо смотреть в базе, как устроен соответствующий опкод, без этого не разберёшься.
Код: C++
  1. CPed *ped;
  2. CVector *point;
  3. ped->m_nPedFlags.b32 = 0;
  4. CPed::SetObjective(ped, OBJECTIVE_RUN_TO_AREA, point);

Цитировать
в некоторые функциях есть параметр CVector, что передаем в таком случае?
Вектор и передаём.

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