if (!String.format) {
    String.format = function(format) {
        var args = Array.prototype.slice.call(arguments, 1)
        return format.replace(/{(\d+)}/g, function(match, number) { 
            return typeof args[number] != "undefined" ? args[number] : match
        })
    }
}

var easing = {
    lerp: function(a, b, percentage) {
        return a + (b - a) * percentage
    }
}

var hsv_to_rgb = function(h, s, v) {
    var r, g, b, i, f, p, q, t;

    if (arguments.length === 1) {
        s = h.s, v = h.v, h = h.h;
    }

    i = Math.floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);

    switch (i % 6) {
        case 0: r = v, g = t, b = p; break;
        case 1: r = q, g = v, b = p; break;
        case 2: r = p, g = v, b = t; break;
        case 3: r = p, g = q, b = v; break;
        case 4: r = t, g = p, b = v; break;
        case 5: r = v, g = p, b = q; break;
    }

    return {
        r: Math.round(r * 255),
        g: Math.round(g * 255),
        b: Math.round(b * 255)
    }
}

var get_bar_color = function() {
    var color = menu.GetColor("Global color")

    var palette = menu.GetValue("Palette")

    if (palette != 0) {
        var rgb_split_ratio = menu.GetValue("Fade split ratio") / 100

        var h = palette == 2 ?
            Globals.Realtime() * (menu.GetValue("Fade frequency") / 100) :
            menu.GetValue("Fade offset") / 1000

        color = hsv_to_rgb(h, 1, 1)
        color = [
            color.r * rgb_split_ratio, 
            color.g * rgb_split_ratio, 
            color.b * rgb_split_ratio
        ]
    }

    return color
}

var anti_aimbot = {
    get_desync: function() {
        var RealYaw = Local.GetRealYaw();
        var FakeYaw = Local.GetFakeYaw();
        var delta = Math.min(Math.abs(RealYaw - FakeYaw) / 2, 58).toFixed(1);

        return delta
    }
}

var menu = {
    Switch: function(name, state) {
        UI.AddCheckbox(name)
        UI.SetValue("Script items", name, state)
    },

    Hotkey: function(name) {
        return UI.AddHotkey(name)
    },

    SliderInt: function(name, default_value, min, max) {
        UI.AddSliderInt(name, min, max)
        UI.SetValue("Script items", name, default_value)
    },

    SliderFloat: function(name, default_value, min, max) {
        UI.AddSliderFloat(name, min, max)
        UI.SetValue("Script items", name, default_value)
    },

    ColorEdit: function(name, color) {
        UI.AddColorPicker(name)
        UI.SetColor("Script items", name, color)
    },

    Combo: function(name, elements) {
        return UI.AddDropdown(name, elements)
    },

    MultiCombo: function(name, elements) {
        return UI.AddMultiDropdown(name, elements)
    },

    Text: function(name) {
        return UI.AddLabel(name)
    },

    Block: function(name) {
        return UI.AddSliderFloat(name, 0, 0)
    },

    TextBox: function(name) {
        return UI.AddTextbox(name)
    },

    SetVisible: function(name, state) {
        return UI.SetEnabled("Script items", name, state)
    },

    GetValue: function(name) {
        return UI.GetValue("Script items", name)
    },

    GetColor: function(name) {
        return UI.GetColor("Script items", name)
    },

    SetValue: function(name, value) {
        return UI.SetValue("Script items", name, value)
    },

    DropdownValue: function(value, index) {
        var mask = 1 << index;
        return value & mask ? true : false;
    }
}

var menu_palette = ["Solid", "Fade", "Dynamic fade"]
var menu_elements = ["Watermark", "Frequency update info", "Anti-aimbot indication"]

menu.Block("")

menu.MultiCombo("Elements", menu_elements)
menu.Combo("Palette", menu_palette)
menu.ColorEdit("Global color", [142, 165, 229, 85])

menu.Block("  ")
menu.SliderInt("Fade offset", 825, 1, 1000)
menu.SliderInt("Fade frequency", 10, 1, 100)
menu.SliderInt("Fade split ratio", 100, 0, 100)

menu.Block(" ")
menu.TextBox("Watermark name")
menu.TextBox("Watermark prefix")
menu.TextBox("Watermark suffix")
menu.SliderInt("HZ", 60, 1, 360)

menu.Block("")

var fonts = function(size, h) {
    return {
        verdana: Render.AddFont("Verdana", size == undefined ? 7 : size, h == undefined ? 400 : h)  
    }
}

var ms_classes = {
    position: {
        offset: 0,

        g_paint_handler: function() {
            ms_classes.position.offset = 0
        }
    },

    watermark: {
        width: 0,
        x: Global.GetScreenSize()[0],

        alpha: 0,

        offset: 0,

        g_paint_handler: function() {
            ms_classes.watermark.offset = easing.lerp(ms_classes.watermark.offset, ms_classes.position.offset, Globals.Frametime() * 8)
            var off = ms_classes.watermark.offset
            if (menu.DropdownValue(menu.GetValue("Elements"), 0)) {
                ms_classes.watermark.alpha = easing.lerp(ms_classes.watermark.alpha, 1, Globals.Frametime() * 12)
                ms_classes.position.offset++
            } else {
                ms_classes.watermark.alpha = easing.lerp(ms_classes.watermark.alpha, 0, Globals.Frametime() * 12)
            }     

            if (ms_classes.watermark.alpha == 0)
                return   

            var font = fonts().verdana
            var today = new Date()
            today = today.toTimeString().substring(0, 8)  
            var color = get_bar_color()

            var actual_time = String.format("{0}", today)
            var prefix = "onetap"
            var suffix = ""
            var nickname = Cheat.GetUsername()

            if (UI.GetString("Script items", "Watermark name") != 0) {
                nickname = UI.GetString("Script items", "Watermark name")
            }

            if (UI.GetString("Script items", "Watermark prefix") != 0) {
                prefix = UI.GetString("Script items", "Watermark prefix")
            }

            if (UI.GetString("Script items", "Watermark suffix") != 0) {
               prefix +=  " [" + UI.GetString("Script items", "Watermark suffix") + "]"
            }

            if (typeof prefix == "Symbol") {
                prefix = prefix.toString();
                prefix = prefix.replace("Symbol(")
                prefix = prefix.replace(")")
            }

            if (typeof nickname == "Symbol") {
                nickname = nickname.toString();
                nickname = nickname.replace("Symbol(")
                nickname = nickname.replace(")")
            }

            var text = ""

            if (!World.GetServerString()) {
                text = String.format("{0} | {1} | {2}", prefix, nickname, actual_time)
            } else {
                text = String.format("{0} | {1} | delay: {2}ms | {3}tick | {4}", prefix, nickname, Math.floor(Entity.GetProp(Entity.GetLocalPlayer(), "CPlayerResource", "m_iPing")), Globals.Tickrate(), today)
            }

            ms_classes.watermark.width = easing.lerp(ms_classes.watermark.width, Render.TextSizeCustom(text, font)[0], Globals.Frametime() * 12)
            ms_classes.watermark.x = easing.lerp(ms_classes.watermark.x, Global.GetScreenSize()[0] - ms_classes.watermark.width - 14, Globals.Frametime() * 8)

            if (menu.GetValue("Palette") == 0) {
                Render.FilledRect(ms_classes.watermark.x - 4, 8 + 22 * off, ms_classes.watermark.width + 8, 2, [color[0], color[1], color[2], 255 * ms_classes.watermark.alpha])
            } else {
                Render.GradientRect(ms_classes.watermark.x - 4, 8 + 22 * off, Math.floor((ms_classes.watermark.width + 8) / 2), 2, 1, [color[1], color[2], color[0], 255 * ms_classes.watermark.alpha], [color[0], color[1], color[2], 255 * ms_classes.watermark.alpha])
                Render.GradientRect(ms_classes.watermark.x - 4 + Math.floor((ms_classes.watermark.width + 8) / 2), 8 + 22 * off, Math.floor((ms_classes.watermark.width + 8) / 2) + 1, 2, 1, [color[0], color[1], color[2], 255 * ms_classes.watermark.alpha], [color[2], color[0], color[1], 255 * ms_classes.watermark.alpha])
            }

            Render.FilledRect(ms_classes.watermark.x - 4, 10 + 22 * off, Math.floor(ms_classes.watermark.width + 8), 17, [17, 17, 17, (255 * ms_classes.watermark.alpha) * (menu.GetColor("Global color")[3] / 255)])

            Render.StringCustom(ms_classes.watermark.x, 11 + 22 * off, 0, text, [255, 255, 255, 255 * ms_classes.watermark.alpha], font)
        }
    },

    antiaim: {
        delta: 0,

        last_set: 0,
        old_time: 0,
        choked_time: 0,
        sim_time: 0,
        ticks: 0,
        choked_ticks_arr: [],

        width_1: 0,
        width_2: 0,

        alpha: 0,

        x_1: Global.GetScreenSize()[0],
        x_2: Global.GetScreenSize()[0],

        offset: 0,

        Arc: function(x, y, radius, start_angle, percent, thickness, color) {
            var precision = (2 * Math.PI) / 30;
            var step = Math.PI / 180;
            var inner = radius - thickness;
            var end_angle = (start_angle + percent) * step;
            var start_angle = (start_angle * Math.PI) / 180;

            for (; radius > inner; --radius) {
                for (var angle = start_angle; angle < end_angle; angle += precision) {
                    var cx = Math.round(x + radius * Math.cos(angle));
                    var cy = Math.round(y + radius * Math.sin(angle));

                    var cx2 = Math.round(x + radius * Math.cos(angle + precision));
                    var cy2 = Math.round(y + radius * Math.sin(angle + precision));

                    Render.Line(cx, cy, cx2, cy2, color);
                }
            }
        },

        g_paint_handler: function() {
            if (!World.GetServerString()) return;
            if (!Entity.IsAlive(Entity.GetLocalPlayer())) return;
            ms_classes.antiaim.offset = easing.lerp(ms_classes.antiaim.offset, ms_classes.position.offset, Globals.Frametime() * 8)
            var off = ms_classes.antiaim.offset
            if (menu.DropdownValue(menu.GetValue("Elements"), 2)) {
                ms_classes.antiaim.alpha = easing.lerp(ms_classes.antiaim.alpha, 1, Globals.Frametime() * 12)
                ms_classes.position.offset++
            } else {
                ms_classes.antiaim.alpha = easing.lerp(ms_classes.antiaim.alpha, 0, Globals.Frametime() * 12)
            } 

            if (ms_classes.antiaim.alpha == 0)
                return

            var body_yaw = anti_aimbot.get_desync()
            ms_classes.antiaim.delta = easing.lerp(ms_classes.antiaim.delta, body_yaw, Globals.Frametime() * 8)

            var sim_time = Entity.GetProp(Entity.GetLocalPlayer(), "CBaseEntity", "m_flSimulationTime");
            var length = 1

            ms_classes.antiaim.choked_time = sim_time - ms_classes.antiaim.old_time;

            if (sim_time != ms_classes.antiaim.old_time) {
                ms_classes.antiaim.ticks = 0;
                ms_classes.antiaim.old_time = sim_time;
                ms_classes.antiaim.ticks = ms_classes.antiaim.choked_time;
                ms_classes.antiaim.choked_ticks_arr.push(Math.round(ms_classes.antiaim.ticks/(1/Globals.Tickrate())));
                ms_classes.antiaim.choked_time = 0;
            }

            if(ms_classes.antiaim.choked_ticks_arr.length > length) {
                ms_classes.antiaim.choked_ticks_arr.shift();
            }

            str = "";

            for (t = 0; t < ms_classes.antiaim.choked_ticks_arr.length; t++) {
                if(ms_classes.antiaim.choked_ticks_arr[t] > 16)
                    continue;
                str += ms_classes.antiaim.choked_ticks_arr[t];

                if(t != ms_classes.antiaim.choked_ticks_arr.length - 1) {
                    str += " - ";
                }
            }

            var font = fonts().verdana

            var addr = Exploit.GetCharge() == 1 ? " | SHIFTING " : ""
            var text = String.format("FL: {0}{1} ", str - 1, addr)

            var y = 13
            ms_classes.antiaim.width_1 = easing.lerp(ms_classes.antiaim.width_1, Render.TextSizeCustom(text, font)[0], Globals.Frametime() * 12)
            ms_classes.antiaim.x_1 = easing.lerp(ms_classes.antiaim.x_1, Global.GetScreenSize()[0] - 10 - ms_classes.antiaim.width_1, Globals.Frametime() * 8)

            var c = [180, 190, 190]
            if (Exploit.GetCharge() == 1)
                c = [255, 150, 0]

            Render.GradientRect(ms_classes.antiaim.x_1 - 5, y + 16 + 22 * off, Math.floor((ms_classes.antiaim.width_1) / 2), 1, 1, [c[0], c[1], c[2], 0 * ms_classes.antiaim.alpha], [c[0], c[1], c[2], 255 * ms_classes.antiaim.alpha])
            Render.GradientRect(ms_classes.antiaim.x_1 - 5 + Math.floor((ms_classes.antiaim.width_1) / 2), y + 16 + 22 * off, Math.floor((ms_classes.antiaim.width_1 + 8) / 2), 1, 1, [c[0], c[1], c[2], 255 * ms_classes.antiaim.alpha], [c[0], c[1], c[2], 0 * ms_classes.antiaim.alpha])

            Render.FilledRect(ms_classes.antiaim.x_1 - 4, y + 22 * off, Math.floor(ms_classes.antiaim.width_1 + 4), 17, [17, 17, 17, 100 * ms_classes.antiaim.alpha])
            Render.StringCustom(ms_classes.antiaim.x_1, y + 1 + 22 * off, 0, text, [255, 255, 255, 255 * ms_classes.antiaim.alpha], font)

            var add_text = (body_yaw <= 0) ? "" : "\x20\x20\x20\x20\x20"
            var f_text = String.format("{0}FAKE ({1} )", add_text, body_yaw)
            var color_fake = [170 + (154 - 186) * body_yaw / 58, 0 + (255 - 0) * body_yaw / 58, 16 + (0 - 16) * body_yaw / 58, 255 * ms_classes.antiaim.alpha]

            ms_classes.antiaim.width_2 = easing.lerp(ms_classes.antiaim.width_2, Render.TextSizeCustom(f_text, font)[0], Globals.Frametime() * 12)
            ms_classes.antiaim.x_2 = easing.lerp(ms_classes.antiaim.x_2, Global.GetScreenSize()[0] - 10 - ms_classes.antiaim.width_2, Globals.Frametime() * 8)

            Render.GradientRect((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 25 - 2, y - 1 + 22 * off, ms_classes.antiaim.width_2 / 2 + 4, 17, 1, [17, 17, 17, 25 * ms_classes.antiaim.alpha], [17, 17, 17, 100 * ms_classes.antiaim.alpha])
            Render.GradientRect((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 25 - 2 + ms_classes.antiaim.width_2 / 2 + 4, y - 1 + 22 * off, ms_classes.antiaim.width_2 / 2, 17, 1, [17, 17, 17, 100 * ms_classes.antiaim.alpha], [17, 17, 17, 25 * ms_classes.antiaim.alpha])

            Render.StringCustom((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 25, y + 1 + 22 * off, 0, f_text, [255, 255, 255, 255 * ms_classes.antiaim.alpha], font)
            Render.Circle(((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 31) + Render.TextSizeCustom(f_text, font)[0], 18 + 22 * off, 1, [255, 255, 255, 255 * ms_classes.antiaim.alpha])

            Render.GradientRect((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 30, y - 1 + 22 * off, 2, 17 / 2, 0, [color_fake[0], color_fake[1], color_fake[2], 0 * ms_classes.antiaim.alpha], [color_fake[0], color_fake[1], color_fake[2], 255 * ms_classes.antiaim.alpha]);
            Render.GradientRect((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 30, y + 1 + 22 * off + 17 / 2 - 4, 2, 17 / 2, 0, [color_fake[0], color_fake[1], color_fake[2], 255 * ms_classes.antiaim.alpha], [color_fake[0], color_fake[1], color_fake[2], 0 * ms_classes.antiaim.alpha]);

            ms_classes.antiaim.Arc((ms_classes.antiaim.x_2 - ms_classes.antiaim.width_1) - 25 + 5, y + 7 + 22 * off, 5, 0, ms_classes.antiaim.delta * 6, 2, [89, 119, 239, 255 * ms_classes.antiaim.alpha]);
        }
    },

    ilstate: {
        frequency: 0,
        request_time: Globals.Curtime(),
        frametime: Globals.Frametime(),
        frametimes: [],

        width_1: 0,
        width_2: 0,

        height: [],
        alpha: 0,
        ms_text: 0,

        x_1: Global.GetScreenSize()[0],
        x_2: Global.GetScreenSize()[0],

        offset: 0,

        g_paint_handler: function() {
            if (menu.DropdownValue(menu.GetValue("Elements"), 1)) {
                ms_classes.ilstate.alpha = easing.lerp(ms_classes.ilstate.alpha, 1, Globals.Frametime() * 12)
            } else {
                ms_classes.ilstate.alpha = easing.lerp(ms_classes.ilstate.alpha, 0, Globals.Frametime() * 12)
            }

            if (ms_classes.ilstate.alpha == 0)
                return

            var font = fonts().verdana

            if (ms_classes.ilstate.request_time + 1 < Globals.Curtime()) {
                ms_classes.ilstate.frametime = Globals.Frametime()
                ms_classes.ilstate.request_time = Globals.Curtime()
                ms_classes.ilstate.frametimes.unshift(ms_classes.ilstate.frametime)

                if (ms_classes.ilstate.frametimes.length > 4)
                    ms_classes.ilstate.frametimes.pop()
            }

            ms_classes.ilstate.offset = easing.lerp(ms_classes.ilstate.offset, ms_classes.position.offset, Globals.Frametime() * 8)
            var off = ms_classes.ilstate.offset

            var io_text = "IO | "
            ms_classes.ilstate.ms_text = easing.lerp(ms_classes.ilstate.ms_text, Math.abs((ms_classes.ilstate.frametime * 1000)), Globals.Frametime() * 8)
            ms_classes.ilstate.frequency = menu.GetValue("HZ")
            var freq_text = String.format("{0}ms / {1}hz", ms_classes.ilstate.ms_text.toFixed(1), ms_classes.ilstate.frequency)

            var y = menu.DropdownValue(menu.GetValue("Elements"), 0) ? 4 : 8
            ms_classes.ilstate.width_1 = easing.lerp(ms_classes.ilstate.width_1, Render.TextSizeCustom(io_text, font)[0] + 24, Globals.Frametime() * 12)
            ms_classes.ilstate.x_1 = easing.lerp(ms_classes.ilstate.x_1, Global.GetScreenSize()[0] - 24 - ms_classes.ilstate.width_1 - Render.TextSizeCustom(freq_text, font)[0], Globals.Frametime() * 8)
        
            Render.FilledRect(ms_classes.ilstate.x_1 - 4, y + 28 * off, Math.floor(ms_classes.ilstate.width_1 + 4), 17, [17, 17, 17, 100 * ms_classes.ilstate.alpha])
            Render.StringCustom(ms_classes.ilstate.x_1, y + 1 + 28 * off, 0, io_text, [255, 255, 255, 255 * ms_classes.ilstate.alpha], font)

            for (var i in ms_classes.ilstate.frametimes) {
                var ft = ms_classes.ilstate.frametimes[i]
                var color = menu.GetColor("Global color")

                if (ms_classes.ilstate.height[i] == null) { ms_classes.ilstate.height[i] = 0 }
                ms_classes.ilstate.height[i] = easing.lerp(ms_classes.ilstate.height[i], Math.floor(Math.min(12, ft / 1 * 1000)), Globals.Frametime() * 8)

                Render.GradientRect(ms_classes.ilstate.x_1 + ms_classes.ilstate.width_1 - 9 - (5 * i), y + 28 * off + 14 - ms_classes.ilstate.height[i], 5, ms_classes.ilstate.height[i], 0, [color[0], color[1], color[2], 0 * ms_classes.ilstate.alpha], [color[0], color[1], color[2], 255 * ms_classes.ilstate.alpha])
            }

            ms_classes.ilstate.width_2 = easing.lerp(ms_classes.ilstate.width_2, Render.TextSizeCustom(freq_text, font)[0], Globals.Frametime() * 12)
            ms_classes.ilstate.x_2 = easing.lerp(ms_classes.ilstate.x_2, Global.GetScreenSize()[0] - 10 - ms_classes.ilstate.width_2 - 4, Globals.Frametime() * 8)

            var color = [0, 255, 0]
            var ft = ms_classes.ilstate.frametime * 1000
            if (ft > 15)
                color = [255, 0, 0]
            else if (ft > 12)
                color = [255, 170, 0]
            else if (ft > 10)
                color = [255, 255, 0]
            else if (ft > 7.5)
                color = [150, 255, 0]
            else if (ft > 5)
                color = [70, 255, 0]

            Render.FilledRect(ms_classes.ilstate.x_2 - 4, y + 28 * off, Math.floor(ms_classes.ilstate.width_2 + 8), 17, [17, 17, 17, 100 * ms_classes.ilstate.alpha])
            Render.StringCustom(ms_classes.ilstate.x_2, y + 1 + 28 * off, 0, freq_text, [255, 255, 255, 255 * ms_classes.ilstate.alpha], font)

            Render.GradientRect(ms_classes.ilstate.x_2 - 3, y + 17 + 28 * off, ms_classes.ilstate.width_2 / 2 + 4, 1, 1, color.concat(0), color.concat(255 * ms_classes.ilstate.alpha))
            Render.GradientRect(ms_classes.ilstate.x_2 + ms_classes.ilstate.width_2 / 2, y + 17 + 28 * off, ms_classes.ilstate.width_2 / 2 + 4, 1, 1, color.concat(255 * ms_classes.ilstate.alpha), color.concat(0))
        }
    },

    menu_set: {
        g_paint_handler: function() {
            var palette = menu.GetValue("Palette")
            var elements = menu.GetValue("Elements")

            if (palette != 0) {
                menu.SetVisible("Global color", false)
                menu.SetVisible("Fade offset", true)
                menu.SetVisible("Fade frequency", true)
                menu.SetVisible("Fade split ratio", true)
                menu.SetVisible("  ", true)
            } else {
                menu.SetVisible("  ", false)
                menu.SetVisible("Global color", true)
                menu.SetVisible("Fade offset", false)
                menu.SetVisible("Fade frequency", false)
                menu.SetVisible("Fade split ratio", false)     
            }

            if (menu.DropdownValue(elements, 0)) {
                menu.SetVisible(" ", true)
                menu.SetVisible("Watermark name", true)
                menu.SetVisible("Watermark suffix", true)
                menu.SetVisible("Watermark prefix", true)
            } else {
                menu.SetVisible(" ", false)
                menu.SetVisible("Watermark name", false)
                menu.SetVisible("Watermark suffix", false)
                menu.SetVisible("Watermark prefix", false)
            }

            if (menu.DropdownValue(elements, 1)) {
                menu.SetVisible("HZ", true)
            } else {
                menu.SetVisible("HZ", false)
            }           
        }
    }
}
Cheat.RegisterCallback("Draw", "ms_classes.position.g_paint_handler")
Cheat.RegisterCallback("Draw", "ms_classes.watermark.g_paint_handler")
Cheat.RegisterCallback("Draw", "ms_classes.antiaim.g_paint_handler")
Cheat.RegisterCallback("Draw", "ms_classes.ilstate.g_paint_handler")
Cheat.RegisterCallback("Draw", "ms_classes.menu_set.g_paint_handler")