if starting:    
    system.setThreadTiming(TimingTypes.HighresSystemTimer)
    system.threadExecutionInterval = 0
    
    def set_button(button, key):
        if keyboard.getKeyDown(key):
            v.setButton(button, True)
        else:
            v.setButton(button, False)
    
    def calculate_rate(max, time):
        if time > 0:
            return max / (time / system.threadExecutionInterval)
        else:
            return max
    int32_max = (2 ** 14) - 1
    int32_min = (( 2** 14) * -1) + 1
    
    v = vJoy[0]
    v.x, v.y, v.z, v.rx, v.ry, v.rz, v.slider, v.dial = (int32_min,) * 8
# =============================================================================================
# Axis inversion settings (multiplier): normal = 1; inverted = -1
# =============================================================================================
    global throttle_inversion, braking_inversion, clutch_inversion, handbraking_inversion
    throttle_inversion = 1
    braking_inversion = 1
    clutch_inversion = 1
    handbraking_inversion = 1
    
# =============================================================================================
# Mouse settings
# =============================================================================================
    
    global mouse_sensitivity, sensitivity_center_reduction
    mouse_sensitivity = 22.5
    sensitivity_center_reduction = 2.5
    
# =============================================================================================
# Ignition cut settings
# =============================================================================================
    global ignition_cut_time, ignition_cut_elapsed_time
    ignition_cut_enabled = True
    ignition_cut_time = 0
    ignition_cut_elapsed_time = 0
    
    global ignition_cut, ignition_cut_released
# Init values, do not change
    ignition_cut = True
    ignition_cut_released = True
    
# =============================================================================================
# Steering settings
# =============================================================================================
    global steering, steering_max, steering_min, steering_center_reduction    
# Init values, do not change
    
    steering = 0.0
    steering_max = float(int32_max)
    steering_min = float(int32_min)
    steering_center_reduction = 1.0
    
# =============================================================================================
# Throttle settings
# =============================================================================================
    
    global throttle_blip_enabled
    throttle_blip_enabled = True
# In milliseconds
    throttle_increase_time = 0
    throttle_increase_time_after_ignition_cut = 0
    throttle_increase_time_blip = 0
    throttle_decrease_time = 0
    
    global throttle, throttle_max, throttle_min
    
# Init values, do not change
    throttle_max = int32_max * throttle_inversion
    throttle_min = int32_min * throttle_inversion
    throttle = throttle_min
    
    global throttle_increase_rate, throttle_decrease_rate
    
# Set throttle behaviour with the increase and decrease time,
# the actual increase and decrease rates are calculated automatically
    throttle_increase_rate = calculate_rate(throttle_max, throttle_increase_time)
    throttle_increase_rate_after_ignition_cut = calculate_rate(throttle_max, throttle_increase_time_after_ignition_cut) 
    throttle_increase_rate_blip = calculate_rate(throttle_max, throttle_increase_time_blip)
    throttle_decrease_rate = calculate_rate(throttle_max, throttle_decrease_time) * -1
    
# =============================================================================================
# Braking settings
# =============================================================================================
    
# In milliseconds
    braking_increase_time = 0
    braking_decrease_time = 0
    
    global braking, braking_max, braking_min
# Init values, do not change
    braking_max = int32_max * braking_inversion
    braking_min = int32_min * braking_inversion
    braking = braking_min
    
    global braking_increase_rate, braking_decrease_rate
    
# Set braking behaviour with the increase and decrease time,
# the actual increase and decrease rates are calculated automatically
    braking_increase_rate = calculate_rate(braking_max, braking_increase_time)
    braking_decrease_rate = calculate_rate(braking_max, braking_decrease_time) * -1
    
# =============================================================================================
# HandBraking settings
# =============================================================================================
    
# In milliseconds
    handbraking_increase_time = 0
    handbraking_decrease_time = 0
    
    global handbraking, handbraking_max, handbraking_min
# Init values, do not change
    handbraking_max = int32_max * handbraking_inversion
    handbraking_min = int32_min * handbraking_inversion
    handbraking = handbraking_min
    
    global handbraking_increase_rate, handbraking_decrease_rate
    
# Set handbraking behaviour with the increase and decrease time,
# the actual increase and decrease rates are calculated automatically
    handbraking_increase_rate = calculate_rate(braking_max, braking_increase_time)
    handbraking_decrease_rate = calculate_rate(braking_max, braking_decrease_time) * -1
    
# =============================================================================================
# Clutch settings
# =============================================================================================   
# In milliseconds
    clutch_increase_time = 0
    clutch_decrease_time = 0
    
    global clutch, clutch_max, clutch_min
# Init values, do not change
    clutch_max = int32_max * clutch_inversion
    clutch_min = int32_min * clutch_inversion
    clutch = clutch_min
    
    global clutch_increase_rate, clutch_decrease_rate
    
# Set clutch behaviour with the increase and decrease time,
# the actual increase and decrease rates are calculated automatically
    clutch_increase_rate = calculate_rate(clutch_max, clutch_increase_time)
    clutch_decrease_rate = calculate_rate(clutch_max, clutch_decrease_time) * -1
    
# =============================================================================================
# Atribuição dos botões em teclas do teclado
# =============================================================================================
    
vJoy[0].setButton(0,int(keyboard.getKeyDown(Key.A)))
vJoy[0].setButton(1,int(keyboard.getKeyDown(Key.S)))
vJoy[0].setButton(2,int(keyboard.getKeyDown(Key.X)))
vJoy[0].setButton(3,int(keyboard.getKeyDown(Key.D)))
vJoy[0].setButton(4,int(keyboard.getKeyDown(Key.W)))
vJoy[0].setButton(5,int(keyboard.getKeyDown(Key.E)))
vJoy[0].setButton(6,int(keyboard.getKeyDown(Key.R)))
vJoy[0].setButton(7,int(keyboard.getKeyDown(Key.V)))
# =================================================================================================
# Logica da Direção "steering"
# =================================================================================================
if steering > 0:
    steering_center_reduction = sensitivity_center_reduction ** (1 - (steering / steering_max))
elif steering < 0:
    steering_center_reduction = sensitivity_center_reduction ** (1 - (steering / steering_min))
steering = steering + ((float(mouse.deltaX) * mouse_sensitivity) / steering_center_reduction)
if steering > steering_max:
    steering = steering_max
elif steering < steering_min:
    steering = steering_min
v.x = int(round(steering))
# =================================================================================================
# Clutch logic
# =================================================================================================
if (throttle_blip_enabled and keyboard.getKeyDown(Key.X)) or (ignition_cut_enabled and ignition_cut_released and keyboard.getKeyDown(Key.S)) or keyboard.getKeyDown(Key.C):
    clutch = clutch_max
else:
    clutch = clutch + clutch_decrease_rate
if clutch > clutch_max * clutch_inversion:
    clutch = clutch_max * clutch_inversion
elif clutch < clutch_min * clutch_inversion:
    clutch = clutch_min * clutch_inversion
v.slider = clutch
# =================================================================================================
# Throttle logic
# =================================================================================================
if ignition_cut_enabled and ignition_cut and ignition_cut_elapsed_time < ignition_cut_time:
    ignition_cut_elapsed_time = ignition_cut_elapsed_time + system.threadExecutionInterval
if ignition_cut_enabled and not ignition_cut_released and keyboard.getKeyUp(Key.X):
    ignition_cut_released = False
if throttle_blip_enabled and ((ignition_cut_enabled and not ignition_cut) or (not ignition_cut_enabled)) and keyboard.getKeyDown(Key.X):
    # Throttle blip
    throttle = throttle + throttle_increase_rate_blip
elif ignition_cut_enabled and ignition_cut_released and keyboard.getKeyDown(Key.S):
    # Ignition cut
    throttle = throttle_min
    ignition_cut = False
    ignition_cut_released = True
    ignition_cut_elapsed_time = 0
elif mouse.leftButton:
    if ignition_cut_enabled and ignition_cut and ignition_cut_elapsed_time >= ignition_cut_time:
        throttle = throttle_max
    else:
        throttle = throttle + throttle_increase_rate
else:
    throttle = throttle + throttle_decrease_rate
if ignition_cut_enabled and ignition_cut and ignition_cut_elapsed_time >= ignition_cut_time:
    ignition_cut = True
    ignition_cut_elapsed_time = 0
if throttle > throttle_max * throttle_inversion:
    throttle = throttle_max * throttle_inversion
elif throttle < throttle_min * throttle_inversion:
    throttle = throttle_min * throttle_inversion
v.y = throttle
# =================================================================================================
# Braking logic
# =================================================================================================
if mouse.rightButton:
    braking = braking + braking_increase_rate
else:
    braking = braking + braking_decrease_rate
if braking > braking_max * braking_inversion:
    braking = braking_max * braking_inversion
elif braking < braking_min * braking_inversion:
    braking = braking_min * braking_inversion
v.z = braking
# =================================================================================================
# HandBraking logic
# =================================================================================================
if keyboard.getKeyDown(Key.Q):
    handbraking = handbraking + handbraking_increase_rate
else:
    handbraking = handbraking + handbraking_decrease_rate
if handbraking > handbraking_max * handbraking_inversion:
    handbraking = handbraking_max * handbraking_inversion
elif handbraking < handbraking_min * handbraking_inversion:
    handbraking = handbraking_min * handbraking_inversion
v.rx = handbraking
# =================================================================================================
# PIE diagnostics logic
# =================================================================================================
diagnostics.watch(v.x)
diagnostics.watch(v.y)
diagnostics.watch(v.z)
diagnostics.watch(v.rx)
diagnostics.watch(v.slider)
diagnostics.watch(steering_center_reduction)
diagnostics.watch(throttle_blip_enabled)
diagnostics.watch(ignition_cut_enabled)
from ctypes import *
user32 = windll.user32
if starting:
    mouselock = False
toggle_mouselock = keyboard.getPressed(Key.O)
if toggle_mouselock:
    mouselock = not mouselock
if (mouselock):
    user32.SetCursorPos(0, 5000)