const float ACTION_TIME_STEP = 0.05f;
const unsigned int TIME_FOR_KEYPRESS = 500;
struct Doorse {
static int componentByDoorId[6]; // Таблица перевода eDoors в Id компонента
static int m_nLastTimeWhenAnyActionWasEnabled; // Последнее время запуска события
enum eDoorEventType { // Тип события
DOOR_EVENT_OPEN, DOOR_EVENT_CLOSE
};
struct DoorEvent { // Класс события
bool m_active; eDoorEventType m_type; float m_openingState;
DoorEvent() { m_active = false; m_type = DOOR_EVENT_CLOSE; }
};
struct VehicleDoors {
DoorEvent events[6]; // События для всех 6 дверей
VehicleDoors(CVehicle*) {}
};
};
struct DoorsExample {
static int componentByDoorId[6]; // Таблица перевода eDoors в Id компонента
static int m_nLastTimeWhenAnyActionWasEnabled; // Последнее время запуска события
enum eDoorEventType { // Тип события
DOOR_EVENT_OPEN, DOOR_EVENT_CLOSE
};
struct DoorEvent { // Класс события
bool m_active; eDoorEventType m_type; float m_openingState;
DoorEvent() { m_active = false; m_type = DOOR_EVENT_CLOSE; }
};
struct VehicleDoors {
DoorEvent events[6]; // События для всех 6 дверей
VehicleDoors(CVehicle*) {}
};
static VehicleExtendedData<VehicleDoors> VehDoors; // Наше расширение
static void EnableDoorEvent(CAutomobile* automobile, eDoors doorId) { // Включить событие двери
if (automobile->IsComponentPresent(componentByDoorId[doorId])) {
CDamageManager* p;
if (p->GetDoorStatus(doorId) != DAMSTATE_NOTPRESENT) {
DoorEvent& event = VehDoors.Get(automobile).events[doorId];
if (event.m_type == DOOR_EVENT_OPEN)
event.m_type = DOOR_EVENT_CLOSE; // Если последнее событие - открытие, то закрываем
else
event.m_type = DOOR_EVENT_OPEN; // Если последнее событие закрытие - то открываем
event.m_active = true; // Включаем обработку
m_nLastTimeWhenAnyActionWasEnabled = CTimer::m_snTimeInMilliseconds;
}
}
};
static void ProcessDoors(CVehicle* vehicle) { // Обработка событий для конкретного авто
if (vehicle->m_nVehicleClass == VEHICLE_AUTOMOBILE) {
CAutomobile* automobile = reinterpret_cast<CAutomobile*>(vehicle);
for (unsigned int i = 0; i < 6; i++) { // Обрабатываем все события
eDoors doorId = static_cast<eDoors>(i);
DoorEvent& event = VehDoors.Get(automobile).events[doorId];
if (event.m_active) { // Если событие активно
if (event.m_type == DOOR_EVENT_OPEN) {
event.m_openingState += ACTION_TIME_STEP;
if (event.m_openingState > 1.0f) { // Если полностью открыли
event.m_active = false; // Отключаем обработку
automobile->OpenDoor(componentByDoorId[doorId], doorId, 1.0f); // Полностью открываем
event.m_openingState = 1.0f;
}
else
automobile->OpenDoor(componentByDoorId[doorId], doorId, event.m_openingState);
}
else {
event.m_openingState -= ACTION_TIME_STEP;
if (event.m_openingState < 0.0f) { // Если полностью открыли
event.m_active = false; // Отключаем обработку
automobile->OpenDoor(componentByDoorId[doorId], doorId, 0.0f); // Полностью открываем
event.m_openingState = 0.0f;
}
else
automobile->OpenDoor(componentByDoorId[doorId], doorId, event.m_openingState);
}
}
}
}
};
};
int DoorsExample::componentByDoorId[6] = { CAR_BONNET, CAR_BOOT, CAR_DOOR_LF, CAR_DOOR_RF, CAR_DOOR_LR, CAR_DOOR_RR };
int DoorsExample::m_nLastTimeWhenAnyActionWasEnabled = 0;
VehicleExtendedData<DoorsExample::VehicleDoors> DoorsExample::VehDoors;
class Message {//имя класса
public: Message() {
Events::gameProcessEvent += [] {//обработчик событий игры
Events::vehicleRenderEvent += DoorsExample::ProcessDoors; // Тут обрабатываем события, а также выключаем их
CPed* player = FindPlayerPed();// найти игрока.
if (!player) return;// проверка найден игрок
static unsigned int time = 0;// обнулить таймер
if (reload == false) {
if (CTimer::m_snTimeInMilliseconds - time > 500) {
this_thread::sleep_for(chrono::milliseconds(600));// задержка
time = 0;// обнулить таймер
reload = true;// флаг, что уже запущен поток.
}
thread th(second, std::ref(reload)); th.detach();// независимый поток.
};
};
}
} message;
int opendoorcar(lua_State* L) { // открыть дверь авто.
try {
if (LUA_TUSERDATA == lua_type(L, -2) && LUA_TNUMBER == lua_type(L, -1)) {// указатель на авто.
CVehicle* b = (CVehicle*)Userdata::get<CVehicle>(L, 1, false);// получить указатель на авто.
CAutomobile* automobile = reinterpret_cast<CAutomobile*>(b); // опять же, приведение типов. Т.к. мы будет юзать damageManager, нам нужно убедиться, что транспорт - это автомобиль (CAutomobile)
int door = Stack<int>::get(L, 2);
switch (door) {
case 0: {DoorsExample::EnableDoorEvent(automobile, BONNET); // 0 капот
break; }
case 1: {DoorsExample::EnableDoorEvent(automobile, BOOT); // 1 багажник
break; }
case 2: { DoorsExample::EnableDoorEvent(automobile, DOOR_FRONT_LEFT); // 2 левая передняя дверь
break; }
case 3: {DoorsExample::EnableDoorEvent(automobile, DOOR_FRONT_RIGHT); // 3 правая передняя дверь
break; }
case 4: {DoorsExample::EnableDoorEvent(automobile, DOOR_REAR_LEFT); // 4 левая задняя дверь
break; }
case 5: {DoorsExample::EnableDoorEvent(automobile, DOOR_REAR_RIGHT); // 5 правая задняя дверь
break; }
default:{}
}
return 0;
}
else { throw "bad argument in function opendoorcar option of the vehicle"; }
}
catch (const char* x) { writelog(x); }
return 0;
};