Visuals - Custom Themes - Random Events
Enjoy a bit of unpredictability with random events that can occur during certain driving conditions. This is purely cosmetic and has no impact on driving controls!
This commit is contained in:
parent
2867aafe65
commit
430ec81028
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import math
|
||||
import random
|
||||
import time
|
||||
import threading
|
||||
from typing import SupportsFloat
|
||||
@ -73,16 +74,21 @@ class Controls:
|
||||
self.frogpilot_toggles = FrogPilotVariables.toggles
|
||||
|
||||
self.drive_added = False
|
||||
self.fcw_random_event_triggered = False
|
||||
self.holiday_theme_alerted = False
|
||||
self.onroad_distance_pressed = False
|
||||
self.openpilot_crashed_triggered = False
|
||||
self.previously_enabled = False
|
||||
self.random_event_triggered = False
|
||||
self.speed_check = False
|
||||
|
||||
self.display_timer = 0
|
||||
self.drive_distance = 0
|
||||
self.drive_time = 0
|
||||
self.max_acceleration = 0
|
||||
self.previous_speed_limit = 0
|
||||
self.previous_v_cruise = 0
|
||||
self.random_event_timer = 0
|
||||
self.speed_limit_timer = 0
|
||||
|
||||
self.green_light_mac = MovingAverageCalculator()
|
||||
@ -415,6 +421,10 @@ class Controls:
|
||||
planner_fcw = self.sm['longitudinalPlan'].fcw and self.enabled
|
||||
if planner_fcw or model_fcw:
|
||||
self.events.add(EventName.fcw)
|
||||
self.fcw_random_event_triggered = True
|
||||
elif self.fcw_random_event_triggered and self.frogpilot_toggles.random_events:
|
||||
self.events.add(EventName.yourFrogTriedToKillMe)
|
||||
self.fcw_random_event_triggered = False
|
||||
|
||||
for m in messaging.drain_sock(self.log_sock, wait_for_one=False):
|
||||
try:
|
||||
@ -673,7 +683,17 @@ class Controls:
|
||||
turning = abs(lac_log.desiredLateralAccel) > 1.0
|
||||
good_speed = CS.vEgo > 5
|
||||
max_torque = abs(self.last_actuators.steer) > 0.99
|
||||
if undershooting and turning and good_speed and max_torque:
|
||||
if undershooting and turning and good_speed and max_torque and not self.random_event_triggered:
|
||||
event_choices = [1, 2]
|
||||
if self.sm.frame % (10000 // len(event_choices)) == 0 and self.frogpilot_toggles.random_events:
|
||||
event_choice = random.choice(event_choices)
|
||||
if event_choice == 1:
|
||||
lac_log.active and self.events.add(EventName.firefoxSteerSaturated)
|
||||
self.params_memory.put_int("CurrentRandomEvent", 1)
|
||||
elif event_choice == 2:
|
||||
lac_log.active and self.events.add(EventName.goatSteerSaturated)
|
||||
self.random_event_triggered = True
|
||||
else:
|
||||
lac_log.active and self.events.add(EventName.goatSteerSaturated if self.frogpilot_toggles.goat_scream else EventName.steerSaturated)
|
||||
elif lac_log.saturated:
|
||||
# TODO probably should not use dpath_points but curvature
|
||||
@ -936,6 +956,9 @@ class Controls:
|
||||
self.events.add(EventName.blockUser)
|
||||
|
||||
if os.path.isfile(os.path.join(sentry.CRASHES_DIR, 'error.txt')) and not self.openpilot_crashed_triggered:
|
||||
if self.frogpilot_toggles.random_events:
|
||||
self.events.add(EventName.openpilotCrashedRandomEvents)
|
||||
else:
|
||||
self.events.add(EventName.openpilotCrashed)
|
||||
self.openpilot_crashed_triggered = True
|
||||
|
||||
@ -957,6 +980,45 @@ class Controls:
|
||||
if self.frogpilot_toggles.lead_departing_alert and self.sm['frogpilotPlan'].leadDeparting:
|
||||
self.events.add(EventName.leadDeparting)
|
||||
|
||||
if self.frogpilot_toggles.random_events:
|
||||
acceleration = CS.aEgo
|
||||
|
||||
if not CS.gasPressed:
|
||||
self.max_acceleration = max(acceleration, self.max_acceleration)
|
||||
else:
|
||||
self.max_acceleration = 0
|
||||
|
||||
if 3.5 > self.max_acceleration >= 3.0 and acceleration < 1.5:
|
||||
self.events.add(EventName.accel30)
|
||||
self.params_memory.put_int("CurrentRandomEvent", 2)
|
||||
self.random_event_triggered = True
|
||||
self.max_acceleration = 0
|
||||
|
||||
elif 4.0 > self.max_acceleration >= 3.5 and acceleration < 1.5:
|
||||
self.events.add(EventName.accel35)
|
||||
self.params_memory.put_int("CurrentRandomEvent", 3)
|
||||
self.random_event_triggered = True
|
||||
self.max_acceleration = 0
|
||||
|
||||
elif self.max_acceleration >= 4.0 and acceleration < 1.5:
|
||||
self.events.add(EventName.accel40)
|
||||
self.params_memory.put_int("CurrentRandomEvent", 4)
|
||||
self.random_event_triggered = True
|
||||
self.max_acceleration = 0
|
||||
|
||||
conversion = 1 if self.is_metric else CV.KPH_TO_MPH
|
||||
v_cruise = max(self.v_cruise_helper.v_cruise_cluster_kph, self.v_cruise_helper.v_cruise_kph) * conversion
|
||||
|
||||
if 70 > v_cruise >= 69:
|
||||
if self.sm.frame % 25 == 0:
|
||||
if v_cruise == self.previous_v_cruise and not self.vCruise69_alert_played:
|
||||
self.events.add(EventName.vCruise69)
|
||||
self.vCruise69_alert_played = True
|
||||
self.previous_v_cruise = v_cruise
|
||||
else:
|
||||
self.vCruise69_alert_played = False
|
||||
self.previous_v_cruise = v_cruise
|
||||
|
||||
if self.frogpilot_toggles.speed_limit_alert or self.frogpilot_toggles.speed_limit_confirmation:
|
||||
current_speed_limit = self.sm['frogpilotPlan'].slcSpeedLimit
|
||||
desired_speed_limit = self.sm['frogpilotPlan'].unconfirmedSlcSpeedLimit
|
||||
@ -1058,6 +1120,13 @@ class Controls:
|
||||
self.previously_enabled |= (self.enabled or self.FPCC.alwaysOnLateral) and CS.vEgo > CRUISING_SPEED
|
||||
self.previously_enabled &= self.driving_gear
|
||||
|
||||
if self.random_event_triggered:
|
||||
self.random_event_timer += DT_CTRL
|
||||
if self.random_event_timer >= 4:
|
||||
self.random_event_triggered = False
|
||||
self.random_event_timer = 0
|
||||
self.params_memory.remove("CurrentRandomEvent")
|
||||
|
||||
signal_check = CS.vEgo >= self.frogpilot_toggles.pause_lateral_below_speed or not (CS.leftBlinker or CS.rightBlinker) or CS.standstill
|
||||
self.speed_check = CS.vEgo >= self.frogpilot_toggles.pause_lateral_below_speed or CS.standstill or signal_check and self.frogpilot_toggles.pause_lateral_below_signal
|
||||
|
||||
|
@ -1097,6 +1097,63 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .1, alert_rate=0.75),
|
||||
},
|
||||
|
||||
# Random Events
|
||||
EventName.accel30: {
|
||||
ET.WARNING: Alert(
|
||||
"UwU u went a bit fast there!",
|
||||
"(⁄ ⁄•⁄ω⁄•⁄ ⁄)",
|
||||
AlertStatus.frogpilot, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.uwu, 4.),
|
||||
},
|
||||
|
||||
EventName.accel35: {
|
||||
ET.WARNING: Alert(
|
||||
"I ain't giving you no tree-fiddy",
|
||||
"you damn Loch Ness monsta!",
|
||||
AlertStatus.frogpilot, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.nessie, 4.),
|
||||
},
|
||||
|
||||
EventName.accel40: {
|
||||
ET.WARNING: Alert(
|
||||
"Great Scott!",
|
||||
"🚗💨",
|
||||
AlertStatus.frogpilot, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.doc, 4.),
|
||||
},
|
||||
|
||||
EventName.firefoxSteerSaturated: {
|
||||
ET.WARNING: Alert(
|
||||
"Turn Exceeds Steering Limit",
|
||||
"IE Has Stopped Responding...",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.firefox, 4.),
|
||||
},
|
||||
|
||||
EventName.openpilotCrashedRandomEvents: {
|
||||
ET.PERMANENT: Alert(
|
||||
"openpilot crashed 💩",
|
||||
"Please post the error log in the FrogPilot Discord!",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.HIGHEST, VisualAlert.none, AudibleAlert.fart, 10.),
|
||||
},
|
||||
|
||||
EventName.vCruise69: {
|
||||
ET.PERMANENT: Alert(
|
||||
"Lol 69",
|
||||
"",
|
||||
AlertStatus.frogpilot, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.noice, 2.),
|
||||
},
|
||||
|
||||
EventName.yourFrogTriedToKillMe: {
|
||||
ET.PERMANENT: Alert(
|
||||
"Your frog tried to kill me...",
|
||||
"👺",
|
||||
AlertStatus.frogpilot, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.none, AudibleAlert.angry, 5.),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
BIN
selfdrive/frogpilot/assets/random_events/images/firefox.png
Normal file
BIN
selfdrive/frogpilot/assets/random_events/images/firefox.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 KiB |
BIN
selfdrive/frogpilot/assets/random_events/images/great_scott.gif
Normal file
BIN
selfdrive/frogpilot/assets/random_events/images/great_scott.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 221 KiB |
BIN
selfdrive/frogpilot/assets/random_events/images/tree_fiddy.gif
Normal file
BIN
selfdrive/frogpilot/assets/random_events/images/tree_fiddy.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 160 KiB |
BIN
selfdrive/frogpilot/assets/random_events/images/weeb_wheel.gif
Normal file
BIN
selfdrive/frogpilot/assets/random_events/images/weeb_wheel.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
BIN
selfdrive/frogpilot/assets/random_events/sounds/angry.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/angry.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/doc.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/doc.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/fart.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/fart.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/firefox.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/firefox.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/goat.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/goat.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/nessie.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/nessie.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/noice.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/noice.wav
Normal file
Binary file not shown.
BIN
selfdrive/frogpilot/assets/random_events/sounds/uwu.wav
Normal file
BIN
selfdrive/frogpilot/assets/random_events/sounds/uwu.wav
Normal file
Binary file not shown.
@ -33,6 +33,18 @@ static void drawIcon(QPainter &p, const QPoint ¢er, const QPixmap &img, cons
|
||||
p.restore();
|
||||
}
|
||||
|
||||
static void drawIconGif(QPainter &p, const QPoint ¢er, const QMovie &img, const QBrush &bg, float opacity) {
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setOpacity(1.0); // bg dictates opacity of ellipse
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(bg);
|
||||
p.drawEllipse(center.x() - btn_size / 2, center.y() - btn_size / 2, btn_size, btn_size);
|
||||
p.setOpacity(opacity);
|
||||
QPixmap currentFrame = img.currentPixmap();
|
||||
p.drawPixmap(center - QPoint(currentFrame.width() / 2, currentFrame.height() / 2), currentFrame);
|
||||
p.setOpacity(1.0);
|
||||
}
|
||||
|
||||
OnroadWindow::OnroadWindow(QWidget *parent) : QWidget(parent), scene(uiState()->scene) {
|
||||
QVBoxLayout *main_layout = new QVBoxLayout(this);
|
||||
main_layout->setMargin(UI_BORDER_SIZE);
|
||||
@ -296,7 +308,12 @@ ExperimentalButton::ExperimentalButton(QWidget *parent) : experimental_mode(fals
|
||||
{4, loadPixmap("../frogpilot/assets/wheel_images/rocket.png", {img_size, img_size})},
|
||||
{5, loadPixmap("../frogpilot/assets/wheel_images/hyundai.png", {img_size, img_size})},
|
||||
{6, loadPixmap("../frogpilot/assets/wheel_images/stalin.png", {img_size, img_size})},
|
||||
{7, loadPixmap("../frogpilot/assets/random_events/images/firefox.png", {img_size, img_size})},
|
||||
};
|
||||
|
||||
wheelImagesGif[1] = new QMovie("../frogpilot/assets/random_events/images/weeb_wheel.gif", QByteArray(), this);
|
||||
wheelImagesGif[2] = new QMovie("../frogpilot/assets/random_events/images/tree_fiddy.gif", QByteArray(), this);
|
||||
wheelImagesGif[3] = new QMovie("../frogpilot/assets/random_events/images/great_scott.gif", QByteArray(), this);
|
||||
}
|
||||
|
||||
void ExperimentalButton::changeMode() {
|
||||
@ -322,10 +339,39 @@ void ExperimentalButton::updateState(const UIState &s) {
|
||||
}
|
||||
|
||||
// FrogPilot variables
|
||||
int randomEvent = scene.current_random_event;
|
||||
|
||||
rotatingWheel = scene.rotating_wheel;
|
||||
wheelIcon = scene.wheel_icon;
|
||||
wheelIconGif = 0;
|
||||
|
||||
if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) {
|
||||
if (randomEvent == 0 && gifLabel) {
|
||||
delete gifLabel;
|
||||
gifLabel = nullptr;
|
||||
} else if (randomEvent == 1) {
|
||||
static int rotationDegree = 0;
|
||||
rotationDegree = (rotationDegree + 36) % 360;
|
||||
steeringAngleDeg = rotationDegree;
|
||||
wheelIcon = 7;
|
||||
update();
|
||||
|
||||
} else if (randomEvent == 2 || randomEvent == 3 || randomEvent == 4) {
|
||||
if (!gifLabel) {
|
||||
gifLabel = new QLabel(this);
|
||||
QMovie *movie = wheelImagesGif[randomEvent - 1];
|
||||
if (movie) {
|
||||
gifLabel->setMovie(movie);
|
||||
gifLabel->setFixedSize(img_size, img_size);
|
||||
gifLabel->move((width() - gifLabel->width()) / 2, (height() - gifLabel->height()) / 2);
|
||||
gifLabel->movie()->start();
|
||||
}
|
||||
}
|
||||
gifLabel->show();
|
||||
wheelIconGif = randomEvent - 1;
|
||||
update();
|
||||
|
||||
} else if (rotatingWheel && steeringAngleDeg != scene.steering_angle_deg) {
|
||||
steeringAngleDeg = scene.steering_angle_deg;
|
||||
update();
|
||||
steeringAngleDeg = scene.steering_angle_deg;
|
||||
} else if (!rotatingWheel) {
|
||||
@ -341,6 +387,7 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) {
|
||||
QPainter p(this);
|
||||
engage_img = wheelImages[wheelIcon];
|
||||
QPixmap img = wheelIcon != 0 ? engage_img : (experimental_mode ? experimental_img : engage_img);
|
||||
QMovie *gif = wheelImagesGif[wheelIconGif];
|
||||
|
||||
QColor background_color = wheelIcon != 0 && !isDown() && engageable ?
|
||||
(scene.always_on_lateral_active ? bg_colors[STATUS_ALWAYS_ON_LATERAL_ACTIVE] :
|
||||
@ -350,7 +397,11 @@ void ExperimentalButton::paintEvent(QPaintEvent *event) {
|
||||
(scene.navigate_on_openpilot ? bg_colors[STATUS_NAVIGATION_ACTIVE] : QColor(0, 0, 0, 166)))))) :
|
||||
QColor(0, 0, 0, 166);
|
||||
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, QColor(0, 0, 0, 166), (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg);
|
||||
if (wheelIconGif != 0) {
|
||||
drawIconGif(p, QPoint(btn_size / 2, btn_size / 2), *gif, background_color, 1.0);
|
||||
} else {
|
||||
drawIcon(p, QPoint(btn_size / 2, btn_size / 2), img, background_color, (isDown() || !engageable) ? 0.6 : 1.0, steeringAngleDeg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QMovie>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStackedLayout>
|
||||
#include <QWidget>
|
||||
@ -106,11 +108,20 @@ private:
|
||||
UIScene &scene;
|
||||
|
||||
QMap<int, QPixmap> wheelImages;
|
||||
QMap<int, QMovie*> wheelImagesGif;
|
||||
|
||||
QMovie engage_gif;
|
||||
QLabel *gifLabel;
|
||||
|
||||
bool docRandomEventTriggered;
|
||||
bool firefoxRandomEventTriggered;
|
||||
bool rotatingWheel;
|
||||
bool treeFiddyRandomEventTriggered;
|
||||
bool weebRandomEventTriggered;
|
||||
|
||||
int steeringAngleDeg;
|
||||
int wheelIcon;
|
||||
int wheelIconGif;
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,6 +42,15 @@ sound_list: dict[int, tuple[str, int | None, float]] = {
|
||||
AudibleAlert.warningSoft: ("warning_soft.wav", None, MAX_VOLUME),
|
||||
AudibleAlert.warningImmediate: ("warning_immediate.wav", None, MAX_VOLUME),
|
||||
|
||||
# Random Events
|
||||
AudibleAlert.angry: ("angry.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.doc: ("doc.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.fart: ("fart.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.firefox: ("firefox.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.nessie: ("nessie.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.noice: ("noice.wav", 1, MAX_VOLUME),
|
||||
AudibleAlert.uwu: ("uwu.wav", 1, MAX_VOLUME),
|
||||
|
||||
# Other
|
||||
AudibleAlert.goat: ("goat.wav", None, MAX_VOLUME),
|
||||
}
|
||||
@ -70,6 +79,18 @@ class Soundd:
|
||||
self.frogpilot_toggles = FrogPilotVariables.toggles
|
||||
|
||||
self.previous_sound_directory = None
|
||||
self.random_events_directory = BASEDIR + "/selfdrive/frogpilot/assets/random_events/sounds/"
|
||||
|
||||
self.random_events_map = {
|
||||
AudibleAlert.angry: MAX_VOLUME,
|
||||
AudibleAlert.doc: MAX_VOLUME,
|
||||
AudibleAlert.fart: MAX_VOLUME,
|
||||
AudibleAlert.firefox: MAX_VOLUME,
|
||||
AudibleAlert.goat: MAX_VOLUME,
|
||||
AudibleAlert.nessie: MAX_VOLUME,
|
||||
AudibleAlert.noice: MAX_VOLUME,
|
||||
AudibleAlert.uwu: MAX_VOLUME,
|
||||
}
|
||||
|
||||
self.update_frogpilot_sounds()
|
||||
|
||||
@ -80,9 +101,12 @@ class Soundd:
|
||||
for sound in sound_list:
|
||||
filename, play_count, volume = sound_list[sound]
|
||||
|
||||
try:
|
||||
if sound in self.random_events_map:
|
||||
wavefile = wave.open(self.random_events_directory + filename, 'r')
|
||||
else:
|
||||
if sound == AudibleAlert.goat and not self.frogpilot_toggles.goat_scream:
|
||||
continue
|
||||
try:
|
||||
wavefile = wave.open(self.sound_directory + filename, 'r')
|
||||
except FileNotFoundError:
|
||||
wavefile = wave.open(BASEDIR + "/selfdrive/assets/sounds/" + filename, 'r')
|
||||
@ -171,6 +195,9 @@ class Soundd:
|
||||
elif self.frogpilot_toggles.alert_volume_control and self.current_alert in self.volume_map:
|
||||
self.current_volume = self.volume_map[self.current_alert] / 100.0
|
||||
|
||||
elif self.current_alert in self.random_events_map:
|
||||
self.current_volume = self.random_events_map[self.current_alert]
|
||||
|
||||
self.get_audible_alert(sm)
|
||||
|
||||
rk.keep_time()
|
||||
|
@ -321,6 +321,7 @@ void ui_update_frogpilot_params(UIState *s) {
|
||||
scene.custom_icons = custom_theme ? params.getInt("CustomIcons") : 0;
|
||||
scene.custom_signals = custom_theme ? params.getInt("CustomSignals") : 0;
|
||||
scene.holiday_themes = custom_theme && params.getBool("HolidayThemes");
|
||||
scene.random_events = custom_theme && params.getBool("RandomEvents");
|
||||
|
||||
scene.disable_smoothing_mtsc = params.getBool("MTSCEnabled") && params.getBool("DisableMTSCSmoothing");
|
||||
scene.disable_smoothing_vtsc = params.getBool("VisionTurnControl") && params.getBool("DisableVTSCSmoothing");
|
||||
@ -419,6 +420,7 @@ void UIState::update() {
|
||||
// FrogPilot live variables that need to be constantly checked
|
||||
scene.conditional_status = scene.conditional_experimental && scene.enabled ? paramsMemory.getInt("CEStatus") : 0;
|
||||
scene.current_holiday_theme = scene.holiday_themes ? paramsMemory.getInt("CurrentHolidayTheme") : 0;
|
||||
scene.current_random_event = scene.random_events ? paramsMemory.getInt("CurrentRandomEvent") : 0;
|
||||
}
|
||||
|
||||
void UIState::setPrimeType(PrimeType type) {
|
||||
|
@ -208,6 +208,7 @@ typedef struct UIScene {
|
||||
bool onroad_distance_button;
|
||||
bool parked;
|
||||
bool pedals_on_ui;
|
||||
bool random_events;
|
||||
bool reverse_cruise;
|
||||
bool reverse_cruise_ui;
|
||||
bool right_hand_drive;
|
||||
@ -247,6 +248,7 @@ typedef struct UIScene {
|
||||
int conditional_speed_lead;
|
||||
int conditional_status;
|
||||
int current_holiday_theme;
|
||||
int current_random_event;
|
||||
int custom_colors;
|
||||
int custom_icons;
|
||||
int custom_signals;
|
||||
|
Loading…
x
Reference in New Issue
Block a user