{$CLEO .cs}
{$USE cleo+}
{$USE ini} 
0000: nop
wait 0
wait 0

const
{0}LEFTSTICKX = 0xB73458       //<LS>
{1}LEFTSTICKY = 0xB7345A       //LS^
{2}RIGHTSTICKX = 0xB7345C      //<RS>
{3}RIGHTSTICKY = 0xB7345E      //RS^
{4}LEFTSHOULDER1 = 0xB73460    //LB
{5}LEFTSHOULDER2 = 0xB73462    //LT
{6}RIGHTSHOULDER1 = 0xB73464   //RB
{7}RIGHTSHOULDER2 = 0xB73466   //RT
{8}DPADUP = 0xB73468           //UP
{9}DPADDOWN = 0xB7346A         //DOWN
{10}DPADLEFT = 0xB7346C        //LEFT
{11}DPADRIGHT = 0xB7346E       //RIGHT
{12}START = 0xB73470           //START
{13}SELECT = 0xB73472          //SELECT
{14}SQUARE = 0xB73474          //X
{15}TRIANGLE = 0xB73476        //Y
{16}CROSS = 0xB73478           //A
{17}CIRCLE = 0xB7347A          //B
{18}LEFTSHOCK = 0xB7347C       //LS
{19}RIGHTSHOCK = 0xB7347E      //RS
{20}GUIDE = 0xB73480           //Guide
end

0AAA: 31@ = get_script_struct_named 'MANDRBY'
03A4: script_name 'MANDRBY'

0@ = 3

if or
    31@ == 0
    31@ == -1
jf @ILoveMyGirlfriendJessica

0@ = 2

if
    0AA2: 31@ = load_dynamic_library "CLEO+.cleo"
jf @ILoveMyGirlfriendJessica
if
    0AA4: 30@ = get_dynamic_library_procedure "GetCleoPlusVersion" library 31@
then
    0AA7: call_function_return 30@ num_params 0 pop 0 29@
end
0AA3: free_dynamic_library 31@
if
    29@ >= 0x1020000
jf @ILoveMyGirlfriendJessica

if
    0E20: is_on_samp
then
    31@ = 0
    0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "DisableOnSAMP"
    if
        31@ > 0
    then
        0A93: terminate_this_custom_script
    end
end

0@ = 1

if
    0AAB: does_file_exist "cleo\SA.ManualDrivebyRemake.cs"
then
    26@s = 'Remake'
    jump @ILoveMyGirlfriendJessica
end
if
    0AAB: does_file_exist "cleo\SA.ManualDrivebyRefixed.cs"
then
    26@s = 'Refixed'
    jump @ILoveMyGirlfriendJessica
end

:Initialization
0@ = 0

if
    0AAB: does_file_exist "cleo\DrivebySettings.ini"
jf @ILoveMyGirlfriendJessica

31@ = 0
0AC8: 31@ = allocate_memory size 256
0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "NextWeaponKey"

:KeyTable
wait 0
9@ = -1
0EC4: string_find 0 31@ ";" store_to 30@    
if 30@ > 0
then 0EC5: cut_string_at 31@ 30@
end
0EC4: string_find 0 31@ "//" store_to 30@    
if 30@ > 0
then 0EC5: cut_string_at 31@ 30@
end
0EC4: string_find 0 31@ " " store_to 30@
if
    30@ > 0
then    
    0D4C: 29@ = get_string_length 31@
    29@ -= 1
    if
        803B: not is_int_lvar_equal_to_int_lvar 29@ <> 30@
    then
        string_find 1 31@ " " store_to 29@   
        while 001D: is_int_lvar_greater_than_int_lvar 29@ > 30@
            0EC5: cut_string_at 31@ 29@ // Cut white spaces and everything until 2nd word
            0062: sub_int_lvar_from_int_lvar 29@ -= 30@
            if
                29@ <> 1
            jf @FinalCut
            0EC4: string_find 1 31@ " " store_to 29@
        end
    else
        :FinalCut
        0EC5: cut_string_at 31@ 30@
    end
end
0D4C: 30@ = get_string_length 31@
if
    30@ > 0
jf @FinishKeyTable
0EC2: set_string_upper 31@
0AD3: 0@v = string_format "%s" 31@
if
    30@ == 1    //Virtual keycodes match with ASCII codes for 0-9 and A-Z 
then
    0AC7: get_var_pointer 30@ = var 0@
    0A8D: 9@ = read_memory 30@ size 1 virtual_protect 1
    if or
        9@ < 48
        9@ > 90
    jf @FinishKeyTable
    9@ = -1
    if 0@V == "+"
    then 9@ = 187
    end
    if 0@V == ","
    then 9@ = 188
    end
    if 0@V == "-"
    then 9@ = 189
    end
    if 0@V == "."
    then 9@ = 190
    end
    if 0@V == "#"
    then 9@ = 191
    end
    if 0@V == "<"
    then 9@ = 226
    end  
    jump @FinishKeyTable
end
if or
0@v == "LMB"
0@v == "LEFTMOUSEBUTTON"
0@v == "LEFTMOUSE"
0@v == "LEFT MOUSE"
0@v == "LEFTBUTTON"
0@v == "LEFT BUTTON"
then 9@ = 1
end
if or
0@v == "RMB"
0@v == "RIGHTMOUSEBUTTON"
0@v == "RIGHTMOUSE"
0@v == "RIGHT MOUSE"
0@v == "RIGHTBUTTON"
0@v == "RIGHT BUTTON"
then 9@ = 2
end
if 0@v == "CANCEL"
then 9@ = 3
end
if or
0@v == "MMB"
0@v == "MIDDLEMOUSEBUTTON"
0@v == "MIDDLEMOUSE"
0@v == "MIDDLE MOUSE"
0@v == "MIDDLE BUTTON"
0@v == "MOUSEWHEELBUTTON"
0@v == "MOUSEWHEEL BUTTON"
0@v == "MOUSE WHEEL"
then 9@ = 4
end
if or
0@v == "BACK"
0@v == "BACKSPACE"
then 9@ = 8
end
if or
0@v == "TAB"
0@v == "TABULATOR"
then 9@ = 9
end
if 0@v == "CLEAR"
then 9@ = 12
end
if or
0@v == "RETURN"
0@v == "ENTER"
then 9@ = 13
end
if 0@v == "SHIFT"
then 9@ = 16
end
if or
0@v == "CTRL"
0@v == "CONTROL"
then 9@ = 17
end
if 0@v == "ALT"
then 9@ = 18
end
if 0@v == "PAUSE"
then 9@ = 19
end
if 0@v == "CAPITAL"
then 9@ = 20
end
if 0@v == "SPACE"
then 9@ = 32
end
if 0@v == "LEFT"
then 9@ = 37
end
if 0@v == "UP"
then 9@ = 38
end
if 0@v == "RIGHT"
then 9@ = 39
end
if 0@v == "DOWN"
then 9@ = 40
end
if 0@v == "NUMPAD0"
then 9@ = 96
end
if 0@v == "NUMPAD1"
then 9@ = 97
end
if 0@v == "NUMPAD2"
then 9@ = 98
end
if 0@v == "NUMPAD3"
then 9@ = 99
end
if 0@v == "NUMPAD4"
then 9@ = 100
end
if 0@v == "NUMPAD5"
then 9@ = 101
end
if 0@v == "NUMPAD6"
then 9@ = 102
end
if 0@v == "NUMPAD7"
then 9@ = 103
end
if 0@v == "NUMPAD8"
then 9@ = 104
end
if 0@v == "NUMPAD9"
then 9@ = 105
end
if 0@v == "MULTIPLY"
then 9@ = 106
end
if 0@v == "ADD"
then 9@ = 107
end
if 0@v == "SEPARATOR"
then 9@ = 108
end
if 0@v == "SUBTRACT"
then 9@ = 109
end
if 0@v == "DECIMAL"
then 9@ = 110
end
if 0@v == "DIVIDE"
then 9@ = 111
end
if 0@v == "F1"
then 9@ = 112
end
if 0@v == "F2"
then 9@ = 113
end
if 0@v == "F3"
then 9@ = 114
end
if 0@v == "F4"
then 9@ = 115
end
if 0@v == "F5"
then 9@ = 116
end
if 0@v == "F6"
then 9@ = 117
end
if 0@v == "F7"
then 9@ = 118
end
if 0@v == "F8"
then 9@ = 119
end
if 0@v == "F9"
then 9@ = 120
end
if 0@v == "F10"
then 9@ = 121
end
if 0@v == "F11"
then 9@ = 122
end
if 0@v == "F12"
then 9@ = 123
end

:FinishKeyTable
0AC9: free_memory 31@
31@ = 0
0@ = 0
1@ = 0
2@ = 0
3@ = 0

if
    23@ < 2
then
    if
        23@ == 0
    then
        0085: set_lvar_int_to_lvar_int 10@ = 9@
        if
            10@ < 1
        then
            0AF0: 10@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "NextWeaponKey"
            if
                10@ < 1
            then
                10@ = 51
            end
        end
        0AC8: 31@ = allocate_memory size 256
        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "LastWeaponKey"
    else
        0085: set_lvar_int_to_lvar_int 11@ = 9@
        if
            11@ < 1
        then
            0AF0: 11@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "LastWeaponKey"
            if
                11@ < 1
            then
                11@ = 49
            end
        end
        0AC8: 31@ = allocate_memory size 256
        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "DrivebyAimButton"
    end
    23@ += 1
    jump @KeyTable
end
0085: set_lvar_int_to_lvar_int 2@ = 9@
if
    2@ < 1
then
    0AF0: 2@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "DrivebyAimButton"
    if
        2@ < 1
    then
        2@ = 2
    end
end

wait 0

0AF0: 3@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "DrivebyControlType"
4@ = 4      //L1
5@ = 17     //Circle
if
    3@ == 3
then
    4@ = 5  //L2
    5@ = 7  //R2
end
if
    3@ == 4
then
    4@ = 7
    5@ = 5
end
if
    3@ == 5
then
    5@ = 6  //R1
end
if
    3@ == 6
then
    4@ = 6
    5@ = 4
end
0AF0: 6@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "DPadButtonsMode"
0AF0: 7@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "UseMouseWheel" 
0AF0: 8@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "SideLookButtons"
0AF0: 12@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "KeepAiming"

08BD: set_local_var_bit_const 1@ bit 8  //flag used for marking to be compatible with Weapon Zoom Unlimited Mod

0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "DisableBikeWeakPoint"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 0
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "CloseWindowsAgain"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 1
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "FreeLineOfSight"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 2
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "DisableOnMission"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 3
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "FPCameraCentering"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 19
    if
        31@ > 1
    then
        08BD: set_local_var_bit_const 1@ bit 20
    end
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSWITCH" key "EnableOnStory"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 22
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "NoAngleLimit"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 29
end
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "PrepareThrowAnim"
if
    31@ > 0
then
    08BD: set_local_var_bit_const 1@ bit 30
end


// Big Buffer Array Cake with two number 9 and extra dip

0AC6: get_label_pointer 14@ = label @Buffer

//---------Offsets

const
    // [WEAPONSETTINGS]
    Poor           = 0xC00  // 4
    Gangster       = 0xC04  // 4
    Hitman         = 0xC08  // 4
    Cars           = 0xC0C  // 1
    Bikes          = 0xC0D  // 1
    Helis          = 0xC0E  // 1
    Planes         = 0xC0F  // 1
    Boats          = 0xC10  // 1
    Trains         = 0xC11  // 1
    
    // [MAIN]
    NoDrWhAim      = 0xC12  // 1
    WiShMode       = 0xC13  // 1
    CrosshairMult  = 0xC14  // 4
    
    // Reload Buttons from Realistic Weapons Settings Mod
    KKey1          = 0xC18  // 2
    KKey2          = 0xC1A  // 2
    JKey1          = 0xC1C  // 2
    JKey2          = 0xC1E  // 2
    
    // [CAMERA]
    RestoreDist    = 0xC20  // 2
    JumpCutRe      = 0xC22  // 2
    JumpCutCarSpe  = 0xC24  // 4
    FOV1           = 0xC28  // 4
    FOV2           = 0xC2C  // 4
    FOV3           = 0xC30  // 4
    DistNearB      = 0xC34  // 4
    DistMidB       = 0xC38  // 4
    DistFarB       = 0xC3C  // 4
    HeightNearB    = 0xC40  // 4
    HeightMidB     = 0xC44  // 4
    HeightFarB     = 0xC48  // 4
    DistNearC      = 0xC4C  // 4
    DistMidC       = 0xC50  // 4
    DistFarC       = 0xC54  // 4
    HeightNearC    = 0xC58  // 4
    HeightMidC     = 0xC5C  // 4
    HeightFarC     = 0xC60  // 4
    
    // Temporary values
    DistAdr        = 0xC64  // 4
    DistVal        = 0xC68  // 4
    HeightVal      = 0xC6C  // 4
    AngleUpVal     = 0xC70  // 4
    AngleDownVal   = 0xC74  // 4
    SpVehAdr       = 0xC78  // 4
    SpVehVal       = 0xC7C  // 4
    TempWeapInfo   = 0xC80  // 4
    SniperFlags    = 0xC84  // 4
    
    // Memory Patch Flags
    SniperCrosshr  = 0xC88  // 1
    ClickSound     = 0xC89  // 1
    SnapShot       = 0xC8A  // 1
    CrosshrDecay   = 0xC8B  // 1
    CrosshrExpan   = 0xC8C  // 1
    Bunnyhop       = 0xC8D  // 1
    Hydraulics     = 0xC8E  // 1
    VehWeapon      = 0xC8F  // 1
    LookBehind     = 0xC90  // 1
    CamStuff       = 0xC91  // 1
    DisableMenu    = 0xC92  // 1   
end


//---- [WEAPONSETTINGS]

20@ = 16
0AC7: get_var_pointer 17@ = var 25@

for 30@ = 0 to 255 step 1   //iterate through possible weapon ID's
    if
        20@ == 16
    then
        wait 0  //wait after 16 ini reads to reduce overheat
        20@ = 0
    end
    20@ += 1
    
    0AD3: 22@s = string_format '%d' 30@

    :ReadWeaponSettings
    25@ = -2.0
    26@ = -2.0  //-1.0 and 0.0 are valid values
    27@ = -2.0
        
    31@ = 0
    0AC8: 31@ = allocate_memory size 256        
    if
        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "WEAPONSETTINGS" key 22@s
    then
        0AD4: 32@ = scan_string 31@ format "%f / %f / %f" 25@ 26@ 27@            
    end
    0AC9: free_memory 31@
    
    0A90: int_mul 23@ = 30@ * 0x0C  //offset for storing the values by weapon ID
    
    for 29@ = 0x00 to 0x08 step 0x04
        0D4E: 28@ = read_struct_offset 17@ offset 29@ size 4    //read content of 25@ 26@ 27@     
        if
            28@ > 0.0
        then
            0EF4: clamp_float 28@ min 0.01 max 9.99 store_to 28@
        end
        0A8E: int_add 22@ = 23@ + 29@
        0E28: write_struct_offset 14@ offset 22@ size 4 value 28@   //write content into buffer
    end
end
if
    30@ == 256
then
    22@s = 'Default'
    jump @ReadWeaponSettings
end

wait 0


// Store weapon settings of vehicle subclasses

for 30@ = Cars to Trains step 0x01
    31@ = 0
    0AC8: 31@ = allocate_memory size 256 
    if
        30@ == Cars
    then
        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "Cars"
    else
        if
            30@ == Bikes
        then
            0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "Bikes"
        else
            if
                30@ == Helis
            then
                0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "Helis"
            else
                if
                    30@ == Planes
                then
                    0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "Planes"
                else
                    if
                        30@ == Boats
                    then
                        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "Boats"
                    else
                        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key "Trains"
                    end
                end
            end
        end
    end
    25@ = 0
    26@ = 0
    27@ = 0
    0AD4: 32@ = scan_string 31@ format "%d/%d/%d" 25@ 26@ 27@
    0AC9: free_memory 31@
    13@ = 0
    if
        25@ > 0
    then
        08BD: set_local_var_bit_const 13@ bit 1
    end
    if
        26@ > 0
    then
        08BD: set_local_var_bit_const 13@ bit 2
    end
    if
        27@ > 0
    then
        08BD: set_local_var_bit_const 13@ bit 3
    end
    0E28: write_struct_offset 14@ offset 30@ size 1 value 13@     
end
if
    13@ > 0
then
    0A8C: write_memory 0x52A52F size 1 value 0xAB virtual_protect 0 //Disable cinematic camera on trains (from Mixsets sourcecode)
end
13@ = -1   


//---- Reload Buttons from Realistic Weapons Settings Mod

25@ = 0
26@ = 0
27@ = 0
28@ = 0
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\RWS_Infos.ini" section "ReloadMod" key "ReloadModActive"
if
    31@ > 1
then
    08BD: set_local_var_bit_const 1@ bit 27
    0AF0: 25@ = read_int_from_ini_file "cleo\RWS_Infos.ini" section "ReloadMod" key "KKey1"
    0AF0: 26@ = read_int_from_ini_file "cleo\RWS_Infos.ini" section "ReloadMod" key "KKey2"
    0AF0: 27@ = read_int_from_ini_file "cleo\RWS_Infos.ini" section "ReloadMod" key "JKey1"
    0AF0: 28@ = read_int_from_ini_file "cleo\RWS_Infos.ini" section "ReloadMod" key "JKey2"
    0EF7: clamp_int 25@ min 0 max 255 store_to 25@
    0EF7: clamp_int 26@ min 0 max 255 store_to 26@
    0EF7: clamp_int 27@ min 0 max 255 store_to 27@
    0EF7: clamp_int 28@ min 0 max 255 store_to 28@
end
0E28: write_struct_offset 14@ offset KKey1 size 2 value 25@
0E28: write_struct_offset 14@ offset KKey2 size 2 value 26@
0E28: write_struct_offset 14@ offset JKey1 size 2 value 27@
0E28: write_struct_offset 14@ offset JKey2 size 2 value 28@

wait 0


//---- [CAMERA]

31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "RestoreDistance"
0EF7: clamp_int 31@ min 0 max 3 store_to 31@ 
0E28: write_struct_offset 14@ offset RestoreDist size 2 value 31@
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "JumpcutRestore"
0EF7: clamp_int 31@ min 0 max 1000 store_to 31@
0E28: write_struct_offset 14@ offset JumpCutRe size 2 value 31@
31@ = 0
0AF2: 31@ = read_float_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "JumpcutCarSpeed"
0E28: write_struct_offset 14@ offset JumpCutCarSpe size 4 value 31@


// Camera Tweaks

for 30@ = FOV1 to HeightFarC step 0x0C
    25@ = -10.0
    26@ = -10.0
    27@ = -10.0
    31@ = 0               
    0AC8: 31@ = allocate_memory size 256    
    if
        30@ == FOV1
    then
        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "TweakFOV"
    else
        if
            30@ == DistNearB
        then
            0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "DistBike"
        else
            if
                30@ == HeightNearB
            then
                0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "HeightBike"
            else
                if
                    30@ == DistNearC
                then
                    0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "DistCar"
                else
                    0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "CAMERA" key "HeightCar"
                end
            end
        end
    end
    0AD4: 32@ = scan_string 31@ format "%f / %f / %f" 25@ 26@ 27@
    0AC9: free_memory 31@
    
    for 29@ = 0x00 to 0x08 step 0x04
        0D4E: 28@ = read_struct_offset 17@ offset 29@ size 4    //read content of 25@ 26@ 27@     
        if
            30@ <= FOV3
        then
            if
                28@ >= 1.0
            then
                0EF4: clamp_float 28@ min 10.0 max 99.9 store_to 28@
            else
                28@ = 70.0
            end
        else
            if
                28@ > -10.0
            then
                0EF4: clamp_float 28@ min -5.0 max 100.0 store_to 28@
            else
                if
                    30@ <= DistFarB
                then
                    28@ = 3.5
                else
                    if
                        30@ <= HeightFarB
                    then
                        28@ = 0.2
                    else
                        if
                            30@ <= DistFarC
                        then
                            28@ = 6.0
                        else
                            28@ = 0.4
                        end
                    end
                end
            end
        end                
        0A8E: int_add 22@ = 30@ + 29@
        0E28: write_struct_offset 14@ offset 22@ size 4 value 28@   //write content into buffer
    end
end

wait 0


//---- [MAIN]

0A8D: 30@ = read_memory 0x858CEC size 4 virtual_protect 0
0AF2: 31@ = read_float_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "CrosshairExpMult"
0EF4: clamp_float 31@ min 0.0 max 10.0 store_to 31@
006B: mult_float_lvar_by_float_lvar 31@ *= 30@
0E28: write_struct_offset 14@ offset CrosshairMult size 4 value 31@ 
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "NoDrivingWhileAiming"
0EF7: clamp_int 31@ min 0 max 2 store_to 31@
0E28: write_struct_offset 14@ offset NoDrWhAim size 1 value 31@
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "WindshieldMode"
0EF7: clamp_int 31@ min 0 max 2 store_to 31@
0E28: write_struct_offset 14@ offset WiShMode size 1 value 31@
31@ = 0
0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "MAIN" key "PreLoadIFP"
if and
    31@ > 0
    84EE: not has_animation_loaded "DRIVEBYS"
then
    04ED: request_animation "DRIVEBYS"
end     

if
    33@ >= 424242
then
    0AD1: print_formatted_now "Reloading completed." time 4000
end

29@ = -1
30@ = -1


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:Main
wait 100    //Performance tweak. If player isn't in the right condition, there's no need to check every frame

:Main0 
wait 0

if
    0256: is_player_playing $PLAYER_CHAR
jf @Main

if
    0ADC: test_cheat "MDRRELOAD"
then
    0ACE: print_help_formatted "Manual Driveby Refixed settings reloading start"
    if
        0@ <> 2
    gosub_if_false @ReenableAndPatchStuff
    if
        0@ <> 4
    gosub_if_false @EnableSideLook    
    0AC7: get_var_pointer 33@ = var 0@
    0A8C: write_memory 33@ size 128 value 0x00 virtual_protect 1    //reset variables
    33@ = 424242
    jump @Initialization
end
    
if
    8ADC: not test_cheat "MYNAMEISRAMBO"
gosub_if_false @Cheat
   
if
    8449: not is_char_sitting_in_any_car $PLAYER_ACTOR
then
    if
        0@ == 0
    jf @LeavingCar
    if
        8EB7: not is_on_scripted_cutscene
    jf @Main    
    if or
        15@ <> 0
        30@ <> -1
    then
        if
            15@ == 0
        gosub_if_false @RevertDual
        19@ = 0
        29@ = -1
        30@ = -1
        jump @NoDriveby
    end
        
    if
        09DE: is_char_getting_in_to_a_car $PLAYER_ACTOR           
    jf @Main
        
    0992: set_player_cycle_weapon_button $PLAYER_CHAR weapons_scrollable 0
    gosub @CheckValidSituation
    
    if and
        20@ > 0
        21@ > 0
        22@ > 0
        29@ <> 5
    then
        0555: remove_weapon_from_char 20@ from_actor $PLAYER_ACTOR  //prevents autoswitch to smg        
        repeat    
            wait 0
            if
                8248: not has_model_loaded 22@
            then
                0247: request_model 22@
            end              
        until 89DE: not is_char_getting_in_to_a_car $PLAYER_ACTOR       
        if
            0256: is_player_playing $PLAYER_CHAR
        then
            if
                8248: not has_model_loaded 22@
            then
                038B: load_all_models_now
            end
            01B2: give_weapon_to_char $PLAYER_ACTOR weapon 20@ ammo 21@
            04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 31@ model_to 32@
            gosub @SetWeaponSlot
        end
        0249: mark_model_as_no_longer_needed 22@  
    else
        repeat    
            wait 0              
        until 89DE: not is_char_getting_in_to_a_car $PLAYER_ACTOR
    end               
    0992: set_player_cycle_weapon_button $PLAYER_CHAR weapons_scrollable 1             
    30@ = -1
    jump @Main0
end

if or
    0EB7: is_on_scripted_cutscene
    89E7: not is_player_control_on $PLAYER_CHAR         //During cutscenes, inside tuning garage etc
    016B: fading                 
then
    if
        8EB7: not is_on_scripted_cutscene
    then
        if and
            09E7: is_player_control_on $PLAYER_CHAR
            016B: fading
        then
            0EC7: get_fade_alpha 31@
            if and
                0@ <> 2
                31@ > 128.0
                001D: is_int_lvar_greater_than_int_lvar TIMERB > 24@    //for not messing up with the fades by this script
            jf @MainConditions
        else
            0AAA: 31@ = get_script_struct_named 'CARMOD'
            if and
                31@ <> 0
                31@ <> -1
            jf @MainConditions        
        end
    end
    08BD: set_local_var_bit_const 1@ bit 26           
    if
        0@ > 0
    jf @Main0
    if and
        0@ > 2
        29@ <> 1 
    jf @NoDriveBy
    06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 1
    30@ = 0
    jump @NoDriveBy
end
            
:MainConditions
if
    08B7: is_local_var_bit_set_const 1@ bit 26
then
    08C3: clear_local_var_bit_const 1@ bit 26
    jump @Main
end
03C0: 23@ = store_car_char_is_in_no_save $PLAYER_ACTOR
if
    803B: not is_int_lvar_equal_to_int_lvar 23@ <> 16@  //Still the same car?
then
    0085: set_lvar_int_to_lvar_int 16@ = 23@
    19@ = -1.61
    jump @NoDriveBy
end

if
    0@ <> 4     //Skip additional condition checks if they have already been checked
then
    if
        0@ <> 3 //Excepted     
    jf @CheckFireButton
    if
        0@ == 2 //StoryDriveby
    then
        gosub @PatchDrivebyTask
        if
            31@ > 1
        then
            if
                31@ <> 2
            jf @Main0
            if or
                0E3E: is_button_just_pressed pad 0 button 4
                0E3E: is_button_just_pressed pad 0 button 17
            then
                0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 41 //CAudioEngine::ReportFrontendAudioEvent (Click Sound)
            end            
        end
        gosub @WeaponSwitch              
        jump @Main0
    end
    if
        0@ <> 1 //Forbidden
    jf @Main
    jump @ConditionRoot
end
                              
if
	0A4B: is_pc_using_joypad
then
    if and
        00E1: is_button_pressed pad 0 button 4@
        80E1: not is_button_pressed pad 0 button 5@
    then
        gosub @GetWeaponSlot
        if
            29@ > 1
        jf @Main0
        if
            0E3E: is_button_just_pressed pad 0 button 4@
        jf @SuppressFireButton
        04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 9@ model_to 19@
        gosub @GetShootRate
        if
            25@ > 0.0
        jf @SuppressNitro
        if or
            0E26: is_weapon_fire_type 30@ 1 //InstantHit
            0E26: is_weapon_fire_type 30@ 4 //Camera
        jf @SpecialWeapons
        if
            08B7: is_local_var_bit_set_const 13@ bit 1
        jf @SuppressFireButton
        if
            9@ > 0
        then
            if
                3@ == 1
            then
                0A8C: write_memory LEFTSHOULDER1 size 2 value 0x00 virtual_protect 0
            end 
            if
                3@ == 2
            then
                08BD: set_local_var_bit_const 1@ bit 25
                jump @DriveBy
            end
            if
                3@ > 2
            jf @DriveBy
            jump @StartDriveBy
        end
        0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 41 //CAudioEngine::ReportFrontendAudioEvent (Click Sound)
        jump @SuppressFireButton                			  				
    end
    
    if
        0E8D: is_any_fire_button_pressed 0
    then
        if
            3@ < 5
        jf @Main0
        if and
            00E1: is_button_pressed pad 0 button 17
            80E1: not is_button_pressed pad 0 button 4
        jf @FireButtonFunction
        if and
            3@ < 3
            8E3E: not is_button_just_pressed pad 0 button 5
            8E3E: not is_button_just_pressed pad 0 button 7
        jf @FireButtonFunction 
        if
            8@ <> 1
        jf @Main0
        if and
            80E1: not is_button_pressed pad 0 button 5
            80E1: not is_button_pressed pad 0 button 7
        jf @FireButtonFunction
        jump @Main0
    end
    
    if or
        3@ > 2
        8@ == 1
    then
        if or
            3@ < 3
            84C8: not is_char_in_flying_vehicle $PLAYER_ACTOR
        jf @NoDriveby    
        0A8D: 31@ = read_memory 0xB7CEEB size 1 virtual_protect 0   // CPlayerData: CanDoDriveBy
        if
            31@ == 1
        jf @NoDriveby
    end
    
    gosub @WeapSwitchPad
    
    jump @CheckOnMission
end

if
    0AB0: is_key_pressed 2@ //Aim button
then
    gosub @GetWeaponSlot
    if
        29@ > 1
    jf @Main0
    if
        0E3D: is_key_just_pressed 2@
    jf @SuppressFireButton 
    04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 9@ model_to 32@
    gosub @GetShootRate
    if
        25@ > 0.0
    jf @SuppressNitro                      
    if or
        0E26: is_weapon_fire_type 30@ 1 //InstantHit
        0E26: is_weapon_fire_type 30@ 4 //Camera
    jf @SuppressFireButton
    if
        08B7: is_local_var_bit_set_const 13@ bit 1              
    jf @SuppressFireButton  
    if
        9@ > 0
    then
        if
            0E3E: is_button_just_pressed pad 0 button 4 //If aim button = secondary fire button
        then
            08BD: set_local_var_bit_const 1@ bit 25
        end
        
        :DriveBy
        if
            8@ <> 1
        jf @StartDriveBy
        if or
            00E1: is_button_pressed pad 0 button 5
            00E1: is_button_pressed pad 0 button 7
        jf @StartDriveBy
        jump @VanillaDriveBy
    end
    0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 41 //CAudioEngine::ReportFrontendAudioEvent (Click Sound)
    jump @SuppressFireButton
end

:CheckFireButton //Disables nitro with primary fire button, hides weapon during bunnyhops, fires grenades and area effect weapons
if
    0E8D: is_any_fire_button_pressed 0
then
    :FireButtonFunction
    gosub @GetWeaponSlot
    if
        29@ == 1
    then
        04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 5 store_weapon_to 22@ ammo_to 23@ model_to 32@
        if
            23@ > 0
        jf @Main0
    end
    04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 9@ model_to 19@
    if
        25@ > 0.0
    then                                                  
        if
            00E1: is_button_pressed pad 0 button 4      //Secondary fire button
        then
            if and
                047A: is_char_on_any_bike $PLAYER_ACTOR
                29@ > 1
            jf @Main0                        
            06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 1   //Switches to fist for not showing the weapon
            repeat
                wait 0
            until 80E1: not is_button_pressed pad 0 button 4            
            jump @WeaponBack
        end
        
        if and
            0@ == 4
            8E26: not is_weapon_fire_type 30@ 1 //InstantHit                    
        then        
            :SpecialWeapons       
            if and
                0E26: is_weapon_fire_type 30@ 3 //AreaEffect
                08B7: is_local_var_bit_set_const 13@ bit 3
            then
                if or
                    30@ == 37   //Flamethrower
                    30@ == 41   //Spraycan
                    30@ == 42   //Extinguisher
                then
                    if
                        9@ < 1
                    jf @Spray
                    0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 42 //CAudioEngine::ReportFrontendAudioEvent (Click Sound)
                    jump @SuppressNitro
                end
            end
            if and
                0E26: is_weapon_fire_type 30@ 2 //Projectiles
                08B7: is_local_var_bit_set_const 13@ bit 2
            then
                0E83: get_current_char_weaponinfo $PLAYER_ACTOR store_to 26@
                0E87: get_weaponinfo_animgroup 26@ store_to 27@
                if
                    27@ == 28   //Grenade
                then
                    if
                        9@ < 1
                    jf @ThrowExplosives
                    0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 42 //CAudioEngine::ReportFrontendAudioEvent (Click Sound)
                    jump @SuppressNitro
                end
            end
            if
                30@ == 40
            then
                09D9: use_detonator
                017B: set_char_ammo $PLAYER_ACTOR 40 0
                04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 9 store_weapon_to 30@ ammo_to 31@ model_to 32@
                if or
                    30@ <> 39
                    31@ < 1
                then
                    04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 1 store_weapon_to 30@ ammo_to 31@ model_to 32@
                end
                gosub @SetWeaponSlot
                jump @SuppressNitro
            end
        end 
                                            
        :VanillaDriveBy
        if or
            18@ >= 0
            18@ == -5
        jf @Main0                                                                    
        04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 5 store_weapon_to 22@ ammo_to 23@ model_to 32@
        if
            23@ > 0
        then    
            if
                0@ == 3
            then
                0085: set_lvar_int_to_lvar_int 30@ = 22@
            end
            if and
                08B7: is_local_var_bit_set_const 1@ bit 27  //RWS Fix
                8E5D: not is_cheat_active 72    //Infinite ammo
                $_100_Percent_Complete == 0
            then
                19@ = -4.20                       
            end 
            06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 0   //Switches to slot 5 for reenabling vanilla shoot
        end
    end
    
    :SuppressNitro
    gosub @EnableSideLook
    TIMERA = 80                   
                                                                                     
    repeat
        gosub @DisableNitro
        if
            19@ == -4.20
        then
            0A96: 26@ = get_ped_pointer $PLAYER_ACTOR
            26@ += 0x610    //CWeapon in Slot 5
            0D4E: 27@ = read_struct_offset 26@ offset 0x08 size 4   //Current ammo in clip
            if
                27@ < 1
            then
                0A8C: write_memory CIRCLE size 2 value 0x00 virtual_protect 0
                0A8C: write_memory LEFTSHOULDER1 size 2 value 0x00 virtual_protect 0
            end
        end
        wait 0                   
        if or
            0E8D: is_any_fire_button_pressed 0
            00E1: is_button_pressed pad 0 button 7
            00E1: is_button_pressed pad 0 button 5
            0AB0: is_key_pressed 2@ //Aim button
        then
            TIMERA = 0
        end                                               
    until TIMERA > 80
                                                                              
    gosub @DisableSideLook
    
    if
        25@ > 0.0
    jf @EnableNitro
    
    :WeaponBack
    if
        0256: is_player_playing $PLAYER_CHAR
    jf @Main
    if and
        9@ < 1
        29@ <> 1                                                                                                                     
    gosub_if_false @SetWeaponSlot      //Switch back to weapon selected previously                      
    jump @SuppressFireButton
end

0A8D: 31@ = read_memory 0xB7CEEB size 1 virtual_protect 0   //CPlayerData: CanDoDriveBy
if
    0@ == 3 //Excepted vehicles
then
    if and
        31@ == 1
        13@ > 0
    jf @Main0
    if or
        88B7: not is_local_var_bit_set_const 1@ bit 3   //DisableOnMission
        8E1D: not is_on_mission                    
    jf @Main0
    jump @NoDriveBy                   
end
if or
    31@ == 1
    8@ <> 1
jf @NoDriveBy

gosub @WeapSwitchMouse

:CheckOnMission
if and
    08B7: is_local_var_bit_set_const 1@ bit 3   //DisableOnMission
    0E1D: is_on_mission
jf @Main0
jump @NoDriveBy


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:LeavingCar                                  
if and
    0@ <> 2
    83EE: not can_player_start_mission $PLAYER_CHAR //player is leaving the car
    8EB7: not is_on_scripted_cutscene
jf @NoDriveBy
if or
    816B: not fading
    801D: not is_int_lvar_greater_than_int_lvar TIMERB > 24@    //for not messing up with the fades by this script
jf @NoDriveBy 
if and
    0@ == 4
    08B7: is_local_var_bit_set_const 1@ bit 1   //CloseWindowsAgain
    88B7: not is_local_var_bit_set_const 1@ bit 16  // No CarWithoutWindows
    8119: not is_car_dead 16@
    8E42: not is_char_doing_task_id $PLAYER_ACTOR task_id 821   //dragged out car  
then
    02E3: get_car_speed 23@ car 16@
    if
        23@ < 17.0                    
    then
        if and
            89BB: not is_car_door_damaged 16@ has_visible_damage_on_component 2
            88A7: not is_car_door_fully_open 16@ componentB 2
        then
            0D33: set_car_door_window_state 16@ door 10 state 0     //left front
        end
        if and
            89BB: not is_car_door_damaged 16@ has_visible_damage_on_component 3
            88A7: not is_car_door_fully_open 16@ componentB 3
        then
            0D33: set_car_door_window_state 16@ door 8 state 0      //right front
        end
        if and
            89BB: not is_car_door_damaged 16@ has_visible_damage_on_component 4
            88A7: not is_car_door_fully_open 16@ componentB 4
        then
            0D33: set_car_door_window_state 16@ door 11 state 0     //left rear
        end
        if and
            89BB: not is_car_door_damaged 16@ has_visible_damage_on_component 5
            88A7: not is_car_door_fully_open 16@ componentB 5
        then
            0D33: set_car_door_window_state 16@ door 9 state 0      //right rear
        end    
    end
end
if
    30@ > -1
then
    06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 1 //however forces the last used weapon stay selected
    06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 0 //weapon back
    gosub @SetWeaponSlot
end

while 0E4A: is_char_exiting_any_car $PLAYER_ACTOR
    wait 0
end
           
:NoDriveBy
if
    0@ <> 2
gosub_if_false @ReenableAndPatchStuff
if
    0@ <> 4
gosub_if_false @EnableSideLook
08C3: clear_local_var_bit_const 1@ bit 13
08C3: clear_local_var_bit_const 1@ bit 15
08C3: clear_local_var_bit_const 1@ bit 16
08C3: clear_local_var_bit_const 1@ bit 17
08C3: clear_local_var_bit_const 1@ bit 18
08C3: clear_local_var_bit_const 1@ bit 21
13@ = -1
0@ = 0
jump @Main0


:ConditionRoot
0@ = 1

if and
    8241: not is_player_in_remote_mode $PLAYER_CHAR
    8A32: not is_char_attached_to_any_car $PLAYER_ACTOR
jf @Main

if
    13@ <> -1
gosub_if_false @CheckValidSituation
           
046C: get_driver_of_car 31@ = car 16@        
if
    87D6: not is_int_lvar_equal_to_int_var 31@ <> $PLAYER_ACTOR
then
    08BD: set_local_var_bit_const 1@ bit 17
    08BD: set_local_var_bit_const 1@ bit 21
    if
        0E1D: is_on_mission
    then
        if or
            0E42: is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
            89E7: not is_player_control_on $PLAYER_CHAR
        then
            19@ = 0 
            if
                08B7: is_local_var_bit_set_const 1@ bit 22 //EnableOnStory
            jf @Main
            if
                30@ > -1
            then
                if
                    8E26: not is_weapon_fire_type 30@ 1 //InstantHit
                then
                    29@ = -1
                    30@ = -1
                end
            end
            gosub @Get_Weapon               
            gosub @DisableAndPatchStuff           
            gosub @DisableSideLook
            gosub @BulletModFix
            0@ = 2
            jump @Main0
        end
    end
end

30@ = -1

if or
    13@ > 0
    18@ >= 0
jf @Main0

if or
    3@ < 3
    8A4B: not is_pc_using_joypad
    84C8: not is_char_in_flying_vehicle $PLAYER_ACTOR
jf @Main0

0@ = 3       

0A97: 17@ = get_vehicle_pointer 16@
17@ += 0x8A4    //pointer to nitro level

if and
    13@ <> 0
    19@ == 0
jf @Main0

0@ = 4

if
    88B7: not is_local_var_bit_set_const 1@ bit 16
then    
    if and
        18@ <> 15   // Coach
        18@ <> 17   // Dozer
        18@ <> 18   // Kart
        18@ <> 25   // BF Injection & Bloodring Banger
        18@ <> 28   // Tractor & Mower
    jf @NoGlass
    31@ = 0
    0AF0: 31@ = read_int_from_ini_file "cleo\DrivebySettings.ini" section "CARSWITHOUTWINDOWS" key 26@s
    if
        31@ > 1
    then
        :NoGlass
        08BD: set_local_var_bit_const 1@ bit 16 // Flag for cars without door windows
        08BD: set_local_var_bit_const 1@ bit 17 // Flag for cars without windshield
    else
        if
            31@ == 1
        then
            08BD: set_local_var_bit_const 1@ bit 16
        end
        0D4E: 31@ = read_struct_offset 14@ offset WiShMode size 1
        if
            31@ < 1
        then
            08BD: set_local_var_bit_const 1@ bit 17 // Windshield breaking is turned off     
        else
            if
                31@ > 1
            then
                08BD: set_local_var_bit_const 1@ bit 18 // Windshield Mode 2 (Old anims)
            end
        end
    end
end
  
07E4: get_model_dimensions 9@ dimensions_cornerA_to 21@ 22@ 23@ dimensions_cornerB_to 26@ 27@ 28@
0063: sub_float_lvar_from_float_lvar 26@ -= 21@
0063: sub_float_lvar_from_float_lvar 28@ -= 23@
if or
    9@ == 578  // DFT-30
    9@ == 554  // Yosemite
    28@ < 2.1
then
    08BD: set_local_var_bit_const 1@ bit 15     // Flat vehicles
else
    if
        28@ > 2.70  // Model height
    then
        06A3: get_car_mass 16@ mass_to 31@
        if or
            26@ > 2.95  // Model width
            31@ > 3500.0
            0969: is_big_vehicle 16@
        then
            08BD: set_local_var_bit_const 1@ bit 13 // Big Vehicles
        end
    end
end

0D4E: 31@ = read_struct_offset 14@ offset NoDrWhAim size 1
if
    31@ < 1
then
    08BD: set_local_var_bit_const 1@ bit 21
else    
    if and
        31@ > 1
        18@ <> 12   // Quadbike
        847A: not is_char_on_any_bike $PLAYER_ACTOR
    then
        08BD: set_local_var_bit_const 1@ bit 21
    end
end

gosub @DisableSideLook

jump @Main0


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:ChangeSideLook    
if
    8@ > 1
return_if_false
if or
    8A4B: not is_pc_using_joypad
    3@ < 3
return_if_false
jump @SideLook2

:DisableSideLook
23@ = 0x9090
jump @SideLook

:EnableSideLook
23@ = 0xC084

:SideLook  
if
    0@ <> 3
return_if_false
if or
    8A4B: not is_pc_using_joypad
    3@ < 3
then
    if
        8@ > 0
    return_if_false
    if or
        8@ == 1
        0@ == 2        
    return_if_false
end

:SideLook2   
0A8C: write_memory 0x527862 size 2 value 23@ virtual_protect 0   //CPad::GetLookLeft(void)
0A8C: write_memory 0x527894 size 2 value 23@ virtual_protect 0   //CPad::GetLookRight(void)
return


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:Spray
gosub @DisableVehFeatures

repeat
    gosub @DisableNitro
    0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 100.0 0.0 -40.0
    if
        00C2: is_point_on_screen 26@ 27@ 28@ radius 25.0
    then
        20@v = "DRIVEBY_R"
        31@ = 8
        break     
    else
        if
            08B7: is_local_var_bit_set_const 1@ bit 16  // CarWithoutWindows
        then
            if and
                30@ == 41
                18@ > 8 // Bicycles
                18@ < 12
            then    
                0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 0.0 100.0 -40.0
                if
                    00C2: is_point_on_screen 26@ 27@ 28@ radius 20.0
                then
                    20@v = "SPRAYCAN_FIRE"
                    08BD: set_local_var_bit_const 1@ bit 10
                    if
                        84EE: not has_animation_loaded "SPRAYCAN"
                    jf break
                    04ED: request_animation "SPRAYCAN"
                    jump @MyBloodyValentine
                end                    
            end
        end
        0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset -100.0 0.0 -40.0
        if
            00C2: is_point_on_screen 26@ 27@ 28@ radius 25.0
        then
            20@v = "DRIVEBY_L"
            31@ = 10
            break
        end
    end
    
    :MyBloodyValentine
    wait 0
    if and
		0256: is_player_playing $PLAYER_CHAR
		0449: is_char_sitting_in_any_car $PLAYER_ACTOR
		056E: does_vehicle_exist 16@		
        8EB7: not is_on_scripted_cutscene
    jf @FinishSpray2
    if
        8E8D: not is_any_fire_button_pressed 0
    jf continue
    if and
        0A4B: is_pc_using_joypad
        00E1: is_button_pressed pad 0 button 4@
    jf @FinishSpray2
until false

if
    88B7: not is_local_var_bit_set_const 1@ bit 16  // No CarWithoutWindows
then
    0D33: set_car_door_window_state 16@ door 31@ state 1
end

0E01: create_object_no_save 19@ at 26@ 27@ 28@ offset 0 ground 0 store_to 24@
04D9: set_object_records_collisions 24@ set_scripted_collision_check 0
0382: set_object_collision 24@ set_scripted_collision_check 0
0174: 31@ = get_car_heading 16@
0177: set_object_heading 24@ 31@

if
    20@v == "SPRAYCAN_FIRE"
then
    0605: task_play_anim $PLAYER_ACTOR perform_animation 20@v IFP "SPRAYCAN" framedelta 4.0 loopA 1 lockX 0 lockY 0 lockF 0 time -1
    070A: task_pick_up_object $PLAYER_ACTOR attach_to_object 24@ offset 0.0 0.0 0.04 on_bone 6 16 perform_animation 20@v IFP_file "SPRAYCAN" time -1
    26@ = 0.1
else
    0605: task_play_anim $PLAYER_ACTOR perform_animation 20@v IFP "PED" framedelta 4.0 loopA 0 lockX 0 lockY 0 lockF 1 time -1
    070A: task_pick_up_object $PLAYER_ACTOR attach_to_object 24@ offset 0.0 0.0 0.04 on_bone 6 16 perform_animation 20@v IFP_file "PED" time -1
    26@ = 0.9
end     

31@ = 0.0
TIMERA = 0
   
repeat
    wait 0            
    if and
        TIMERA < 4000
		0256: is_player_playing $PLAYER_CHAR
		0449: is_char_sitting_in_any_car $PLAYER_ACTOR
		0611: is_char_playing_anim $PLAYER_ACTOR performing 20@v
		056E: does_vehicle_exist 16@
		03CA: does_object_exist 24@		
        8EB7: not is_on_scripted_cutscene                        		
    jf @FinishSpray
    gosub @DisableNitro
    0613: get_char_anim_current_time 31@ = actor $PLAYER_ACTOR animation 20@v
until 0025: is_float_lvar_greater_than_float_lvar 31@ > 26@

if
    30@ == 37
then    
    0@ = 1.0
    if and
        0AAB: does_file_exist "cleo\WD Other.cs"    //Weapon Details Mod
        0AAB: does_file_exist "cleo\Flame.ini"
    then
        066E: create_fx_system_on_object_with_direction "FLAMETHROWER" attached_to_object 24@ with_offset 0@ -0.03 0.4 rotation 45.0 0.0 0.0 flag 1 store_to 20@
    else
        066E: create_fx_system_on_object_with_direction "FLAMETHROWER" attached_to_object 24@ with_offset 0@ -0.03 0.6 rotation 45.0 0.0 0.0 flag 1 store_to 20@
    end
else
    if
        30@ == 41
    then
        0@ = 0.16
        066E: create_fx_system_on_object_with_direction "SPRAYCAN" attached_to_object 24@ with_offset 0@ 0.01 0.02 rotation 45.0 0.0 0.0 flag 1 store_to 20@
    else
        0@ = 0.55
        066E: create_fx_system_on_object_with_direction "EXTINGUISHER" attached_to_object 24@ with_offset 0@ 0.12 0.18 rotation 45.0 0.0 0.0 flag 1 store_to 20@
    end                
end

064C: play_fx_system 20@         

0A96: 31@ = get_ped_pointer $PLAYER_ACTOR

29@ -= 1    //Slot
29@ *= 0x1C //CWeapon Size
005A: add_int_lvar_to_int_lvar 29@ += 31@
29@ += 0x5A0 //CWeapon

0A8E: int_add 19@ = 31@ + 0x394    //CAEPedWeaponAudioEntity
    
repeat
    0087: set_lvar_float_to_lvar_float 26@ = 0@
    26@ *= 1.2
    0208: generate_random_float_in_range 32@ = random_float_in_ranges -0.1 0.1
    0208: generate_random_float_in_range 33@ = random_float_in_ranges -0.1 0.1    
    0400: get_offset_from_object_in_world_coords 21@ 22@ 23@ from_object 24@ with_offset 26@ 32@ 33@
    0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 0@ 32@ 33@    
    0AC7: get_var_pointer 32@ = var 21@
    0AC7: get_var_pointer 33@ = var 26@
    
    0AA6: call_method 0x73E800 struct 29@ num_params 4 pop 0 32@ 0 33@ 31@ //char __thiscall CWeapon::FireAreaEffect(CEntity *firingEntity,CVector *origin, CEntity *targetEntity, CVector *target)
    0AA6: call_method 0x504F80 struct 19@ num_params 3 pop 0 145 31@ 30@ //void __thiscall CAEWeaponAudioEntity::WeaponFire(CAEPedWeaponAudioEntity *this,eWeaponType weaponType,CPhysical *entity,int audioEventId)

    gosub @SetAmmo
                    
    wait 0
       
    if or
		8256: not is_player_playing $PLAYER_CHAR
		8449: not is_char_sitting_in_any_car $PLAYER_ACTOR
		856E: not does_vehicle_exist 16@
		83CA: not does_object_exist 24@		
        0EB7: is_on_scripted_cutscene                		
	then
        0650: kill_fx_system 20@
        jump @FinishSpray
    end
    gosub @DisableNitro
    if
        9@ > 0
    jf break
    if
        8E8D: not is_any_fire_button_pressed 0
    jf continue
    if and
        0A4B: is_pc_using_joypad
        00E1: is_button_pressed pad 0 button 4@
    jf break
until false

0650: kill_fx_system 20@
if
    03CA: does_object_exist 24@
then
    0108: delete_object 24@
end

0687: clear_char_tasks $PLAYER_ACTOR

0781: get_weapontype_model 30@ model_to 19@
0E01: create_object_no_save 19@ at 0.0 0.0 0.0 offset 0 ground 0 store_to 24@
04D9: set_object_records_collisions 24@ set_scripted_collision_check 0
0382: set_object_collision 24@ set_scripted_collision_check 0
070A: task_pick_up_object $PLAYER_ACTOR attach_to_object 24@ offset 0.0 0.0 0.04 on_bone 6 16 perform_animation "NULL" IFP_file "NULL" time -1

TIMERA = 0

repeat
    wait 0
    gosub @DisableNitro
until TIMERA > 200

:FinishSpray
if
    03CA: does_object_exist 24@
then
    0108: delete_object 24@
end
0687: clear_char_tasks $PLAYER_ACTOR

:FinishSpray2
if
    08B7: is_local_var_bit_set_const 1@ bit 10
jf @FinishSpecialWeapons
08C3: clear_local_var_bit_const 1@ bit 10
04EF: remove_animation "SPRAYCAN"   
jump @FinishSpecialWeapons


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:ThrowExplosives
gosub @DisableVehFeatures

if and
    18@ >= 0
    08B7: is_local_var_bit_set_const 1@ bit 30  //PrepareThrowAnim
then
    0605: task_play_anim $PLAYER_ACTOR perform_animation "CAR_TUNE_RADIO" IFP "PED" framedelta 4.0 loop 0 lockX 0 lockY 0 lockF 0 time -1
end
TIMERA = 0
24@ = -1
22@ = 0.0

//Player "prepares" the throw and waits for releasing fire button
repeat
    gosub @DisableNitro
    
    if and
        18@ >= 0
        08B7: is_local_var_bit_set_const 1@ bit 30  //PrepareThrowAnim
    then
        if
            22@ < 0.7
        then
            0613: get_char_anim_current_time 22@ = actor $PLAYER_ACTOR animation "CAR_TUNE_RADIO"
            if and
                83CA: not does_object_exist 24@
                22@ >= 0.3
            then
                0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 0.0 0.0 -20.0
                0E01: create_object_no_save 19@ at 26@ 27@ 28@ offset 0 ground 0 store_to 24@
                04D9: set_object_records_collisions 24@ set_scripted_collision_check 0
                0382: set_object_collision 24@ set_scripted_collision_check 0
                070A: task_pick_up_object $PLAYER_ACTOR attach_to_object 24@ offset 0.0 0.0 0.0 on_bone 6 16 perform_animation "CAR_TUNE_RADIO" IFP_file "PED" time -1
            end     
            if
                22@ >= 0.7
            then
                0393: set_char_anim_speed $PLAYER_ACTOR "CAR_TUNE_RADIO" 0.0    //Freeze anim
            end
        end
    else
        if
            83CA: not does_object_exist 24@
        then
            0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 0.0 0.0 -20.0
            0E01: create_object_no_save 19@ at 26@ 27@ 28@ offset 0 ground 0 store_to 24@
            04D9: set_object_records_collisions 24@ set_scripted_collision_check 0
            0382: set_object_collision 24@ set_scripted_collision_check 0
            070A: task_pick_up_object $PLAYER_ACTOR attach_to_object 24@ offset 0.0 0.0 0.0 on_bone 6 16 perform_animation "NULL" IFP_file "NULL" time -1
        end
    end

    wait 0
    
    if and
		0256: is_player_playing $PLAYER_CHAR
		0449: is_char_sitting_in_any_car $PLAYER_ACTOR
		056E: does_vehicle_exist 16@
        8EB7: not is_on_scripted_cutscene                		
	jf @FinishThrow
    if
        8E8D: not is_any_fire_button_pressed 0
    jf continue
    if and
        0A4B: is_pc_using_joypad
        00E1: is_button_pressed pad 0 button 4@
    jf break
until false

0393: set_char_anim_speed $PLAYER_ACTOR "CAR_TUNE_RADIO" 1.0

//Getting throw direction
0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 0.0 100.0 -40.0
if
    00C2: is_point_on_screen 26@ 27@ 28@ radius 10.0
then
    0@ = 0.0    //Forward    
else
    0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset -100.0 0.0 -40.0
    if
        00C2: is_point_on_screen 26@ 27@ 28@ radius 10.0
    then
        0@ = -1.0   //Left
    else
        0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 100.0 0.0 -40.0
        if
            00C2: is_point_on_screen 26@ 27@ 28@ radius 10.0
        then
            0@ = 1.0    //Right    
        else
            if or
                30@ == 18
                88B7: not is_local_var_bit_set_const 1@ bit 15
            jf @Backward
            if
                08B7: is_local_var_bit_set_const 1@ bit 13
            then        
                0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 100.0 -85.0 -40.0
            else
                0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 100.0 -75.0 -40.0
            end
            if
                00C2: is_point_on_screen 26@ 27@ 28@ radius 10.0
            then
                0@ = 1.0    //Right    
            else
                :Backward
                0407: get_offset_from_car_in_world_coords 26@ 27@ 28@ from_car 16@ with_offset 0.0 -100.0 -40.0
                if
                    00C2: is_point_on_screen 26@ 27@ 28@ radius 10.0
                jf @FinishThrow
                0@ = -4.20      //Backward
            end    
        end
    end
end

if
    03CA: does_object_exist 24@
then
    0108: delete_object 24@
end

//Get min and max throw distances
0A90: int_mul 29@ = 30@ * 0x0C
0D4E: 20@ = read_struct_offset 14@ offset 29@ size 4
29@ += 0x08
0D4E: 22@ = read_struct_offset 14@ offset 29@ size 4
0EF4: clamp_float 20@ min 0.01 max 9.99 store_to 20@
0EF4: clamp_float 22@ min 0.01 max 9.99 store_to 22@
if
    20@ < 0.4
then
    if or
        0@ == 0.0
        0@ == -4.20
    then
        0087: set_lvar_float_to_lvar_float 21@ = 20@
        21@ *= -2.27
        21@ += 1.91
        006B: mult_float_lvar_by_float_lvar 20@ *= 21@
    end
end

0093: cset_lvar_float_to_lvar_int 29@ = TIMERA
29@ /= 714.3
0EF4: clamp_float 29@ min 20@ max 22@ store_to 29@

if
    0@ == 0.0
then
    02E3: get_car_speed 20@ car 16@
    if
        20@ > 1.0
    then
        0EFD: get_car_pedals 16@ gas_to 21@ break_to 22@    //Switch throw direction if car is moving in that direction
        if or
            20@ > 20.0
            21@ > 0.1
        then
            if or
                20@ > 30.0
                22@ < 0.9
            then
                0@ = -4.20
                20@ *= 0.008
                0EF4: clamp_float 20@ min 0.01 max 9.99 store_to 29@
                08BD: set_local_var_bit_const 1@ bit 11
            end
        end
    end
end

gosub @ThrowAnimName

if
    88B7: not is_local_var_bit_set_const 1@ bit 16  // No CarWithoutWindows
then
    if
        20@v == "DRIVEBY_R"
    then
        0D33: set_car_door_window_state 16@ door 8 state 1
    else
        0D33: set_car_door_window_state 16@ door 10 state 1
    end   
end 

0E01: create_object_no_save 19@ at 26@ 27@ 28@ offset 0 ground 0 store_to 24@
04D9: set_object_records_collisions 24@ set_scripted_collision_check 0
0382: set_object_collision 24@ set_scripted_collision_check 0
0605: task_play_anim $PLAYER_ACTOR perform_animation 20@v IFP "PED" framedelta 4.0 loopA 0 lockX 0 lockY 0 lockF 1 time -1
070A: task_pick_up_object $PLAYER_ACTOR attach_to_object 24@ offset 0.0 0.0 0.0 on_bone 6 16 perform_animation 20@v IFP_file "PED" time -1

TIMERA = 0
26@ = 0.0
27@ = 0.7
if
    0@ == 0.0
then
    27@ = 0.3
end

//Wait for anim progress    
repeat
    gosub @DisableNitro
    wait 0
    if and
        TIMERA < 4000
		0256: is_player_playing $PLAYER_CHAR
		0449: is_char_sitting_in_any_car $PLAYER_ACTOR
		0611: is_char_playing_anim $PLAYER_ACTOR performing 20@v
		056E: does_vehicle_exist 16@
		03CA: does_object_exist 24@
        8EB7: not is_on_scripted_cutscene                        		
	jf @FinishThrow     
    0613: get_char_anim_current_time 26@ = actor $PLAYER_ACTOR animation 20@v
until 0035: is_float_lvar_greater_or_equal_to_float_lvar 26@ >= 27@

gosub @DisableNitro
    
if
    30@ == 39   //Satchel            
then
    04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 13 store_weapon_to 26@ ammo_to 27@ model_to 32@
    if
        26@ <> 40   //Detonator
    then
        if
           8248: not has_model_loaded 364
        then
            0247: request_model 364
            038B: load_all_models_now
        end
        01B2: give_weapon_to_char $PLAYER_ACTOR 40 1
        0249: mark_model_as_no_longer_needed 364
    else
        if
            27@ < 1
        then
            017B: set_char_ammo $PLAYER_ACTOR 40 1
        end
    end
end

0174: 31@ = get_car_heading 16@
0177: set_object_heading 24@ 31@

if or
    18@ >= 0
    18@ == -14
jf @SideSpawn

if
    0@ == 0.0
then
    if and
        8137: not is_car_model 16@ <> 406   //Dumper
        08B7: is_local_var_bit_set_const 1@ bit 17  //Sitting in vehicle without windshield
    then
        27@ = 3
    else  
        0A97: get_vehicle_pointer 26@ = vehicle 16@
        26@ += 0x5A0          
        0AA8: call_method_return 0x6C2180 struct 26@ num_params 1 pop 0 4 27@   //Get windhsield damage state (0 = intact, 1 = broken, 3 = vanished)
    end
    if
        27@ > 1
    then
        08BD: set_local_var_bit_const 1@ bit 31
    end
end   

//Determining the spawning coords for the projectile. Molotovs need a special handling because they crack immediately when touching anything.    
if or
    30@ == 16   //Grenade
    30@ == 17   //Teargas
    30@ == 39   //Satchel
then    
    if or
        18@ < 3
        18@ > 12
    jf @SideSpawn
    if or
        0@ <> 0.0
        08B7: is_local_var_bit_set_const 1@ bit 31
    jf @SideSpawn
    if
        0@ == -4.20
    then
        if and
            08B7: is_local_var_bit_set_const 1@ bit 16
            8137: not is_car_model 16@ == 406
        jf @SideSpawn
        if
            18@ == 0
        then
            096D: get_current_car_mod 16@ component_on_slot 7 model_to 31@  //Roof
            if
                31@ < 1
            jf @SideSpawn
        end
    end
    if
        30@ <> 16
    then
        0A96: 31@ = get_ped_pointer $PLAYER_ACTOR
        0AC7: get_var_pointer 26@ = var 26@
        0AA6: call_method 0x5E4280 struct 31@ num_params 3 pop 0 bIncludeAnim 1 iBoneID 8 vPosition 26@ // CPed__getBonePosition
        if
            8EBE: not locate_camera_distance_to_coordinates 26@ 27@ 28@ radius 0.35 // First person cam
        jf @SideSpawn
    end
    0819: get_char_height_above_ground 31@ = actor $PLAYER_ACTOR
    0EF4: clamp_float 31@ min 0.0 max 4.0 store_to 31@
    31@ += 1.0
    31@ *= -1.0
    0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 0.0 0.0 31@   //Spawning underground because of collision problems. Will be moved next frame.
else
    :SideSpawn  //Basically Molotovs and for safety also added weapons
    08BD: set_local_var_bit_const 1@ bit 23 //Flag for spawning the projectile outside the car
                   
    if
        20@v == "DRIVEBY_R"
    then
        20@ = 0.1
    else
        20@ = -0.1
        if and
            0@ == 0.0
            18@ > 2
            18@ < 13
        then
            20@ = 0.1
        end
    end
    31@ = 0.0
    32@ = 0
    33@ = 0.2
    
    repeat
        005B: add_float_lvar_to_float_lvar 31@ += 20@
        if and
            31@ < 5.0
            31@ > -5.0
        jf break
        0400: get_offset_from_object_in_world_coords 21@ 22@ 23@ from_object 24@ with_offset 31@ -2.0 33@
        0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 31@ 1.0 33@
        if
            06BD: is_line_of_sight_clear 26@ 27@ 28@ 21@ 22@ 23@ buildings 0 cars 1 chars 0 objects 0 particles 0     //Finding safe spawn coords sideways
        then
            0400: get_offset_from_object_in_world_coords 21@ 22@ 23@ from_object 24@ with_offset 31@ -0.1 -0.2
            0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 31@ -0.1 0.6
            if
                06BD: is_line_of_sight_clear 26@ 27@ 28@ 21@ 22@ 23@ buildings 0 cars 1 chars 0 objects 0 particles 0
            then
                if
                    32@ < 3
                jf break
                32@ += 1
                if
                    32@ == 1
                jf continue
                if
                    0@ <> 0.0
                then
                    32@ = 2
                    continue
                end
                
                repeat
                    0400: get_offset_from_object_in_world_coords 21@ 22@ 23@ from_object 24@ with_offset 31@ 1.2 33@
                    0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 0.6 1.2 33@
                    33@ += 0.1
                    if
                        33@ < 0.6
                    jf break
                until 06BD: is_line_of_sight_clear 26@ 27@ 28@ 21@ 22@ 23@ buildings 0 cars 1 chars 0 objects 0 particles 0 //Finding appropriate Z when throwing forward
                
                if
                    08B7: is_local_var_bit_set_const 1@ bit 31
                then
                    0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 0.1 0.8 33@
                    jump @SpawnProjectile
                end                                    
                0063: sub_float_lvar_from_float_lvar 31@ -= 20@
                continue
            end
        end
        if
            32@ > 0
        jf continue
        32@ = 1
    until false
    
    0063: sub_float_lvar_from_float_lvar 31@ -= 20@   
    06A3: get_car_mass 16@ mass_to 21@    
    if or
        21@ > 3000.0
        08B7: is_local_var_bit_set_const 1@ bit 13  //Big Vehicles
    then
        20@ *= 2.2           
        if
            21@ > 5000.0
        then
            20@ *= 1.2
            if
                21@ > 7000.0
            then
                20@ *= 2.0
            end
        end
    else
        if
            30@ == 39
        then
            if
                00E1: is_button_pressed pad 0 button 0
            then
                20@ *= 6.0
            else               
                20@ *= 2.0
            end
        else 
            20@ *= 1.6
        end
        if and
            31@ < 0.0
            31@ > -0.5
        then
            31@ = -0.5
        end
    end
    005B: add_float_lvar_to_float_lvar 31@ += 20@   //Apply a little more offset
    0400: get_offset_from_object_in_world_coords 26@ 27@ 28@ from_object 24@ with_offset 31@ -0.1 33@  //Final spawn position
end

:SpawnProjectile
0A96: 31@ = get_ped_pointer $PLAYER_ACTOR
0AA5: call_function 0x737C80 num_params 8 pop 8 0 0.0 0.5 28@ 27@ 26@ 30@ 31@ //CProjectileInfo::AddProjectile(CEntity *creator,eWeaponType WeponType,float srcx,float srcy,float srcz,float force,CVector *dest,CEntity *victim)

gosub @SetAmmo
if and
    9@ < 1
    30@ == 39
then
    30@ = 40
    gosub @SetWeaponSlot
end

30@ = 0
0AC7: get_var_pointer 31@ = var 26@
0AA7: call_function_return 0x5693F0 num_params 9 pop 9 0 1 0 0 0 0 5.0 31@ 19@ 30@

if
    30@ <> 0
jf @FinishThrow

0AEC: get_object_ref 20@ = object_struct 30@ 
050E: sort_out_object_collision_with_car 20@ no_collision_with_car 16@  //Praise the lord that this command exists
           
if
    88B7: not is_local_var_bit_set_const 1@ bit 23
then
    if
        0@ == 0.0
    then
        0400: get_offset_from_object_in_world_coords 21@ 22@ 23@ from_object 24@ with_offset 0.05 0.05 0.2
    else
        0400: get_offset_from_object_in_world_coords 21@ 22@ 23@ from_object 24@ with_offset 0.05 0.05 0.02
    end
    01BC: set_object_coordinates 20@ 21@ 22@ 23@    //Final and visible "spawn" coords           
end

if or
    00E1: is_button_pressed pad 0 button 5
    00E1: is_button_pressed pad 0 button 7
then
    if or
        3@ < 3
        8A4B: not is_pc_using_joypad
    then                    
        0174: 21@ = get_car_heading 16@
        if and
            00E1: is_button_pressed pad 0 button 5
            00E1: is_button_pressed pad 0 button 7
        then
            21@ -= 180.0
            jump @BennyBenassi
        end
        if
            00E1: is_button_pressed pad 0 button 5
        then   
            21@ += 90.0
            jump @BennyBenassi
        end
        21@ -= 90.0
        jump @BennyBenassi
    end
end

if
    08B7: is_local_var_bit_set_const 1@ bit 11
then
    00AA: get_car_coordinates 16@ 32@ 33@ 21@
    0407: get_offset_from_car_in_world_coords 22@ 23@ 21@ from_car 16@ with_offset 0.0 1.0 0.0
else
    // Create camera vector
    068D: get_active_camera_coordinates 32@ 33@ 21@
    0EB2: get_offset_from_camera_in_world_coords 0.0 1.0 0.0 store_to 22@ 23@ 21@
end
        
0063: sub_float_lvar_from_float_lvar 22@ -= 32@
0063: sub_float_lvar_from_float_lvar 23@ -= 33@
                    
// Get angle
05A4: get_angle_between_2d_vectors 22@ 23@ 0.0 1.0 store_to 21@
if
    22@ < 0.0
then
    :BennyBenassi
    21@ *= -1.0
end
                                      
02F6: sin 22@ = sine 21@
02F7: cos 23@ = cosine 21@                 

006B: mult_float_lvar_by_float_lvar 22@ *= 29@
006B: mult_float_lvar_by_float_lvar 23@ *= 29@

if or
    0@ == 1.0
    0@ == -1.0
then
    02E3: get_car_speed 31@ car 16@
    31@ *= 0.02
    0EF4: clamp_float 31@ min 0.0 max 4.0 store_to 31@
    0EFD: get_car_pedals 16@ gas_to 21@ break_to 32@
    if
        21@ < -0.2
    then
        31@ *= -1.0
    end
    0D4E: 32@ = read_struct_offset 30@ offset 0x44 size 4   //get x speed
    0D4E: 33@ = read_struct_offset 30@ offset 0x48 size 4   //get y speed                                              
    006B: mult_float_lvar_by_float_lvar 32@ *= 31@
    006B: mult_float_lvar_by_float_lvar 33@ *= 31@                
    005B: add_float_lvar_to_float_lvar 22@ += 32@
    005B: add_float_lvar_to_float_lvar 23@ += 33@
end   
                               
0E28: write_struct_offset 30@ offset 0x44 size 4 value 22@ //set x speed                
0E28: write_struct_offset 30@ offset 0x48 size 4 value 23@ //set y speed
0E28: write_struct_offset 30@ offset 0x4C size 4 value 0.08 //set z speed

gosub @ThrowAnimName

TIMERA = 0
26@ = 0.0
27@ = 1.0
if
    0@ == 0.0
then
    if or
        18@ == 12   // Quadbike
        047A: is_char_on_any_bike $PLAYER_ACTOR
        88B7: not is_local_var_bit_set_const 1@ bit 23
    then
        27@ = 0.6
    end
end

//Wait for finishing throw anim
repeat
    if and
        TIMERA < 4000
		0256: is_player_playing $PLAYER_CHAR
		0449: is_char_sitting_in_any_car $PLAYER_ACTOR
		0611: is_char_playing_anim $PLAYER_ACTOR performing 20@v
		056E: does_vehicle_exist 16@
        8EB7: not is_on_scripted_cutscene                		
	jf break
    if
        03CA: does_object_exist 24@
    then
        0750: set_object_visible 24@ visibility 0
    end
	gosub @DisableNitro
	0613: get_char_anim_current_time 26@ = actor $PLAYER_ACTOR animation 20@v
    wait 0
until 0035: is_float_lvar_greater_or_equal_to_float_lvar 26@ >= 27@

:FinishThrow
if
    03CA: does_object_exist 24@
then
    0108: delete_object 24@
end
0687: clear_char_tasks $PLAYER_ACTOR
08C3: clear_local_var_bit_const 1@ bit 11
08C3: clear_local_var_bit_const 1@ bit 23
08C3: clear_local_var_bit_const 1@ bit 31
wait 0
wait 0

:FinishSpecialWeapons
if
    08B7: is_local_var_bit_set_const 1@ bit 9
then
    08C3: clear_local_var_bit_const 1@ bit 9
    0EAC: get_char_proofs $PLAYER_ACTOR bullet 21@ fire 22@ explosion 23@ collision 26@ melee 27@            
    02AB: set_char_proofs $PLAYER_ACTOR bullet 21@ fire 0 explosion 23@ collision 26@ melee 27@             
    if
        056E: does_vehicle_exist 16@
    then
        0EAD: get_car_proofs 16@ bullet 21@ fire 22@ explosion 23@ collision 26@ melee 27@            
        02AC: set_car_proofs 16@ bullet 21@ fire 0 explosion 23@ collision 26@ melee 27@
    end
end
07CC: set_player_enter_car_button $PLAYER_CHAR can_enter_exit_vehicles 1
24@ = 0
TIMERB = 1051

while true
    if or
        3@ < 3
        8A4B: not is_pc_using_joypad
    jf break
    if or
        00E1: is_button_pressed pad 0 button 5
        00E1: is_button_pressed pad 0 button 7
    jf break
    if and
        056E: does_vehicle_exist 16@
        0256: is_player_playing $PLAYER_CHAR
    jf break
    if and
        09E7: is_player_control_on $PLAYER_CHAR
        0449: is_char_sitting_in_any_car $PLAYER_ACTOR
    jf break
    if
        0E8D: is_any_fire_button_pressed 0
    then
        0@ = 4
        gosub @GetWeaponSlot
        04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 9@ model_to 19@
        jump @SpecialWeapons
    end
    wait 0        
end
     
gosub @DisableSideLook
jump @ReenableVehFeatures


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:ThrowAnimName
if
    0@ > 0.0
then
    20@v = "DRIVEBY_R"
    return
end
20@v = "DRIVEBY_L"
if and
    0@ == -4.20
    08B7: is_local_var_bit_set_const 1@ bit 16  //CarsWithoutWindows
return_if_false
if and
    18@ > 2     // Bikes
    18@ < 13
then
    20@v = "DRIVEBY_R"
    return
end
if or
    30@ == 16
    30@ == 17
    30@ == 39
    30@ == 40
return_if_false
20@v = "DRIVEBY_R"
return


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:StartDriveBy
06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 0
gosub @SetWeaponSlot

gosub @DisableAndPatchStuff
gosub @DisableMenu
23@ = 0x9090 
gosub @ChangeSideLook

0A8D: 31@ = read_memory 0x527830 size 2 virtual_protect 0
if
    31@ == 0x1F74
then
    0A8C: write_memory 0x527830 size 1 value 0xEB virtual_protect 0   //Disable Look Behind  
    0E28: write_struct_offset 14@ offset LookBehind size 1 value 1
end

0A8D: 31@ = read_memory 0x522423 size 2 virtual_protect 0
if
    31@ == 0x6674
then                           
    0A8C: write_memory 0x522423 size 2 value 0x9090 virtual_protect 0  //disbales camera messing up during driveby
    0E28: write_struct_offset 14@ offset CamStuff size 1 value 1
end
       		
0A39: get_player_in_car_camera_mode 20@
0EF7: clamp_int 20@ min 1 max 3 store_to 19@
0A8E: int_add 29@ = 19@ + -1
29@ *= 0x04

0801: get_camera_fov 24@
if
    24@ <> 100.0
then
    0A96: 31@ = get_ped_pointer $PLAYER_ACTOR
    0AC7: get_var_pointer 26@ = var 26@
    0AA6: call_method 0x5E4280 struct 31@ num_params 3 pop 0 bIncludeAnim 1 iBoneID 8 vPosition 26@ // CPed__getBonePosition
    if
        0EBE: locate_camera_distance_to_coordinates 26@ 27@ 28@ radius 0.35 // First person cam 
    then
        24@ = 100.0
    else            			    
        0A8D: 26@ = read_memory 0x52161A size 1 virtual_protect 0
        0A8D: 27@ = read_memory 0x52161B size 4 virtual_protect 0                                                                				
        if and
            26@ == 0x0F
            27@ == 0x071887BE 
        then
            0A8C: write_memory 0x52161A size 1 value 0xE9 virtual_protect 0          //Custom Camera Zoom
    	    0A8C: write_memory 0x52161B size 4 value 0x000000B3 virtual_protect 0
        end       
        gosub @TweakFOV        
    end
end

if and
    18@ > 2     // Bikes
    18@ < 13
then
    if and
        18@ > 8 // Bicycles
        18@ < 12
    then
        gosub @DisableBunnyhop
    else
        if
            08B7: is_local_var_bit_set_const 1@ bit 0   //DisableBikeWeakPoint
        then
            09C4: set_petrol_tank_weakpoint 16@ 0
        end
    end
    
    06A3: get_car_mass 16@ mass_to 0@   //used for falling off bike fix
    0@ /= 5.0
    
    29@ += DistNearB
else
    if
        88B7: not is_local_var_bit_set_const 1@ bit 16  // No CarWithoutWindows
    then
        0D33: set_car_door_window_state 16@ door 10 state 1
        0D33: set_car_door_window_state 16@ door 8 state 1
    end
      
    if
        18@ < 0
    then
        gosub @DisableVehWeapon    
        0D4E: 31@ = read_struct_offset 14@ offset SpVehAdr size 4
        0A8C: write_memory 31@ size 1 value 128 virtual_protect 0
        if
            18@ > -14
        jf @EnableForbVehON 
    else
        gosub @DisableHydraulics   
        if and
            18@ > 13
            18@ < 19
        then
            :EnableForbVehON
            0A97: 31@ = get_vehicle_pointer 16@
            0D4E: 23@ = read_struct_offset 31@ offset 0x384 size 4  //m_pHandlingData
            0E28: write_struct_offset 23@ offset 0xDE size 1 value 0    //AnimGroup
        end
    end
          
    29@ += DistNearC   
end

0D4E: 22@ = read_struct_offset 14@ offset DistAdr size 4

23@ = AngleDownVal
if        
    88B7: not is_local_var_bit_set_const 1@ bit 29  // NoAngleLimit
then
    23@ = HeightVal
end

for 30@ = DistVal to 23@ step 0x04
    0A8D: 21@ = read_memory 22@ size 4 virtual_protect 0
    0E28: write_struct_offset 14@ offset 30@ size 4 value 21@
    if 
        30@ > HeightVal
    then
        if or
            24@ <> 100.0
            22@ < 0x8CC4F8
        then    
            0A8C: write_memory 22@ size 4 value 1.49 virtual_protect 0
        end
    else 
        0D4E: 21@ = read_struct_offset 14@ offset 29@ size 4
        if
            18@ < 0
        then
            if or
                18@ == -4
                18@ == -15
            then
                21@ *= 2.0
            else
                21@ *= 1.5
            end
        end
        0A8C: write_memory 22@ size 4 value 21@ virtual_protect 0
        if
            30@ == DistVal
        then
            29@ += 0x0C
            22@ += 0x0C
        end
    end
    22@ += 0x04
end

0713: task_drive_by $PLAYER_ACTOR driveby_actor -1 car -1 point 0.0 0.0 0.0 radius 600.0 4 0 firing_rate 100

if or
    20@ < 1
    20@ > 3
then
    0174: 31@ = get_car_heading 16@
    31@ -= 90.0
    0858: set_heading_for_attached_player $PLAYER_CHAR scan_horizon_to_angle 31@ rotation_speed 360.0
end

gosub @BulletModFix

TIMERA = -300
TIMERB = -300
20@ = 0

gosub @EQ_BugFix
                                                                                                                       	        			
while true
    gosub @DisableNitro
            
    if
        88B7: not is_local_var_bit_set_const 1@ bit 5   //not Camera weapon active
    then
        if
            08B7: is_local_var_bit_set_const 1@ bit 25  //DrivebyControlType = 2 or AimButton = Secondary fire button
        then   
            if
                00E1: is_button_pressed pad 0 button 17     //Circle
            then
                0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 1
            else
                0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 0
            end
        end
    else
        0A2F: set_photo_camera_effect 1
        0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 0
        if or
            0E3E: is_button_just_pressed pad 0 button 4
            0E3E: is_button_just_pressed pad 0 button 17
        then
            if
                TIMERB >= 0
            then
                0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 1
                0EB2: get_offset_from_camera_in_world_coords 0.0 4.0 0.0 store_to 21@ 22@ 23@
                0E01: create_object_no_save 367 at 21@ 22@ 23@ offset 0 ground 0 store_to 31@
                04D9: set_object_records_collisions 31@ set_scripted_collision_check 0
                0382: set_object_collision 31@ set_scripted_collision_check 0
                0750: set_object_visible 31@ 0
                097B: report_mission_audio_event_at_object 31@ event 1132
                03E6: clear_help
                0A1E: take_photo 1
                0AA5: call_function 0x456A70 num_params 0 pop 0
                0470: 30@ = get_current_char_weapon $PLAYER_ACTOR
                gosub @SetAmmo
                TIMERA = 0
                    
                repeat
                    wait 0                  
                    0A2F: set_photo_camera_effect 1
                    0A8C: write_memory CIRCLE size 2 value 0x00 virtual_protect 0
                    0A8C: write_memory LEFTSHOULDER1 size 2 value 0x00 virtual_protect 0
                    0EB2: get_offset_from_camera_in_world_coords 0.0 4.0 0.0 store_to 21@ 22@ 23@
                    if
                        03CA: does_object_exist 31@
                    then
                        01BC: set_object_coordinates 31@ 21@ 22@ 23@
                    end
                    gosub @EQ_BugFix
                until TIMERA > 200
                
                0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 0
                wait 0                                
                if
                    03CA: does_object_exist 31@
                then
                    0108: delete_object 31@
                end
                if
                    9@ > 0  // Out of ammo
                jf break
                gosub @EQ_BugFix
                gosub @DisableNitro
            end
        end
    end
           
    wait 0
        
    if and
		0256: is_player_playing $PLAYER_CHAR
		056E: does_vehicle_exist 16@
		00DF: is_char_in_any_car $PLAYER_ACTOR
        8EB7: not is_on_scripted_cutscene              		
    jf @CancelDriveby    
    if or
        0E42: is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
        08B7: is_local_var_bit_set_const 1@ bit 28
    jf @CancelDriveby
    
    if
        00E1: is_button_pressed pad 0 button 15     //exit
    then
        0@ = 17.0
        if and
            18@ > 2   // Bikes
            18@ < 13
        then
            0@ = 14.0
        end
        02E3: get_car_speed 31@ car 16@
        if
            0025: is_float_lvar_greater_than_float_lvar 31@ > 0@
        then
            02EB: restore_camera_jumpcut
        end
        jump @CancelDriveBy
    end
        
    if and
        18@ > 2   // Bikes
        18@ < 13
    then
        083F: get_car_upright_value 16@ vertical_deviation_to 23@
        0E65: get_car_collision_intensity 16@ store_to 31@  //falling off bike fix
        if and
            23@ > 0.6
            8025: not is_float_lvar_greater_than_float_lvar 31@ > 0@
        jf @CancelDriveBy
        if and
            18@ > 8 // Bicycles
            18@ < 12
            88B7: not is_local_var_bit_set_const 1@ bit 25
            88B7: not is_local_var_bit_set_const 1@ bit 5
        then
            if or
                8A4B: not is_pc_using_joypad
                3@ == 3
                3@ == 4
            then
                if
                    00E1: is_button_pressed pad 0 button 4  //Bunnyhop
                then
                    if
                        88B7: not is_local_var_bit_set_const 1@ bit 28
                    then
                        0687: clear_char_tasks $PLAYER_ACTOR
                        02EB: restore_camera_jumpcut
                        gosub @ReenableBunnyhop
                        08BD: set_local_var_bit_const 1@ bit 28
                    end
                    0A8C: write_memory CIRCLE size 2 value 0x00 virtual_protect 0
                    TIMERB = 0
                else
                    if
                        08B7: is_local_var_bit_set_const 1@ bit 28
                    then
                        if and
                            TIMERB > 200
                            8E93: not is_car_really_in_air 16@
                        then
                            gosub @DisableBunnyhop
                            0713: task_drive_by $PLAYER_ACTOR driveby_actor -1 car -1 point 0.0 0.0 0.0 radius 600.0 4 0 firing_rate 100
                            08C3: clear_local_var_bit_const 1@ bit 28
                        end
                    end    
                end
            end
        end            
    else
        if and
            18@ <> -5   //Boats
            18@ <> 18   //Kart
        then
            068D: get_active_camera_coordinates 21@ 22@ 23@
            0AC7: get_var_pointer 26@ = var 26@
            0AC7: get_var_pointer 29@ = var 29@
            0AA6: call_method {CCamera::Find3rdPersonCamTargetVector} 0x514970 struct 0xB6F028 num_params 6 pop 0 _targetOut 26@ _cameraOut 29@ _z 23@ _y 22@ _x 21@ _range 8.0
                    
            if and
                24@ <> 100.0
                08B7: is_local_var_bit_set_const 1@ bit 2   //FreeLineOfSight
                001D: is_int_lvar_greater_than_int_lvar TIMERB > 20@
            then                            
                04C4: get_offset_from_char_in_world_coords 28@ 29@ 30@ from_actor $PLAYER_ACTOR with_offset 0.0 0.0 4.0
                050A: get_distance_between_coords_3d 0@ = distance_between_XYZ 21@ 22@ 23@ and_XYZ 28@ 29@ 30@
                
                31@ = 5.2            
                if
                    88B7: not is_local_var_bit_set_const 1@ bit 15  // No flat vehicle
                then
                    // Create camera vector
                    0063: sub_float_lvar_from_float_lvar 26@ -= 21@
                    0063: sub_float_lvar_from_float_lvar 27@ -= 22@
                    
                    // Create car vector
                    0407: get_offset_from_car_in_world_coords 30@ 31@ 20@ 16@ 3.6 -8.0 4.0
                    0063: sub_float_lvar_from_float_lvar 28@ -= 30@
                    0063: sub_float_lvar_from_float_lvar 29@ -= 31@
                                
                    // Angle for look behind check
                    05A4: get_angle_between_2d_vectors 26@ 27@ 28@ 29@ store_to 31@
                    
                    // Schrdinger equation
                    0087: set_lvar_float_to_lvar_float 29@ = 0@
                    29@ *= -0.0001
                    29@ += 0.0027
                    if
                        29@ < 0.0001
                    then
                        29@ = 0.0001
                    end
                    
                    0087: set_lvar_float_to_lvar_float 30@ = 31@
                    006B: mult_float_lvar_by_float_lvar 30@ *= 29@
                    30@ += 1.0
                    
                    006B: mult_float_lvar_by_float_lvar 30@ *= 30@
                    006B: mult_float_lvar_by_float_lvar 0@ *= 30@
                                        
                    29@ *= 10.0
                    31@ *= 0.05
                    006B: mult_float_lvar_by_float_lvar 31@ *= 31@ 
                    006B: mult_float_lvar_by_float_lvar 31@ *= 29@
                end
                
                0092: cset_lvar_int_to_lvar_float 20@ = 0@
                20@ *= 10
                0EF7: clamp_int 20@ min 50 max 300 store_to 20@
                
                if
                    18@ < 0
                then
                    0EF4: clamp_float 0@ min 14.0 max 80.0 store_to 0@
                else
                    0EF4: clamp_float 0@ min 2.0 max 80.0 store_to 0@
                    0087: set_lvar_float_to_lvar_float 29@ = 23@
                    29@ -= 10.0
                    if
                        80C2: not is_point_on_screen 21@ 22@ 29@ radius 31@ // Keep car visible when targeting the ground
                    jf @VisibilityReset
                end
                
                // Find crosshair target coords
                0AC7: get_var_pointer 28@ = var 21@
                0AC7: get_var_pointer 29@ = var 29@
                0AA6: call_method 0x514970 struct 0xB6F028 num_params 6 pop 0 _targetOut 29@ _cameraOut 28@ _z 23@ _y 22@ _x 21@ _range 0@ {CCamera::Find3rdPersonCamTargetVector}
                
                if
                    86BD: not is_line_of_sight_clear 21@ 22@ 23@ 29@ 30@ 31@ buildings 0 cars 1 chars 0 objects 0 particles 0
                then
                    if
                        88B7: not is_local_var_bit_set_const 1@ bit 14
                    then
                        20@ *= 2
                        if
                            001D: is_int_lvar_greater_than_int_lvar TIMERB > 20@
                        then
                            0338: set_car_visible 16@ 0
                            08BD: set_local_var_bit_const 1@ bit 14
                        end
                        TIMERB = 0
                    end
                else
                    :VisibilityReset
                    if
                        08B7: is_local_var_bit_set_const 1@ bit 14
                    then
                        20@ *= 2
                        if
                            001D: is_int_lvar_greater_than_int_lvar TIMERB > 20@
                        then
                            20@ /= 2
                            TIMERB = 0
                        else                    
                            gosub @SetCarVisible
                        end
                    else
                        0085: set_lvar_int_to_lvar_int TIMERB = 20@
                    end
                end
            end                       
        
            :CheckWindshield   
            if and
                02E0: is_char_shooting $PLAYER_ACTOR
                88B7: not is_local_var_bit_set_const 1@ bit 17 // NoWindshield flag
            then
                0A97: get_vehicle_pointer 29@ = vehicle 16@
                29@ += 0x5A0
                30@ = -1
                0AA8: call_method_return 0x6C2180 struct 29@ num_params 1 pop 0 4 30@
                if or
                    30@ == 0
                    30@ == 1
                then
                    // Create camera vector
                    0063: sub_float_lvar_from_float_lvar 26@ -= 21@
                    0063: sub_float_lvar_from_float_lvar 27@ -= 22@
                    
                    // Create car vector
                    if
                        08B7: is_local_var_bit_set_const 1@ bit 18
                    then
                        if
                            24@ == 100.0
                        then
                            0407: get_offset_from_car_in_world_coords 0@ 31@ 23@ 16@ -8.2 -8.0 0.0
                        else
                            0407: get_offset_from_car_in_world_coords 0@ 31@ 23@ 16@ -7.2 -8.0 0.0
                        end
                    else
                        if
                            24@ == 100.0
                        then
                            0407: get_offset_from_car_in_world_coords 0@ 31@ 23@ 16@ -3.2 -8.0 0.0
                        else
                            0407: get_offset_from_car_in_world_coords 0@ 31@ 23@ 16@ -2.2 -8.0 0.0
                        end
                    end                                                                                                          
                    00AA: get_car_coordinates 16@ 28@ 29@ 23@
                    0063: sub_float_lvar_from_float_lvar 28@ -= 0@
                    0063: sub_float_lvar_from_float_lvar 29@ -= 31@
                    
                    // Angle for look forward check
                    05A4: get_angle_between_2d_vectors 26@ 27@ 28@ 29@ store_to 31@
                    
                    if
                        31@ > 14.0
                    jf @BreakWindshield
                    if and
                        31@ < 38.0
                        88B7: not is_local_var_bit_set_const 1@ bit 18
                    then
                        :BreakWindshield       
                        if
                            30@ == 0
                        then
                            0730: damage_car_panel 16@ damage_component 4
                        else
                            0A97: get_vehicle_pointer 29@ = vehicle 16@
                            0AA5: call_function 0x71C2B0 num_params 1 pop 1 29@ 
                            0697: pop_car_panel 16@ remove_component 4 visible_effect_flag 0
                        end
                    end
                end
            end
        end
    end
    
    if
        0E3E: is_button_just_pressed pad 0 button 13    //change view
    then
        if
            24@ == 100.0    //not in first person view
        then
            24@ = -2    //flag for "change view from first person view"
            break
        end
        
        19@ -= 1
        if
            19@ < 1
        then
            19@ = 3
        end
        09AD: set_player_in_car_camera_mode 19@
        0A8E: int_add 29@ = 19@ + -1
        29@ *= 0x04
        
        0087: set_lvar_float_to_lvar_float 30@ = 24@
        0801: get_camera_fov 24@
        gosub @TweakFOV
        0087: set_lvar_float_to_lvar_float 24@ = 30@
        
        0D4E: 22@ = read_struct_offset 14@ offset DistAdr size 4
        if
            22@ == 0x8CC4DC
        then
            29@ += DistNearB
        else    
            29@ += DistNearC
        end
        
        0A8E: int_add 30@ = 29@ + 0x0C
        
        for 31@ = 29@ to 30@ step 0x0C
            0D4E: 21@ = read_struct_offset 14@ offset 31@ size 4
            if
                18@ < 0
            then
                if or
                    18@ == -4
                    18@ == -15
                then
                    21@ *= 2.0
                else
                    21@ *= 1.5
                end
            end
            0A8C: write_memory 22@ size 4 value 21@ virtual_protect 0
            22@ += 0x10
        end
               
        0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 32 //CAudioEngine::ReportFrontendAudioEvent (Bing sound)
    end
    
    if
        08B7: is_local_var_bit_set_const 1@ bit 5
    then
        31@ = 2
    else    
        gosub @PatchDrivebyTask   
        if
            31@ > 2
        then
            wait 120
            if or
            	8256: not is_player_playing $PLAYER_CHAR
            	856E: not does_vehicle_exist 16@
            	80DF: not is_char_in_any_car $PLAYER_ACTOR
                0EB7: is_on_scripted_cutscene              		
            then
                :CancelDriveBy
                0687: clear_char_tasks $PLAYER_ACTOR
                TIMERB = 1051
                jump @FinishDriveBy
            end
            0AA6: call_method 0x506EA0 struct 0xB6BC90 num_params 3 pop 0 1.0 0.0 41 //CAudioEngine::ReportFrontendAudioEvent (Click Sound)
            break
        end
    end
       
    if
        0A4B: is_pc_using_joypad
    then
        if
            3@ == 1
        then
            if
                80E1: not is_button_pressed pad 0 button 17 //Circle
            jf break
            if and
                TIMERB >= 0
                00E1: is_button_pressed pad 0 button 4
            then
                0A8C: write_memory CIRCLE size 2 value 0xFF virtual_protect 0   //emulates pressed fire button
            end
            0A8C: write_memory LEFTSHOULDER1 size 2 value 0x00 virtual_protect 0                    
        else
            if
                80E1: not is_button_pressed pad 0 button 4@ //aim button
            then
                if
                    12@ > 0
                jf break
                if or
                    12@ == 1
                    24@ == 100.0
                jf break
            else
                if
                    12@ > 0
                then
                    if or
                        12@ == 1
                        24@ == 100.0
                    then
                        if
                            8E3E: not is_button_just_pressed pad 0 button 4@
                        jf break
                    end
                end
            end
            if
                3@ > 2
            then
                if
                    00E1: is_button_pressed pad 0 button 5@ //shoot button
                then
                    if or
                        3@ > 4
                        8E8D: not is_any_fire_button_pressed 0
                    then
                        0A8C: write_memory CIRCLE size 2 value 0xFF virtual_protect 0   //emulates pressed fire button
                    end
                end
            end
        end
        if
            31@ == 2        
        gosub_if_false @WeapSwitchPad
        gosub @MaybeCarMovementFix
        continue
    end
    if and
        12@ <> 1
        8AB0: not is_key_pressed 2@ //aim button
    then
        if and
            12@ == 2
            24@ == 100.0
        jf break                        
    else
        if
            8E3D: not is_key_just_pressed 2@
        jf break
    end                                                                                                                                        
    if
        31@ == 2        
    gosub_if_false @WeapSwitchMouse
    gosub @CarMovementFix
end

TIMERB = 1051                                                                             					    				    			
0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 0
07CC: set_player_enter_car_button $PLAYER_CHAR can_enter_exit_vehicles 0
gosub @SetCarVisible                

0087: set_lvar_float_to_lvar_float 31@ = 25@
25@ = 1.0    //reset shoot rate
gosub @ShootRateFix
0087: set_lvar_float_to_lvar_float 25@ = 31@

0D4E: 26@ = read_struct_offset 14@ offset JumpCutRe size 2
              
23@ = 0.0                       
if
    24@ <> -2   //not while changing from first person view
jf @FadeIn             			        			        				    				        			                                                          
if
    24@ == 100.0    //first person view
then
    if
        88B7: not is_local_var_bit_set_const 1@ bit 20
    jf @FadeIn
else
    0801: get_camera_fov 23@
    if
        0045: is_float_lvar_equal_to_float_lvar 23@ == 24@
    then
        23@ = 0.0
    end 
    0D4E: 27@ = read_struct_offset 14@ offset JumpCutCarSpe size 4
    02E3: get_car_speed 31@ car 16@
    if and
        26@ > 0 //jumpcut restore enabled
        8025: not is_float_lvar_greater_than_float_lvar 27@ > 31@
    then
        08BD: set_local_var_bit_const 1@ bit 6  //flag for camera restore jumpcut                                                                           
        if
            26@ <> 1    
        then
            :FadeIn
            043C: set_music_does_fade 0
            016A: do_fade 0 0
            gosub @EQ_BugFix
            gosub @DisableNitro
            wait 0
        end
    end
    if
        23@ > 0.0
    then
        if or
            24@ < 10.0
            24@ > 100.0
        then
            0922: camera_set_lerp_fov 70.0 to 70.0 timelimit 100 smooth_transition 0
        else
            0087: set_lvar_float_to_lvar_float 31@ = 24@
            31@ -= 70.0
            if and
                31@ > -5.0
                31@ < 5.0
            then
                24@ = 70.0
            end 
            if
                08B7: is_local_var_bit_set_const 1@ bit 6   //camera restore jumpcut
            then 
                0922: camera_set_lerp_fov 24@ to 24@ timelimit 100 smooth_transition 0  //reset FOV immediately                           
            else
                0@ = 0
                0A8D: 31@ = read_memory 0x58E020 size 2 virtual_protect 0
                if
                    31@ == 0xEC83
                then
                    0A8C: write_memory 0x58E020 size 1 value 0xC3 virtual_protect 0  //disable crosshair
                    0@ = 1
                end
                0922: camera_set_lerp_fov 23@ to 24@ timelimit 200 smooth_transition 0  //reset FOV gently
                TIMERA = 0
                
                repeat
                    gosub @EQ_BugFix
                    gosub @DisableNitro
                    wait 0
                until TIMERA > 190
                
                0922: camera_set_lerp_fov 24@ to 24@ timelimit 100 smooth_transition 0
                gosub @EQ_BugFix
                gosub @DisableNitro
                wait 0
                0A8D: 31@ = read_memory 0x58E020 size 2 virtual_protect 0
                if and
                    31@ == 0xECC3
                    0@ == 1
                then
    		        0A8C: write_memory 0x58E020 size 1 value 0x83 virtual_protect 0    //reenable crosshair
    		    end
            end
        end
        0931: camera_persist_fov 0                                                                        
    end                                    
end                       
                             			
0687: clear_char_tasks $PLAYER_ACTOR          			

if
    24@ == 100.0
then       			
    if
        08B7: is_local_var_bit_set_const 1@ bit 19
    then
        0A8C: write_memory LEFTSHOULDER2 size 2 value 0xFF virtual_protect 0    //LookLeft pressed        
        0A8C: write_memory RIGHTSHOULDER2 size 2 value 0xFF virtual_protect 0    //LookRight pressed
        wait 0
    end
else
    0D4E: 28@ = read_struct_offset 14@ offset RestoreDist size 2                                                                      			                                   
    if
        24@ == -2   //change view from first person view
    then
        28@ = 3
        0A8C: write_memory SELECT size 2 value 0x00 virtual_protect 0
        wait 0
        0A8C: write_memory SELECT size 2 value 0xFF virtual_protect 0   //emulates a second press of the change view button for skipping cinematic view
        TIMERA = 0
        repeat
            wait 0                          
            0801: get_camera_fov 31@
            if
                31@ == 100.0
            jf break                                                                           
        until TIMERA > 100
        wait 0
        if
            80E1: not is_button_pressed pad 0 button 13
        then
            28@ = 2
        end
        03E6: clear_help    //clear help message of cinematic view
    end               
    if
        28@ > 0
    then
        09AD: set_player_in_car_camera_mode 28@                          
    end
end                                                
  
if or
    08B7: is_local_var_bit_set_const 1@ bit 6
    24@ == 100.0
    24@ < -1
then   
    02EB: restore_camera_jumpcut
end                                                                      

if
    24@ <> -2   //change view from first person view
jf @FadeOut    
if
    24@ == 100.0    //first person view
then
    if
        88B7: not is_local_var_bit_set_const 1@ bit 20
    jf @FadeOut
else
    if and
        26@ > 1
        08B7: is_local_var_bit_set_const 1@ bit 6   //camera restore jumpcut
    then
        :FadeOut
        0085: set_lvar_int_to_lvar_int 24@ = 26@
        0EF7: clamp_int 24@ min 200 max 1000 store_to 24@
        016A: do_fade 1 24@
        043C: set_music_does_fade 1
        24@ += 50
        TIMERB = 0
    end
end

07CC: set_player_enter_car_button $PLAYER_CHAR can_enter_exit_vehicles 1

:FinishDriveBy
0931: camera_persist_fov 0
                
0A8D: 26@ = read_memory 0x52161A size 1 virtual_protect 0
0A8D: 27@ = read_memory 0x52161B size 4 virtual_protect 0                                                               				
if and
    26@ == 0xE9
    27@ == 0x000000B3 
then
    0A8C: write_memory 0x52161A size 1 value 0x0F virtual_protect 0
    0A8C: write_memory 0x52161B size 4 value 0x071887BE virtual_protect 0
end

0D4E: 22@ = read_struct_offset 14@ offset DistAdr size 4

23@ = AngleDownVal
if        
    88B7: not is_local_var_bit_set_const 1@ bit 29  // NoAngleLimit
then
    23@ = HeightVal
end

for 30@ = DistVal to 23@ step 0x04
    0D4E: 21@ = read_struct_offset 14@ offset 30@ size 4   
    0A8C: write_memory 22@ size 4 value 21@ virtual_protect 0 
    if
        30@ == DistVal
    then
        22@ += 0x0C
    end
    22@ += 0x04
end

if
    18@ < 0
then
    0D4E: 22@ = read_struct_offset 14@ offset SpVehAdr size 4
    0D4E: 21@ = read_struct_offset 14@ offset SpVehVal size 4
    0A8C: write_memory 22@ size 1 value 21@ virtual_protect 0
end

0D4E: 26@ = read_struct_offset 14@ offset CamStuff size 1
if
    26@ == 1
then
    0E28: write_struct_offset 14@ offset CamStuff 1 value 0
    0A8D: 26@ = read_memory 0x522423 size 2 virtual_protect 0
    if
        26@ == 0x9090
    then
        0A8C: write_memory 0x522423 size 2 value 0x6674 virtual_protect 0  //reverting camera stuff, probably actually not necessary
    end
end

gosub @ReenableAndPatchStuff

if
    8@ == 0
then
    0AAA: 31@ = get_script_struct_named 'WZOOMUL'
    if and
        31@ <> 0
        31@ <> -1
    then
        0D2F: 23@ = get_script_var 31@ index 8
        if
            23@ > 0
        then
            0085: set_lvar_int_to_lvar_int 8@ = 23@
        end
    end   
end
         
0881: set_player_fire_button $PLAYER_CHAR able_to_shoot_weapons 1

0A8D: 31@ = read_memory 0xB7CDD0 size 4 virtual_protect 0       // CPlayerData -> Player flags
08C3: clear_local_var_bit_const 31@ bit 3                       // Clear "Free aiming" flag
0A8C: write_memory 0xB7CDD0 size 4 value 31@ virtual_protect 0  // Fixes a bug causing camera bugs when leaving the car

08C3: clear_local_var_bit_const 1@ bit 6
08C3: clear_local_var_bit_const 1@ bit 12
08C3: clear_local_var_bit_const 1@ bit 25
08C3: clear_local_var_bit_const 1@ bit 28
0EF7: clamp_int 24@ min 0 max 1050 store_to 24@

if
    056E: does_vehicle_exist 16@
then
    gosub @SetCarVisible
    if
        08B7: is_local_var_bit_set_const 1@ bit 24  //BulletMod installed
    then
        0EAD: get_car_proofs 16@ bullet 21@ fire 22@ explosion 23@ collision 26@ melee 27@            
        02AC: set_car_proofs 16@ bullet 0 fire 22@ explosion 23@ collision 26@ melee 27@
    end        
    if and
        18@ > 2   // Bikes
        18@ < 13
    then
        if or
            18@ < 9
            18@ > 11
        then
            if
                08B7: is_local_var_bit_set_const 1@ bit 0
            then
                09C4: set_petrol_tank_weakpoint 16@ 1
            end
        end
    else
        if
            18@ > -14
        jf @EnableForbVehOFF       
        if and
            18@ > 13
            18@ < 19
        then
            :EnableForbVehOFF
            0A97: 31@ = get_vehicle_pointer 16@
            0D4E: 23@ = read_struct_offset 31@ offset 0x384 size 4  //m_pHandlingData
            if
                18@ > -14
            then
                0E28: write_struct_offset 23@ offset 0xDE size 1 value 18@    //AnimGroup
            else
                18@ *= -1
                0E28: write_struct_offset 23@ offset 0xDE size 1 value 18@    //AnimGroup
                18@ *= -1
            end   
        end
    end
end

while true
    if or
        3@ < 5
        8A4B: not is_pc_using_joypad
    jf break
    if or
        00E1: is_button_pressed pad 0 button 5
        00E1: is_button_pressed pad 0 button 7
    jf break
    if
        0256: is_player_playing $PLAYER_CHAR
    jf break
    if
        0449: is_char_sitting_in_any_car $PLAYER_ACTOR
    jf break    
    0A8C: write_memory CIRCLE size 2 value 0x00 virtual_protect 0
    0A8C: write_memory LEFTSHOULDER1 size 2 value 0x00 virtual_protect 0
    wait 0
end

0D4E: 26@ = read_struct_offset 14@ offset LookBehind size 1
if
    26@ == 1 
then
    0E28: write_struct_offset 14@ offset LookBehind size 1 value 0
    0A8D: 26@ = read_memory 0x527830 size 2 virtual_protect 0
    if
        26@ == 0x1FEB
    then
        0A8C: write_memory 0x527830 size 1 value 0x74 virtual_protect 0   //Reenable Look Behind
    end
end
 
23@ = 0xC084
gosub @ChangeSideLook

:ReenableVehFeatures
0D4E: 26@ = read_struct_offset 14@ offset VehWeapon size 1
if        
    26@ == 1 
then
    0E28: write_struct_offset 14@ offset VehWeapon size 1 value 0
    0A8D: 26@ = read_memory 0x6E398D size 2 virtual_protect 0
    if
        26@ == 0xE990
    then
        0A8C: write_memory 0x6E398D size 2 value 0x850F virtual_protect 0
    end
end
0D4E: 26@ = read_struct_offset 14@ offset Hydraulics size 1
if
    26@ > 0
then
    if and
        26@ == 2
        056E: does_vehicle_exist 16@
    then
        07FF: set_car_hydraulics 16@ 1
    end
    0E28: write_struct_offset 14@ offset Hydraulics size 1 value 0
    0A8D: 26@ = read_memory 0x6B1FC9 size 1 virtual_protect 0
    if
        26@ == 0xEB
    then 
        0A8C: write_memory 0x6B1FC9 size 1 value 0x74 virtual_protect 0
    end
end
gosub @ReenableBunnyhop

0D4E: 26@ = read_struct_offset 14@ offset DisableMenu size 1
if
    26@ == 1
then
    0E28: write_struct_offset 14@ offset DisableMenu size 1 value 0
    0A8D: 31@ = read_memory 0x576B70 size 2 virtual_protect 0
    if
        31@ == 0x56C3
    then
        0A8C: write_memory 0x576B70 size 1 value 0x53 virtual_protect 0   //Reenable CMenuManager::CheckForMenuClosing
    end
end 

0@ = 4
gosub @GetWeaponSlot
04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 31@ model_to 32@

:SuppressFireButton
while 0E8D: is_any_fire_button_pressed 0
    if
        0256: is_player_playing $PLAYER_CHAR
    jf break
    if
        0449: is_char_sitting_in_any_car $PLAYER_ACTOR
    jf break
    0A8C: write_memory CIRCLE size 2 value 0x00 virtual_protect 0
    0A8C: write_memory LEFTSHOULDER1 size 2 value 0x00 virtual_protect 0    
    wait 0
end

:EnableNitro
if and
    18@ >= 0
    8119: not is_car_dead 16@
jf @Main0
0A8D: 28@ = read_memory 17@ size 4 virtual_protect 0    //read nitro level
if and
    28@ < 1.0
    28@ >= 0.99
jf @Main0
0A8C: write_memory 17@ size 4 value 1.0 virtual_protect 0   //reenable nitro
jump @Main0


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:DisableNitro
if and
    18@ >= 0
    8119: not is_car_dead 16@
return_if_false
0A8D: 28@ = read_memory 17@ size 4 virtual_protect 0    //read nitro level
if and
    28@ <= 1.0
    28@ > 0.99
return_if_false
0A8C: write_memory 17@ size 4 value 0.99 virtual_protect 0  //disable nitro                                                        
return


:DisableMenu
0A8D: 31@ = read_memory 0x576B70 size 2 virtual_protect 0
if
    31@ == 0x5653
return_if_false
0A8C: write_memory 0x576B70 size 1 value 0xC3 virtual_protect 0   //Disable CMenuManager::CheckForMenuClosing 
0E28: write_struct_offset 14@ offset DisableMenu size 1 value 1
return


:DisableVehFeatures
gosub @DisableMenu
07CC: set_player_enter_car_button $PLAYER_CHAR can_enter_exit_vehicles 0
if and
    3@ > 2
    0A4B: is_pc_using_joypad    
gosub_if_false @EnableSideLook

if or
    30@ == 18   //Molotov
    30@ == 37   //Flamethrower
then
    0EAD: get_car_proofs 16@ bullet 21@ fire 22@ explosion 23@ collision 26@ melee 27@
    if
        22@ == 0
    then            
        02AC: set_car_proofs 16@ bullet 21@ fire 1 explosion 23@ collision 26@ melee 27@
        0EAC: get_char_proofs $PLAYER_ACTOR bullet 21@ fire 22@ explosion 23@ collision 26@ melee 27@            
        02AB: set_char_proofs $PLAYER_ACTOR bullet 21@ fire 1 explosion 23@ collision 26@ melee 27@
        08BD: set_local_var_bit_const 1@ bit 9
    end
end

if
    18@ < 0
then
    :DisableVehWeapon
    0A8D: 23@ = read_memory 0x6E398D size 2 virtual_protect 0
    if
        23@ == 0x850F
    return_if_false
    0A8C: write_memory 0x6E398D size 2 value 0xE990 virtual_protect 0
    0E28: write_struct_offset 14@ offset VehWeapon size 1 value 1
    return
end

if and
    18@ > 8 // Bicycles
    18@ < 12
then
    :DisableBunnyhop
    0A8D: 26@ = read_memory 0x6C184E size 4 virtual_protect 0
    0A8D: 27@ = read_memory 0x6C1852 size 2 virtual_protect 0
    0A8D: 28@ = read_memory 0x6C1854 size 1 virtual_protect 0
    if and
        26@ == 0x3BE8CE8B
        27@ == 0xFFED
        28@ == 0xFF
    return_if_false
    0E6A: make_nop 0x6C184E size 7
    0E28: write_struct_offset 14@ offset Bunnyhop size 1 value 1
    return
end

24@ = 0.0

:DisableHydraulics
if
    0803: does_car_have_hydraulics 16@
return_if_false
0A8D: 23@ = read_memory 0x6B1FC9 size 1 virtual_protect 0
if
    23@ == 0x74
return_if_false
0A8C: write_memory 0x6B1FC9 size 1 value 0xEB virtual_protect 0
if or
    24@ <> 0.0
    8A4B: not is_pc_using_joypad
then
    0E28: write_struct_offset 14@ offset Hydraulics size 1 value 1
    return
end
09FE: reset_vehicle_hydraulics 16@
07FF: set_car_hydraulics 16@ 0
0E28: write_struct_offset 14@ offset Hydraulics size 1 value 2   
return


:ReenableBunnyhop
0D4E: 26@ = read_struct_offset 14@ offset Bunnyhop size 1
if
    26@ == 1
return_if_false
0E28: write_struct_offset 14@ offset Bunnyhop size 1 value 0
0A8D: 26@ = read_memory 0x6C184E size 4 virtual_protect 0
0A8D: 27@ = read_memory 0x6C1852 size 2 virtual_protect 0
0A8D: 28@ = read_memory 0x6C1854 size 1 virtual_protect 0
if and
    26@ == 0x90909090
    27@ == 0x9090
    28@ == 0x90
return_if_false
0A8C: write_memory 0x6C184E size 4 value 0x3BE8CE8B virtual_protect 0
0A8C: write_memory 0x6C1852 size 2 value 0xFFED virtual_protect 0
0A8C: write_memory 0x6C1854 size 1 value 0xFF virtual_protect 0
return


:DisableAndPatchStuff
0A8D: 31@ = read_memory 0x74066F size 4 virtual_protect 0
if
    31@ == 0x858CEC
then
    0A8E: int_add 31@ = 14@ + CrosshairMult
    0A8C: write_memory 0x74066F size 4 value 31@ virtual_protect 0
end
    
0A8D: 26@ = read_memory 0x627E63 size 4 virtual_protect 0
0A8D: 27@ = read_memory 0x627E67 size 2 virtual_protect 0
0A8D: 31@ = read_memory 0x627E69 size 1 virtual_protect 0
if and
    26@ == 0x2C42C7
    27@ == 0x00
    31@ == 0x00
then
    0E6A: make_nop 0x627E63 size 7  //Disable crosshair reset in CTaskSimpleGangDriveBy
    0E28: write_struct_offset 14@ offset CrosshrDecay size 1 value 1
end

0A8D: 31@ = read_memory 0x60F241 size 1 virtual_protect 0
if
    31@ == 0x74
then
    0A8C: write_memory 0x60F241 size 1 value 0xEB virtual_protect 0 //Disable Sniper Click Sound
    0E28: write_struct_offset 14@ offset ClickSound size 1 value 1
end

:PatchSniperAndCamera
if
    0E26: is_weapon_fire_type 30@ 4 //Camera
then
    0A8C: write_memory 28@ size 4 value 0x01 virtual_protect 0  //Change to InstantHit        
    0A8D: 31@ = read_memory 0x455764 size 2 virtual_protect 0
    if
        31@ == 0x752E
    then
        0A8C: write_memory 0x455764 size 2 value 0x7460 virtual_protect 0   //Patch SnapShot Pickup visibility
        0E28: write_struct_offset 14@ offset Snapshot size 1 value 1
    end   
    08BD: set_local_var_bit_const 1@ bit 5
    0AAA: 26@ = get_script_struct_named 'DBYFNPC'
    if and
        26@ <> 0
        26@ <> -1
    then
        0D2F: 27@ = get_script_var 26@ index 0
        08BD: set_local_var_bit_const 27@ bit 7
        0D2E: set_script_var 26@ index 0 value 27@
    end
else
    0A96: 26@ = get_ped_pointer $PLAYER_ACTOR
    0D4E: 27@ = read_struct_offset 26@ offset 0x480 size 4
    0E28: write_struct_offset 27@ offset 0x2C size 4 value 0.001  //Reset float for crosshair expansion
    if
        25@ > 4.0
    then
        0A8D: 26@ = read_memory 0x740676 size 2 virtual_protect 0
        0A8D: 27@ = read_memory 0x740678 size 1 virtual_protect 0
        if and
            26@ == 0x58D9
            27@ == 0x2C
        then
            0E6A: make_nop 0x740676 size 3  //Disable crosshair expansion in CTaskSimpleGangDriveBy
            0E28: write_struct_offset 14@ offset CrosshrExpan size 1 value 1
        end
    end        
    0D4E: 31@ = read_struct_offset 14@ offset SniperFlags size 4
    if and
        30@ > 33
        31@ == 0
    return_if_false
    0D4E: 31@ = read_struct_offset 28@ offset 0x18 size 4   //Flags
    if or
        30@ == 34
        31@ == 0xA014
    return_if_false
    0E28: write_struct_offset 14@ offset SniperFlags size 4 value 31@
    0E28: write_struct_offset 28@ offset 0x18 size 4 value 0x7008    
    0A8D: 31@ = read_memory 0x58E1BF size 1 virtual_protect 0
    if
        31@ == 0x21
    then
        0A8C: write_memory 0x58E1BF size 1 value 0x22 virtual_protect 0
        0E28: write_struct_offset 14@ offset SniperCrosshr size 1 value 1
    end
end
0E28: write_struct_offset 14@ offset TempWeapInfo size 4 value 28@
return


:ReenableAndPatchStuff
0A8E: int_add 31@ = 14@ + CrosshairMult
0A8D: 26@ = read_memory 0x74066F size 4 virtual_protect 0
if
    003B: is_int_lvar_equal_to_int_lvar 26@ == 31@
then
    0A8C: write_memory 0x74066F size 4 value 0x858CEC virtual_protect 0
end

0D4E: 26@ = read_struct_offset 14@ offset CrosshrDecay size 1
if
    26@ == 1
then
    0E28: write_struct_offset 14@ offset CrosshrDecay size 1 value 0
    0A8D: 26@ = read_memory 0x627E63 size 4 virtual_protect 0
    0A8D: 27@ = read_memory 0x627E67 size 2 virtual_protect 0
    0A8D: 31@ = read_memory 0x627E69 size 1 virtual_protect 0
    if and
        26@ == 0x90909090
        27@ == 0x9090
        31@ == 0x90
    then
        0A8C: write_memory 0x627E63 size 4 value 0x2C42C7 virtual_protect 0  //Reenable crosshair reset in CTaskSimpleGangDriveBy
        0A8C: write_memory 0x627E67 size 2 value 0x00 virtual_protect 0
        0A8C: write_memory 0x627E69 size 1 value 0x00 virtual_protect 0
    end    
end

0D4E: 26@ = read_struct_offset 14@ offset ClickSound size 1
if
    26@ == 1
then
    0E28: write_struct_offset 14@ offset ClickSound size 1 value 0
    0A8D: 26@ = read_memory 0x60F241 size 1 virtual_protect 0
    if
        26@ == 0xEB
    then 
        0A8C: write_memory 0x60F241 size 1 value 0x74 virtual_protect 0  //Revert Sniper Click Sound
    end
end

:RevertSniperAndCamera
0D4E: 26@ = read_struct_offset 14@ offset CrosshrExpan size 1
if
    26@ == 1
then
    0E28: write_struct_offset 14@ offset CrosshrExpan size 1 value 0
    0A8D: 26@ = read_memory 0x740676 size 2 virtual_protect 0
    0A8D: 27@ = read_memory 0x740678 size 1 virtual_protect 0
    if and
        26@ == 0x9090
        27@ == 0x90
    then
        0A8C: write_memory 0x740676 size 2 value 0x58D9 virtual_protect 0   //Reenable crosshair expansion in CTaskSimpleGangDriveBy
        0A8C: write_memory 0x740678 size 1 value 0x2C virtual_protect 0
    end    
end
0D4E: 27@ = read_struct_offset 14@ offset TempWeapInfo size 4
if
    27@ <> 0
return_if_false    
0D4E: 31@ = read_struct_offset 14@ offset SniperFlags size 4
if
    31@ == 0
then
    0A2F: set_photo_camera_effect 0
    0A8C: write_memory 27@ size 4 value 0x04 virtual_protect 0  // Revert Camera firetype    
    0D4E: 26@ = read_struct_offset 14@ offset SnapShot size 1
    if
        26@ == 1
    then    
        0E28: write_struct_offset 14@ offset SnapShot size 1 value 0
        0A8D: 26@ = read_memory 0x455764 size 2 virtual_protect 0
        if
            26@ == 0x7460
        then
            0A8C: write_memory 0x455764 size 2 value 0x752E virtual_protect 0  //Revert SnapShot Pickup visibility
        end
    end
    08C3: clear_local_var_bit_const 1@ bit 5
    0AAA: 26@ = get_script_struct_named 'DBYFNPC'
    if and
        26@ <> 0
        26@ <> -1
    then
        0D2F: 27@ = get_script_var 26@ index 0
        08C3: clear_local_var_bit_const 27@ bit 7
        0D2E: set_script_var 26@ index 0 value 27@
    end
else
    0E28: write_struct_offset 27@ offset 0x18 size 4 value 31@
    0E28: write_struct_offset 14@ offset SniperFlags size 4 value 0x00    
    0D4E: 26@ = read_struct_offset 14@ offset SniperCrosshr size 1
    if
        26@ == 1
    then
        0E28: write_struct_offset 14@ offset SniperCrosshr size 1 value 0
        0A8D: 26@ = read_memory 0x58E1BF size 1 virtual_protect 0
        if
            26@ == 0x22
        then   
            0A8C: write_memory 0x58E1BF size 1 value 0x21 virtual_protect 0
        end
    end    
end
0E28: write_struct_offset 14@ offset TempWeapInfo size 4 value 0x00
return


:TweakFOV
0A8E: int_add 31@ = 29@ + FOV1
0D4E: 21@ = read_struct_offset 14@ offset 31@ size 4
if and
    24@ > 68.0
    24@ < 72.0
then
    24@ = 70.0
end
if
    8045: not is_float_lvar_equal_to_float_lvar 21@ <> 24@
return_if_false
0922: camera_set_lerp_fov 24@ to 21@ timelimit 400 smooth_transition 0    //apply TweakFOV
0931: camera_persist_fov 1
return


:BulletModFix
31@ = 0
08C3: clear_local_var_bit_const 1@ bit 24
0EAD: get_car_proofs 16@ bullet 31@ fire 32@ explosion 32@ collision 32@ melee 32@
if
    31@ == 0
return_if_false
if
    8AA2: not 31@ = load_dynamic_library "bullet.asi"
then
    if
        0AA2: 31@ = load_dynamic_library "$bullet.asi"
    return_if_false
end
0AA3: free_dynamic_library 31@
08BD: set_local_var_bit_const 1@ bit 24
return


:PatchDrivebyTask
0A96: 21@ = get_ped_pointer $PLAYER_ACTOR
0D4E: 22@ = read_struct_offset 21@ offset 0x480 size 4
if
    22@ <> 0
then
    0D4E: 23@ = read_struct_offset 22@ offset 0x2C size 4           // Dynamic float used to calculate crosshair expansion
    if
        23@ > 0.0
    then
        0EF4: clamp_float 23@ min 0.0 max 6.0 store_to 23@
        0A8D: 26@ = read_memory 0x8D2E64 size 4 virtual_protect 0   // Decay = *(float*)0x8D2E64
        0A8D: 27@ = read_memory 0xB7CB5C size 4 virtual_protect 0   // CTimer::ms_fTimeStep
        0AEE: 28@ = 26@ pow 27@
        006B: mult_float_lvar_by_float_lvar 23@ *= 28@
        if
            25@ > 2.0
        then
            0073: div_float_lvar_by_float_lvar 23@ /= 25@
            23@ *= 2.0
        end                    
        if
            23@ < 0.001
        then
            23@ = 0.0
        end
        0E28: write_struct_offset 22@ offset 0x2C size 4 value 23@
    end
end

0E8B: get_char_weapon_state $PLAYER_ACTOR store_to 31@
if
    08B7: is_local_var_bit_set_const 1@ bit 24  //BulletMod installed
then
    0EAD: get_car_proofs 16@ bullet 21@ fire 22@ explosion 23@ collision 26@ melee 27@ 
    if
        31@ == 1
    then                       
        02AC: set_car_proofs 16@ bullet 1 fire 22@ explosion 23@ collision 26@ melee 27@
    else
        02AC: set_car_proofs 16@ bullet 0 fire 22@ explosion 23@ collision 26@ melee 27@
    end
end
0EFF: get_char_simplest_active_task $PLAYER_ACTOR id_to 21@ pointer_to 22@
if
    22@ <> 0
then
    0D4E: 21@ = read_struct_offset 22@ offset 0x24 size 4   // Direction ID
end
if
    803B: not is_int_lvar_equal_to_int_lvar 21@ <> 9@
then
    08BD: set_local_var_bit_const 1@ bit 12
    0085: set_lvar_int_to_lvar_int 9@ = 21@
end
if
    31@ == 0
then
    if
        08B7: is_local_var_bit_set_const 1@ bit 27  //Realistic Weapon Settings Mod installed
    return_if_false 
    if
        TIMERA < 0
    return_if_false
    jump @RWS_Fix
end
if
    31@ == 1
then
    if
        08B7: is_local_var_bit_set_const 1@ bit 12
    return_if_false
    if
        02E0: is_char_shooting $PLAYER_ACTOR
    return_if_false
    08C3: clear_local_var_bit_const 1@ bit 12
    jump @ShootRateFix
end 
if
    31@ == 2    //Reloading
return_if_false

:RWS_Fix
08BD: set_local_var_bit_const 1@ bit 12
0087: set_lvar_float_to_lvar_float 21@ = 25@
25@ = 1.0
if and
    08B7: is_local_var_bit_set_const 1@ bit 27  //Realistic Weapon Settings Mod installed
    8E5D: not is_cheat_active 72    //Infinite ammo
    $_100_Percent_Complete == 0
then
    0085: set_lvar_int_to_lvar_int 22@ = 15@
    0E83: get_current_char_weaponinfo $PLAYER_ACTOR store_to 15@
    gosub @GetCWeapon
    0085: set_lvar_int_to_lvar_int 15@ = 22@
    0D4E: 22@ = read_struct_offset 26@ offset 0x0C size 4    //Total ammo
    if
        22@ < 1
    then
        31@ = 3
        return
    end
    if
        23@ > 1
    then
        if or
            TIMERA < 0
            27@ > 0
        then
            31@ = 2
            0E28: write_struct_offset 26@ offset 0x04 size 4 value 0x02  //Weapon state
            0A8C: write_memory CIRCLE size 2 value 0x00 virtual_protect 0             
        else 
            if
                80E1: not is_button_pressed pad 0 button 17 
            then
                if
                    0A4B: is_pc_using_joypad
                then
                    0D4E: 27@ = read_struct_offset 14@ offset JKey1 size 2
                    0D4E: 28@ = read_struct_offset 14@ offset JKey2 size 2
                    if
                        28@ > 0
                    then
                        if or
                            80E1: not is_button_pressed pad 0 button 27@
                            80E1: not is_button_pressed pad 0 button 28@
                        jf @StartReload
                    else
                        if
                            80E1: not is_button_pressed pad 0 button 27@
                        jf @StartReload    
                    end                                
                else
                    0D4E: 27@ = read_struct_offset 14@ offset KKey1 size 2
                    0D4E: 28@ = read_struct_offset 14@ offset KKey2 size 2
                    if
                        28@ > 0
                    then
                        if or
                            8AB0: not is_key_pressed 27@
                            8AB0: not is_key_pressed 28@
                        jf @StartReload
                    else
                        if
                            0AB0: is_key_pressed 27@
                        then
                            :StartReload    
                            TIMERA = -1212
                        end
                    end
                end
            end
            31@ = 0
            0E28: write_struct_offset 26@ offset 0x04 size 4 value 0x00  //Weapon state
            25@ = 0.0
        end                     
    end                  
end
gosub @ShootRateFix
0087: set_lvar_float_to_lvar_float 25@ = 21@
return


:EQ_BugFix
if
    0A4B: is_pc_using_joypad
then
    :MaybeCarMovementFix
    if
        3@ < 5
    then
        if
            3@ > 2
        then
            if
                12@ <> 1
            jf @CarMovementFix
            if or
                12@ == 0
                24@ <> 100.0
            jf @CarMovementFix
            0A8C: write_memory LEFTSHOULDER2 size 2 value 0x00 virtual_protect 0    //LookLeft not pressed
            0A8C: write_memory RIGHTSHOULDER2 size 2 value 0x00 virtual_protect 0    //LookRight not pressed                   
        else                            
            0AAA: 31@ = get_script_struct_named 'WZOOMUL'
            if and
                31@ <> 0
                31@ <> -1
            jf @CarMovementFix
            0D2F: 31@ = get_script_var 31@ index 0
            if
                31@ == 1
            jf @CarMovementFix
        end
    end
else        
    :CarMovementFix
    if
        84C8: not is_char_in_flying_vehicle $PLAYER_ACTOR
    then
        0A8D: 26@ = read_memory LEFTSHOULDER2 size 2 virtual_protect 0
        0A8D: 27@ = read_memory RIGHTSHOULDER2 size 2 virtual_protect 0
        if or
            26@ <> 0
            27@ <> 0
        then
            0A8C: write_memory LEFTSHOULDER2 size 2 value 0xFF virtual_protect 0    //LookLeft pressed
            0A8C: write_memory RIGHTSHOULDER2 size 2 value 0xFF virtual_protect 0    //LookRight pressed
        end
    end
end

if
    88B7: not is_local_var_bit_set_const 1@ bit 21  // NoDriveWhileAiming
return_if_false
if
    00E1: is_button_pressed pad 0 button 0
then
    0A8C: write_memory LEFTSTICKX size 2 value 0x00 virtual_protect 0
end
if
    00E1: is_button_pressed pad 0 button 14
then
    0A8C: write_memory SQUARE size 2 value 0x00 virtual_protect 0
end
if
    00E1: is_button_pressed pad 0 button 16
then
    0A8C: write_memory CROSS size 2 value 0x00 virtual_protect 0
end
return


:SetCarVisible
if
    08B7: is_local_var_bit_set_const 1@ bit 14
return_if_false
0338: set_car_visible 16@ 1
08C3: clear_local_var_bit_const 1@ bit 14
return


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:WeaponSwitch
if
    0A4B: is_pc_using_joypad
then
    :WeapSwitchPad
    if or
        6@ > 0
        04C8: is_char_in_flying_vehicle $PLAYER_ACTOR
    then
        if
            6@ > 1
        then
            if
                8E3E: not is_button_just_pressed pad 0 button 8     //D-Pad Up
            jf @NextWeapon
            if
                8E3E: not is_button_just_pressed pad 0 button 9     //D-Pad Down
            jf @LastWeapon
        else
            if
                8E3E: not is_button_just_pressed pad 0 button 11    //D-Pad Right
            jf @NextWeapon
            if
                8E3E: not is_button_just_pressed pad 0 button 10    //D-Pad Left
            jf @LastWeapon
        end        
    end
    if
        3@ < 3
    return_if_false
else
    :WeapSwitchMouse
    if
        7@ > 0
    then
        if or
            7@ == 1
            0E42: is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
        then
            if
                0E11: is_mouse_wheel_down
            then
                gosub @SuppressRadioSwitch
                gosub @NextWeapon
                repeat
                    wait 0
                    gosub @SuppressRadioSwitch
                until 8E11: not is_mouse_wheel_down
                return
            end
            if
                0E10: is_mouse_wheel_up
            then
                gosub @SuppressRadioSwitch            
                gosub @LastWeapon
                repeat
                    wait 0
                    gosub @SuppressRadioSwitch                  
                until 8E10: not is_mouse_wheel_up
                return
            end
        end
    end
    if or
        0AB0: is_key_pressed 10@
        0AB0: is_key_pressed 11@
    then
        gosub @SuppressRadioSwitch
        if 
            8E3D: not is_key_just_pressed 10@
        jf @NextWeapon 
        if
            8E3D: not is_key_just_pressed 11@
        jf @LastWeapon
    end
end
if and
    8@ > 0
    84C8: not is_char_in_flying_vehicle $PLAYER_ACTOR
return_if_false
if or
    8@ == 1
    0E42: is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
return_if_false 
if and 
    0E3E: is_button_just_pressed pad 0 button 7      //look right
    8E3E: not is_button_just_pressed pad 0 button 5
then
    :NextWeapon
    21@ = 1
    jump @SwitchWeapon
end
if and 
    0E3E: is_button_just_pressed pad 0 button 5      //look left
    8E3E: not is_button_just_pressed pad 0 button 7
return_if_false           

:LastWeapon  
21@ = -1

:SwitchWeapon
gosub @GetWeaponSlot        
      
:SlotIteration
005A: add_int_lvar_to_int_lvar 29@ += 21@                     
if
    29@ < 1
then
    29@ = 13
end            
if
    29@ > 13
then
    29@ = 1
end    
04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 31@ model_to 32@
if or
    0E26: is_weapon_fire_type 30@ 1 //InstantHit
    8E42: not is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
jf @SlotIteration                        
if
    29@ == 1    //Fist                
then
    25@ = 1.0
    jump @SetWeaponSlot
end                         
if
    31@ > 0
jf @SlotIteration     
gosub @GetShootRate
if
    23@ == -4.20    //Flag for valid weapons
jf @SlotIteration
if
    0E42: is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
return_if_false
gosub @RevertSniperAndCamera
gosub @PatchSniperAndCamera

:ShootRateFix
if
    847A: not is_char_on_any_bike $PLAYER_ACTOR
jf @BikeAnims 
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebylhs"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebylhs" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebyrhs"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebyrhs" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebylhs_fwd"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebylhs_fwd" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebylhs_bwd"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebylhs_bwd" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebytop_lhs"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebytop_lhs" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebytop_rhs"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebytop_rhs" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebyrhs_fwd"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebyrhs_fwd" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "gang_drivebyrhs_bwd"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "gang_drivebyrhs_bwd" 25@
    return
end

:BikeAnims
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "pass_driveby_lhs"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "pass_driveby_lhs" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "pass_driveby_rhs"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "pass_driveby_rhs" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "pass_driveby_fwd"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "pass_driveby_fwd" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "pass_driveby_bwd"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "pass_driveby_bwd" 25@
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "cop_dvby_l"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "cop_dvby_l" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "cop_dvby_r"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "cop_dvby_r" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "cop_dvby_ft"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "cop_dvby_ft" 25@
    return
end
if
    0611: is_char_playing_anim $PLAYER_ACTOR performing "cop_dvby_b"
then
    0393: set_char_anim_speed $PLAYER_ACTOR "cop_dvby_b" 25@
    return
end
return


:SuppressRadioSwitch    
0A8C: write_memory DPADUP size 2 value 0x00 virtual_protect 0
0A8C: write_memory DPADDOWN size 2 value 0x00 virtual_protect 0
return


:CheckValidSituation
13@ = 0
0E28: write_struct_offset 14@ offset DistAdr size 4 value 0x8CC4F8
0811: get_car_char_is_using 16@ = actor $PLAYER_ACTOR
0441: 9@ = get_car_model 16@
0EF9: get_car_animgroup 16@ store_to 18@
if and
    9@ <> 601   //S.W.A.T.
    18@ <> 24   //tank
then
    0E12: get_vehicle_subclass 16@ subclass_to 24@   
    if and
        24@ > 2
        24@ < 7
    then   
        08BD: set_local_var_bit_const 1@ bit 17 // Flag for cars without windshield
        0E28: write_struct_offset 14@ offset SpVehVal size 4 value 24@
        if
            24@ == 3
        then
            0E28: write_struct_offset 14@ offset SpVehAdr size 4 value 0x6D5D47
            0D4E: 13@ = read_struct_offset 14@ offset Helis size 1
        else
            if
                24@ == 4
            then
                0E28: write_struct_offset 14@ offset SpVehAdr size 4 value 0x6D5D4C
                0D4E: 13@ = read_struct_offset 14@ offset Planes size 1
            else
                08BD: set_local_var_bit_const 1@ bit 16 // Flag for cars without door windows
                if
                    24@ == 5
                then
                    0E28: write_struct_offset 14@ offset SpVehAdr size 4 value 0x6D5D56
                    0D4E: 13@ = read_struct_offset 14@ offset Boats size 1
                else
                    0E28: write_struct_offset 14@ offset SpVehAdr size 4 value 0x6D5D51
                    0D4E: 13@ = read_struct_offset 14@ offset Trains size 1
                end           
            end
        end
        if
            18@ == 23   //Vortex
        then
            18@ = -5
        else 
            if and
                18@ > 13
                18@ < 19
            then
                18@ *= -1
            else
                0A90: int_mul 18@ = 24@ * -1
            end
        end      
    else   
        if and
            18@ > 2 //Bikes
            18@ < 13
        then
            08BD: set_local_var_bit_const 1@ bit 16 // Flag for cars without door windows
            08BD: set_local_var_bit_const 1@ bit 17 // Flag for cars without windshield
            0E28: write_struct_offset 14@ offset DistAdr size 4 value 0x8CC4DC
            0D4E: 13@ = read_struct_offset 14@ offset Bikes size 1        
        else
            0D4E: 13@ = read_struct_offset 14@ offset Cars size 1
        end
    end    
    0AD3: 26@s = string_format '%d' 9@
    31@ = 0   
    0AC8: 31@ = allocate_memory size 256
    if 
        0AF4: 31@ = read_string_from_ini_file "cleo\DrivebySettings.ini" section "EXCEPTIONS" key 26@s
    then        
        25@ = 0
        26@ = 0
        27@ = 0
        0AD4: 32@ = scan_string 31@ format "%d/%d/%d" 25@ 26@ 27@
        0AC9: free_memory 31@
        13@ = 0
        if
            25@ > 0
        then
            08BD: set_local_var_bit_const 13@ bit 1
        end
        if
            26@ > 0
        then
            08BD: set_local_var_bit_const 13@ bit 2
        end
        if
            27@ > 0
        then
            08BD: set_local_var_bit_const 13@ bit 3
        end
    end            
end

gosub @Get_Weapon
04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 5 store_weapon_to 20@ ammo_to 21@ model_to 22@     //SMG equipped?

19@ = 0

0A8D: 31@ = read_memory 0xB7CEEB size 1 virtual_protect 0   // CPlayerData: CanDoDriveBy
if
    31@ == 0
then
    if
        8@ <> 1
    jf @NoValidSituation
    if or
        3@ < 3
        8A4B: not is_pc_using_joypad
    jf @NoValidSituation
end

if and
    0E1D: is_on_mission
    08B7: is_local_var_bit_set_const 1@ bit 3   //DisableOnMission
then
    23@ = 0
    
    :NoValidSituation
    19@ = -4.20    
    if
        29@ <> 5
    return_if_false    
end

if
    23@ <> -4.20    //No valid weapon
return_if_false

if
    21@ > 0
then
    29@ = 5
    if
        0@ > 0
    return_if_false
    06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 0
    return
end
29@ = 1
06AB: hide_char_weapon_for_scripted_cutscene $PLAYER_ACTOR all_weapons_hidden 1   //Switch to fist if no valid weapon is equipped
return


:Cheat
if
    88B7: not is_local_var_bit_set_const 1@ bit 7
then
    08BD: set_local_var_bit_const 1@ bit 7
    26@s = 'CHEAT1'
else
    08C3: clear_local_var_bit_const 1@ bit 7
    26@s = 'CHEAT8'
end
03E5: print_help 26@s
0AAA: 23@ = get_script_struct_named 'WeaponRe'
if and
    23@ <> 0
    23@ <> -1
    0AF2: 31@ = read_float_from_ini_file "cleo\WeaponRecoilAuto.ini" section "RecoilMultipliers" key "fDriveBy"
then
    0D2F: 22@ = get_script_var 23@ index 14
    if and
        22@ > 0.09
        22@ < 10.0
    then
        if
            08B7: is_local_var_bit_set_const 1@ bit 7
        then
            31@ = 0.1
        end                  
        0D2E: set_script_var 23@ index 14 value 31@ //Smaller recoil because it is too much with high shoot rates
    end
end
if
    0@ > 1
return_if_false

:Get_Weapon
25@ = 1.0
23@ = 0
if
    29@ == -1
then
    gosub @GetWeaponSlot
else
    if or
        30@ > -1
        19@ == -1.61
    gosub_if_false @GetWeaponSlot
end

04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 29@ store_weapon_to 30@ ammo_to 31@ model_to 32@
if
    29@ == 1
then
    04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 5 store_weapon_to 28@ ammo_to 31@ model_to 32@
    if
        31@ < 1
    return_if_false
    23@ = -4.20    
    jump @SetWeaponSlot
end
if
    31@ < 1
then
    04B8: get_char_weapon_in_slot $PLAYER_ACTOR slot 5 store_weapon_to 30@ ammo_to 31@ model_to 32@
    if
        31@ > 0
    return_if_false
    29@ = 5
end 

:GetShootRate
25@ = 1.0
23@ = 0
gosub @SetWeaponSlot
0E83: get_current_char_weaponinfo $PLAYER_ACTOR store_to 28@
if
    29@ <> 5
then
    if
        13@ > 0
    return_if_false
    0E89: get_weaponinfo_fire_type 28@ store_to 31@
    if
        31@ == 4
    then
        31@ = 1
    end
    if or   
        31@ < 1
        31@ > 3
        08B7: is_local_var_bit_set_const 13@ bit 31@
    return_if_false
end
0D4E: 27@ = read_struct_offset 28@ offset 0x30 size 4   //Skill level
0EF7: clamp_int 27@ min 0 max 2 store_to 27@     
if and
    15@ <> 0
    27@ < 2
then
    27@ += 1
    0E84: get_weaponinfo 30@ skill 27@ store_to 23@
    if
        803C: not is_int_var_equal_to_int_lvar 23@ <> 15@
    then
        27@ -= 1
        23@ = 0
    end
end
0A90: int_mul 26@ = 27@ * 0x04
if
    30@ < 256
jf @DefaultSetting
0A90: int_mul 31@ = 30@ * 0x0C
005A: add_int_lvar_to_int_lvar 31@ += 26@
0D4E: 25@ = read_struct_offset 14@ offset 31@ size 4
if
    25@ == -2.0
then
    :DefaultSetting
    if
        0E26: is_weapon_fire_type 30@ 1 //InstantHit
    return_if_false
    26@ += Poor
    0D4E: 25@ = read_struct_offset 14@ offset 26@ size 4
end
if or
    29@ <> 5
    25@ > 0.0
jf @DefaultShootRate
if
    25@ >= 0.0
then
    if
        25@ == 0.0
    then
        if
            8E42: not is_char_doing_task_id $PLAYER_ACTOR task_id 1022  //driveby
        return_if_false
        23@ = -4.20
        return 
    end
    if or
        25@ < 0.01
        25@ > 9.99
    then
        :DefaultShootRate
        25@ = 1.0
    end
    //Dual wield ammo bug fix
    0D4E: 31@ = read_struct_offset 28@ offset 0x18 size 4   //Flags
    if and
        31@ == 0x3833    //Dual wielded
        23@ == 0
    then
        if
            15@ == 0
        gosub_if_false @RevertDual
        0D4E: 23@ = read_struct_offset 28@ offset 0x34 size 4   //Required skill stat level
        if
            23@ > 0
        then
            0085: set_lvar_int_to_lvar_int 15@ = 28@
            0E28: write_struct_offset 15@ offset 0x34 size 4 value 99999    //Required skill stat level      
            gosub @GetCWeapon
            23@ /= 2
            if
                002D: is_int_lvar_greater_than_int_lvar 27@ > 23@
            then
                0062: sub_int_lvar_from_int_lvar 23@ -= 27@
                005A: add_int_lvar_to_int_lvar 27@ += 23@
                0E28: write_struct_offset 26@ offset 0x08 size 4 value 27@   //Current ammo in clip
            end
            0E83: get_current_char_weaponinfo $PLAYER_ACTOR store_to 28@
        end
    end
    
    0D4E: 26@ = read_struct_offset 28@ offset 0x50 size 4  //AnimLoop2End
    0D4E: 27@ = read_struct_offset 28@ offset 0x4C size 4  //AnimLoop2Start
    0063: sub_float_lvar_from_float_lvar 26@ -= 27@
    0AEE: 27@ = 26@ pow -0.9596   
    27@ *= 0.1749
    if
        23@ <> 0
    then
        27@ *= 1.06  //Compensation for slower single shoot rates with dual wielded weapons
    end
    006B: mult_float_lvar_by_float_lvar 25@ *= 27@
    0EF4: clamp_float 25@ min 0.01 max 8.0 store_to 25@    
    23@ = -4.20 //Flag for valid weapon
end
if and
    25@ < 5.0
    08B7: is_local_var_bit_set_const 1@ bit 7   //Cheat activated
return_if_false
25@ = 5.0
23@ = -4.20
return


:RevertDual
0E28: write_struct_offset 15@ offset 0x34 size 4 value 9   //Required skill stat level             
gosub @GetCWeapon
15@ = 0  
0D4E: 31@ = read_struct_offset 26@ offset 0x0C size 4    //Total ammo
if
    002D: is_int_lvar_greater_or_equal_to_int_lvar 31@ >= 23@
return_if_false 
23@ /= 2
if
    002D: is_int_lvar_greater_or_equal_to_int_lvar 23@ >= 27@
return_if_false
005A: add_int_lvar_to_int_lvar 27@ += 23@
0E28: write_struct_offset 26@ offset 0x08 size 4 value 27@   //Current ammo in clip
return


:GetCWeapon
0D4E: 26@ = read_struct_offset 15@ offset 0x14 size 4    //Slot
26@ *= 0x1C //CWeapon Size
0A96: 27@ = get_ped_pointer $PLAYER_ACTOR
005A: add_int_lvar_to_int_lvar 26@ += 27@
26@ += 0x5A0 //CWeapon
0D4E: 27@ = read_struct_offset 26@ offset 0x08 size 4   //Current ammo in clip
0D4E: 23@ = read_struct_offset 15@ offset 0x20 size 2   //Ammo clip
return


:GetWeaponSlot
0A96: 29@ = get_ped_pointer $PLAYER_ACTOR
0D4E: 29@ = read_struct_offset 29@ offset 0x718 size 1  //[byte] Current weapon slot (1 byte)
29@ += 1
return


:SetWeaponSlot
0A96: 31@ = get_ped_pointer $PLAYER_ACTOR
0AA6: call_method 0x5E6280 struct 31@ num_params 1 pop 0 30@    //Forces the weapon stored in 30@ to be selected
return


:SetAmmo
if and
    $_100_Percent_Complete <> 1
    8E5D: not is_cheat_active 72    //Infinite ammo
return_if_false
9@ -= 1
017B: set_char_ammo $PLAYER_ACTOR 30@ 9@
return


//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


:Buffer
hex
    00(3218)
end


:ILoveMyGirlfriendJessica
TIMERA = 0

repeat
    wait 0
    if
        0@ == 3
    then
        0AD1: print_formatted_now "Manual Driveby Refixed: You installed multiple copies of the mod. Find the wrong one and clean up your game." time 200
    end
    if
        0@ == 2
    then
        0AD1: print_formatted_now "Manual Driveby Refixed: CLEO+ 1.2.0 or newer required. It's a plugin for CLEO. Please download and install it." time 200
    end
    if
        0@ == 1
    then 
        0AD1: print_formatted_now "Manual Driveby Refixed: You forgot to delete an old version of Manual Driveby %s. Find and uninstall it and try again." time 200 26@s
    end
    if
        0@ == 0
    then
        0AD1: print_formatted_now "Manual Driveby Refixed: Failed to find the file 'DrivebySettings.ini'. Check the file path or file name." time 200
    end
    if and
        09E7: is_player_control_on $PLAYER_CHAR
        816B: not fading
    jf @ILoveMyGirlfriendJessica
until TIMERA > 10000 

0A93: terminate_this_custom_script