Автор Тема: Перевозка транспорта  (Прочитано 10180 раз)

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #30 : Январь 19, 2019, 05:46:52 pm »
Цитировать
Есть опкод 01EC: make_car $2159 very_heavy 1
Он делает авто тяжелее и медленнее. Но я его не ковырял, так что может там всё настолько запутанно
Там всё просто:
Код: C++
  1. case SET_CAR_HEAVY:
  2. CRunningScript::CollectParameters(this, &this->m_nIp, 2);
  3. vehicle_01EC = CPool<CVehicle>::AtHandle(CPools::ms_pVehiclePool, ScriptParams[0].m_nIntValue);
  4. if ( ScriptParams[1].m_nIntValue )
  5.     vehicle_01EC->physical.m_nMoveFlags = vehicle_01EC->physical.m_nMoveFlags & 0xFE | 1;
  6. else
  7.     vehicle_01EC->physical.m_nMoveFlags &= 0xFEu;
  8. result = 0;
  9. break;

т.е.
Код: C++
  1. vehicle->m_nMoveFlags.bHeavy = 1;

UPD:
Это я для gta3 разобрал опкод. Для VC так:
Код: C++
  1. case 0x1EC:
  2.       CRunningScript::CollectParameters(this + 16, 2);
  3.       vehicle_01EC = CPool_CVehicle_CAutomobile_GetAt(ScriptParams[0]);
  4.       if ( ScriptParams[1] )
  5.       {
  6.         vehicle_01EC->physical.m_nMoveFlags = vehicle_01EC->physical.m_nMoveFlags & 0xFE | 1;
  7.         vehicle_01EC->physical.m_fMass = 3.0 * vehicle_01EC->m_pHandlingData->m_fMass;
  8.         turnMass_01EC = 5.0 * vehicle_01EC->m_pHandlingData->m_fTurnMass;
  9.       }
  10.       else
  11.       {
  12.         vehicle_01EC->physical.m_nMoveFlags &= 0xFEu;
  13.         vehicle_01EC->physical.m_fMass = vehicle_01EC->m_pHandlingData->m_fMass;
  14.         turnMass_01EC = vehicle_01EC->m_pHandlingData->m_fTurnMass;
  15.       }
  16.       vehicle_01EC->physical.m_fTurnMass = turnMass_01EC;
  17.       result = 0;
  18.       break;

т.е. как раз масса изменяется

Код: C++
  1. vehicle->m_nMoveFlags.bHeavy = 1;
  2. vehicle->m_fMass = vehicle->m_pHandlingData->m_fMass * 3.0f;
  3. vehicle->m_fTurnMass = vehicle->m_pHandlingData->m_fTurnMass * 5.0f;
« Последнее редактирование: Январь 19, 2019, 06:21:07 pm от kenking »

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 598
  • Репутация: +92/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #31 : Январь 19, 2019, 08:19:17 pm »
Уточню свое пожелание - в трафике скорость устраивает, там и так все тащатся как черепахи. Хотелось бы снизить лимит максимальной скорости именно для игрока, например взять из хэндлинга и поделить пополам, имитируя тяжесть прицепа. Сам тягач не хотелось бы утяжелять, превращая в локомотив, который всех снесет. Кроме того set_heavy плохо влияет на отображение колес при мягкой подвеске, они проседают, создавая развал. Нормального способа вытащить скорость или ускорение из хэндлинга через поля класса я не нашел, может это хранится умноженное на какой-то коэффициент. Можно и как-то проще придумать, например ограничить скорость при наличии прицепа 40 км/ч, только как это лучше сделать?

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #32 : Январь 20, 2019, 12:05:21 pm »
Есть опкод
04BA: set_car 0@ speed_instantly 5.0
Код: C++
  1. case 0x4BA:
  2.       CRunningScript::CollectParameters(this + 16, 2);
  3.       car_04BA = CPool<CVehicle>::AtHandle(ScriptParams[0]);
  4.       x_04BA = *&ScriptParams[1] * 0.016666668;
  5.       y_04BA = x_04BA * car_04BA->vehicle.physical.entity.m_placement.matrix.at.z;
  6.       z_04BA = x_04BA * car_04BA->vehicle.physical.entity.m_placement.matrix.at.y;
  7.       car_04BA->vehicle.physical.m_vecMoveSpeed.x = x_04BA * car_04BA->vehicle.physical.entity.m_placement.matrix.at.x;
  8.       car_04BA->vehicle.physical.m_vecMoveSpeed.y = z_04BA;
  9.       car_04BA->vehicle.physical.m_vecMoveSpeed.z = y_04BA;
  10.       if ( car_04BA->vehicle.m_pHandlingData->uFlags & 0x20000 && !car_04BA->vehicle.m_nVehicleClass )
  11.         car_04BA->fNegSpeed = 1046562734;       // 0.22
  12.       result = 0;
  13.       break;

Когда-то yelmi писал скрипт на ручную коробку передач для SA. Посмотри скрипт.

Если сильно не заморачиваться, то можно регулировать максимальную скорость так:
Код: C++
  1. playerCar->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity *= 0.5f; // уменьшаем при наличии прицепа
  2. playerCar->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity *= 2.0f; // восстанавливаем, когда прицеп отцеплен или игрок не в этом авто
  3.  

Правда изменение коснётся всего транспорта этой модели, в трафике в том числе, но в трафике это не так заметно, а на авто игрока ощущается изменение.



Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 598
  • Репутация: +92/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #33 : Январь 21, 2019, 03:30:51 pm »
Второй вариант похож, на то, что я ищу. Уменьшение вдое замедляет машину. В трафике машины до определенного момента не замечают изменений, пока не "оживут". Но я так и не понимаю, что хранится в этих параметрах трансмиссии. Если рассмотреть cTranmissionGear.h, то должно быть так:
Код: C++
  1.     float             m_fEngineAcceleration; // 0.1 to 10.0
  2.     float             m_fMaxGearVelocity; // 5.0 to 150.0
  3.     float             m_fMaxSpeed;
  4.     float             m_fMinGearVelocity;
  5.     float             m_fCurrentSpeed;

Кто-нибудь анализировал эти значения? У меня какая-то каша, не пойму закономерности. И они у меня не соответствуют комментариям из cTranmissionGear.h. Сложность в том, чтобы определить момент сцепки и отцепки, в которые нужно делить или умножать скорость на 2.

Код: C++
  1. m_fEngineAcceleration = 0.0006    // handling = 15.0
  2. m_fMaxGearVelocity = 0.788001    // handling = 120.0
  3. m_fMaxSpeed = 0.656667
Код: C++
  1. m_fEngineAcceleration = 0.0008    // handling = 10.0
  2. m_fMaxGearVelocity = 0.654667   // handling = 100.0
  3. m_fMaxSpeed = 0.545556
Код: C++
  1. m_fEngineAcceleration = 0.00144    // handling = 18.0
  2. m_fMaxGearVelocity = 0.964001    // handling = 150.0
  3. m_fMaxSpeed = 0.803334

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #34 : Январь 22, 2019, 04:07:48 pm »
Я думаю, что расхождения в значениях из-за разных единиц измерения. Возможно используется какой-то коэффициент. В том же опкоде 04BA значение умножается на 0.016666668. При получении скорости транспорта значение тоже приходится пересчитывать, чтобы получилось в км/ч и т.д.

Цитировать
Сложность в том, чтобы определить момент сцепки и отцепки, в которые нужно делить или умножать скорость на 2.
Можно сделать так:
Добавить к CVehicle следующие данные
Код: C++
  1. CVehicle *m_pTrailer;
  2. bool enableSpeed;
 
Две функции (названия дамми для сцепки у меня другие)
Код: C++
  1. static CVector GetFramePosn(RwFrame *frame) {
  2.         CVector posnFrame;
  3.         RwV3d posn = RwFrameGetLTM(frame)->pos;
  4.         posnFrame.x = posn.x;
  5.         posnFrame.y = posn.y;
  6.         posnFrame.z = posn.z;
  7.         return posnFrame;
  8.     }
  9.  
  10.     static void SearchTrailer(CVehicle *vehicle) {
  11.         if (vehComps.Get(vehicle).misc) {
  12.             for (auto trailer : CPools::ms_pVehiclePool) {
  13.                 if (vehComps.Get(trailer).hookup && (vehComps.Get(vehicle).connector == vehComps.Get(trailer).connector)) {
  14.                     if (DistanceBetweenPoints(GetFramePosn(vehComps.Get(vehicle).misc), GetFramePosn(vehComps.Get(trailer).hookup)) <= 2.0f) {
  15.                         vehComps.Get(vehicle).m_pTrailer = trailer; break;
  16.                     }
  17.                 }
  18.             }
  19.         }
  20.     }

Далее так (тест с выводом на экран нужных данных, делал для GTA3)
Код: C++
  1. Events::drawingEvent += [] {
  2.     CPed *player = FindPlayerPed();
  3.     if (player) {
  4.         if (player->m_pVehicle && player->m_pVehicle->m_nVehicleClass == VEHICLE_AUTOMOBILE) {
  5.             vehComps.Get(player->m_pVehicle).m_pTrailer = nullptr;
  6.             if (player->m_bInVehicle) {
  7.                 SearchTrailer(player->m_pVehicle);
  8.                 if (vehComps.Get(player->m_pVehicle).m_pTrailer) {
  9.                     if (vehComps.Get(player->m_pVehicle).enableSpeed) {
  10.                         player->m_pVehicle->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity *= 0.5f;
  11.                         vehComps.Get(player->m_pVehicle).enableSpeed = false;
  12.                     }
  13.                 }
  14.                 else if (!vehComps.Get(player->m_pVehicle).enableSpeed) {
  15.                     player->m_pVehicle->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity *= 2.0f;
  16.                     vehComps.Get(player->m_pVehicle).enableSpeed = true;
  17.                 }
  18.             }
  19.             else if (!vehComps.Get(player->m_pVehicle).enableSpeed) {
  20.                 player->m_pVehicle->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity *= 2.0f;
  21.                 vehComps.Get(player->m_pVehicle).enableSpeed = true;
  22.             }
  23.             CFont::SetScale(0.5f, 1.0f);
  24.             CFont::SetColor(CRGBA(238, 173, 53, 255));
  25.             CFont::SetJustifyOn();
  26.             CFont::SetFontStyle(0);
  27.             CFont::SetPropOn();
  28.             CFont::SetWrapx(600.0f);
  29.             wchar_t text[64];
  30.             swprintf(text, L"enableSpeed %d", vehComps.Get(player->m_pVehicle).enableSpeed);
  31.             CFont::PrintString(10.0f, 100.0f, text);
  32.             swprintf(text, L"MaxGearVelocity %.2f", player->m_pVehicle->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity);
  33.             CFont::PrintString(10.0f, 120.0f, text);
  34.             if (vehComps.Get(player->m_pVehicle).m_pTrailer) {
  35.                 swprintf(text, L"ID trailer %d", vehComps.Get(player->m_pVehicle).m_pTrailer->m_nModelIndex);
  36.                 CFont::PrintString(10.0f, 80.0f, text);
  37.             }
  38.         }
  39.     }
  40. };


Можно, конечно, заморочиться ещё сильнее и значение на которое уменьшается максимальная скорость, "завязать" на массу прицепа. Больше масса - больше уменьшаем значение. Например, масса прицепа до 1000 кг - уменьшаем в два раза, масса больше 1000 кг - уменьшаем в три раза.

У кого-нибудь есть другой вариант реализации этой идеи или оптимизации этих функций? Пишите пожалуйста. Идея заинтересовала и думаю тоже реализовать это в плагине для GTA3.

Оффлайн liaz6212

  • Призрак
  • Сообщений: 1
  • Репутация: +0/-0
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #35 : Январь 23, 2019, 11:03:15 am »
А если изменить значение массы тягача - это же должно повлиять на скорость и ускорение?
Увеличение массы даёт увеличение максимальной скорости.

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 598
  • Репутация: +92/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #36 : Январь 23, 2019, 11:26:09 am »
Почему тогда в гонках это не используют, стараясь максимально облегчить машину.

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #37 : Январь 24, 2019, 03:42:32 pm »
Цитировать
Кто-нибудь анализировал эти значения? У меня какая-то каша, не пойму закономерности.
Посмотрел в базе для GTA3, для VC коэффициенты вроде такие же.
Код: C++
  1. void __thiscall cHandlingDataMgr::ConvertDataToGameUnits(cHandlingDataMgr *this, tHandlingData *vehicleHandling)
  2. {
  3.   tHandlingData *handling;
  4.   float v3;
  5.   double v4;
  6.   double v5;
  7.   double v6;
  8.   double i;
  9.   float engineAcceleration;
  10.   double _engineAcceleration;
  11.  
  12.   handling = vehicleHandling;
  13.   vehicleHandling->m_transmissionData.m_fEngineAcceleration = vehicleHandling->m_transmissionData.m_fEngineAcceleration * 0.00039999999;
  14.   handling->m_transmissionData.m_fMaxGearVelocity = handling->m_transmissionData.m_fMaxGearVelocity * 0.0055555599;
  15.   handling->m_transmissionData.field_60 = handling->m_transmissionData.field_60 * 0.00039999999;
  16.   handling->m_fTurnMass = (handling->m_vecDimensions.y * handling->m_vecDimensions.y
  17.                          + handling->m_vecDimensions.x * handling->m_vecDimensions.x)
  18.                         * handling->m_fMass
  19.                         * 0.083333336;
  20.   if ( vehicleHandling->m_fTurnMass >= 10.0 )
  21.     vehicleHandling->m_fTurnMass = vehicleHandling->m_fTurnMass * 5.0;
  22.   vehicleHandling->m_fInvMass = 1.0 / vehicleHandling->m_fMass;
  23.   vehicleHandling->m_fBuoyancyConstant = 0.0080000004
  24.                                        * vehicleHandling->m_fMass
  25.                                        * 100.0
  26.                                        / vehicleHandling->m_nPercentSubmerged;
  27.   v3 = vehicleHandling->m_vecDimensions.z * (vehicleHandling->m_vecDimensions.x * 0.5) / vehicleHandling->m_fMass;
  28.   v4 = v3;
  29.   v5 = 0.0;
  30.   v6 = 100.0;
  31.   for ( i = vehicleHandling->m_transmissionData.m_fMaxGearVelocity;
  32.         v5 >= v6 && i > 0.0;
  33.         v6 = (1.0 / (v4 * i * i + 1.0) - 1.0) * -i )
  34.   {
  35.     i = i - 0.0099999998;
  36.     engineAcceleration = vehicleHandling->m_transmissionData.m_fEngineAcceleration * 0.1666666666666666;
  37.     v5 = engineAcceleration;
  38.   }
  39.   if ( vehicleHandling->index == RUMPO )
  40.   {
  41.     vehicleHandling->m_transmissionData.m_fMaxSpeed = vehicleHandling->m_transmissionData.m_fMaxGearVelocity;
  42.   }
  43.   else
  44.   {
  45.     vehicleHandling->m_transmissionData.m_fMaxSpeed = i;
  46.     vehicleHandling->m_transmissionData.m_fMaxGearVelocity = 1.2 * i;
  47.   }
  48.   LODWORD(vehicleHandling->m_transmissionData.m_fMinGearVelocity) = -0.2;
  49.   if ( vehicleHandling->m_transmissionData.m_nDriveType == DRIVE_TYPE_4x4 )
  50.     _engineAcceleration = vehicleHandling->m_transmissionData.m_fEngineAcceleration * 0.25;
  51.   else
  52.     _engineAcceleration = vehicleHandling->m_transmissionData.m_fEngineAcceleration * 0.5;
  53.   vehicleHandling->m_transmissionData.m_fEngineAcceleration = _engineAcceleration;
  54.   cTransmission::InitGearRatios(&vehicleHandling->m_transmissionData);
  55. }


Цитировать
Увеличение массы даёт увеличение максимальной скорости.
Проверил увеличивая/уменьшая значение массы непосредственно в игре- на саму скорость изменение значения массы не влияет, влияет только на тормозной путь и время остановки авто. Меньше масса - быстрее останавливается и короче путь и наоборот.

Оффлайн xanser

  • Главный Модератор
  • Постоялец
  • *****
  • Сообщений: 598
  • Репутация: +92/-0
  • Есть такая профессия - на работе сидеть
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #38 : Январь 25, 2019, 01:07:17 pm »
Теперь понятно, что это за геморрой, как-то муторно. Сделал по-простому - сканируется трафик, накапливается m_fMaxGearVelocity в массив эталонных ускорений всех моделей авто, встретившихся первый раз. При сканировании трафика восстанавливается ускорение из эталонного, если оно уже обнаружено. Дальше при обработке сцепки тягачу присваивается уменьшенное от эталонного значение из массива. Сам момент сцепки и отцепки не проверяется. Если прицеп отвалится, то просто пропустится этап уменьшения ускорения и останется только восстановленное.

Оффлайн DK

  • Новичок
  • **
  • Сообщений: 234
  • Репутация: +328/-0
    • dk22pac
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #39 : Январь 25, 2019, 06:03:26 pm »

1. В новой версией sdk добавлен автоматический конверт из RwV3d в CVector. Вот это:
static CVector GetFramePosn(RwFrame *frame) {
    CVector posnFrame;
    RwV3d posn = RwFrameGetLTM(frame)->pos;
    posnFrame.x = posn.x;
    posnFrame.y = posn.y;
    posnFrame.z = posn.z;
    return posnFrame;
}
Теперь можно записать так:
Код: C++
  1. // автоматическая конверсия RwV3d > CVector
  2. static CVector GetFramePosn(RwFrame *frame) {
  3.     return RwFrameGetLTM(frame)->pos;
  4. }
2. CFont::PrintString для GTA3/GTAVC поддерживает однобайтные строки (char *)
3. Для форматирования удобнее использовать функцию plugin::Format
4. Для быстрого вывода на экран можно использовать класс gamefont (обёртка над CFont)
5. Класс gamefont может выводить список из строк на экран
Код: C++
  1. // вывод списка строк на экран
  2. gamefont::Print({
  3.     Format("enableSpeed %d", vehComps.Get(player->m_pVehicle).enableSpeed),
  4.     Format("MaxGearVelocity %.2f", player->m_pVehicle->m_pHandlingData->m_transmissionData.m_fMaxGearVelocity),
  5.     Format("ID trailer %d", vehComps.Get(player->m_pVehicle).m_pTrailer ? vehComps.Get(player->m_pVehicle).m_pTrailer->m_nModelIndex : -1)
  6. }, 10, 100, 1, FONT_DEFAULT, 1, 1, color::Orange);
« Последнее редактирование: Январь 25, 2019, 06:06:56 pm от DK »
Plugin-SDK https://github.com/DK22Pac/plugin-sdk

Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv

Оффлайн kenking

  • Новичок
  • **
  • Сообщений: 237
  • Репутация: +16/-0
    • Просмотр профиля
Re: Перевозка транспорта
« Ответ #40 : Январь 26, 2019, 11:24:41 am »
Спасибо.
Цитировать
В новой версией sdk добавлен автоматический конверт из RwV3d в CVector.
Тогда там функция GetFramePosn вообще не нужна. Можно сразу так:
Код: C++
  1. if (DistanceBetweenPoints(RwFrameGetLTM(vehComps.Get(vehicle).misc)->pos, RwFrameGetLTM(vehComps.Get(trailer).hookup)->pos) <= 2.0f)

Цитировать
Класс gamefont может выводить список из строк на экран
Вот это очень полезная вещь!