Zaloguj się by uzyskać pełen dostęp. Nie masz jeszcze konta? Założ je już teraz w kilka sekund.

Wysłany: 2020-03-15, 19:26


Mazeusz







Wiek: 31
Na forum: 2814 dni
Posty: 52
Nick w MP: Mazeusz*



Respekt: 50

Ostrzeżeń: 80%
Witam chcia?bym zrobi? tak interakcje ?e gdy pojazd przekroczy dany przebieg silnik nie odpali zrobi?em tak ale nadal odpala

c

local font = dxCreateFont("font.ttf", 14) or default-bold
local font2 = dxCreateFont("font.ttf", 16) or default-bold

local sw,sh = guiGetScreenSize();
local baseX = 1920;
local zoom = 1;
local minzoom = 2;
if sw < baseX then
    zoom = math.min(minzoom, baseX/sw);
end;

local selected = 1;
local tick = getTickCount();
local interaction = {};
local type_i = "join"

local tick_int = getTickCount();
local int = false;
local type = "join";

local a1,a2,a3 = 0,0,0;

local img = {
  ["car"] = dxCreateTexture("img/settings/car.png", "argb", false, "clamp"),
  ["click_off"] = dxCreateTexture("img/settings/click_on.png", "argb", false, "clamp"),
  ["click_on"] = dxCreateTexture("img/settings/click_off.png", "argb", false, "clamp"),

  ["engine"] = dxCreateTexture("img/engine.png", "argb", false, "clamp"),
  ["handbrake"] = dxCreateTexture("img/handbrake.png", "argb", false, "clamp"),
  ["leave"] = dxCreateTexture("img/leave.png", "argb", false, "clamp"),
  ["light"] = dxCreateTexture("img/light.png", "argb", false, "clamp"),
  ["lock"] = dxCreateTexture("img/lock.png", "argb", false, "clamp"),
  ["settings"] = dxCreateTexture("img/settings.png", "argb", false, "clamp"),
  ["reload"] = dxCreateTexture("img/reload.png", "argb", false, "clamp"),
};

function isMouseIn(x, y, w, h)
    if not isCursorShowing() then return end

    local pos = {getCursorPosition()}
    pos[1],pos[2] = (pos[1]*sw),(pos[2]*sh)

    if pos[1] >= x and pos[1] <= (x+w) and pos[2] >= y and pos[2] <= (y+h) then
        return true
    end
    return false
end

function isEventHandlerAdded( sEventName, pElementAttachedTo, func )
        local aAttachedFunctions = getEventHandlers( sEventName, pElementAttachedTo )
        if #aAttachedFunctions > 0 then
            for i, v in ipairs( aAttachedFunctions ) do
                if v == func then
                    return true
                end
            end
        end

    return false
end

local selected_option = {
  function(veh, option, trigger)
    if trigger then
      if option == 1 then
        return "switchLIGHT"
      elseif option == 2 then
        return "switchENGINE"
      elseif option == 3 then
        return "switchHANDBRAKE"
      elseif option == 4 then
        return "kickOCCUPANTS"
      elseif option == 5 then
        return "changeLOCKED"
      elseif option == 7 then
        return "changeTYPE"
      end
    else
      if option == 1 then
        return getVehicleOverrideLights(veh) == 1 and "Odpal lampy" or "Zga? lampy"
      elseif option == 2 then
        return getVehicleEngineState(veh) == true and "Zga? silnik" or "Odpal silnik"
      elseif option == 3 then
        return getElementData(veh, "vehicle:handbrake") and "Spu?? r?czny" or "Zaci?gnij r?czny"
      elseif option == 4 then
        return "Wysad? pasa?er?w"
      elseif option == 5 then
        return isVehicleLocked(veh) == true and "Otw?rz zamek" or "Zamknij zamek"
      elseif option == 6 then
        return "Wi?cej opcji"
      elseif option == 7 then
        return getElementData(veh, "vehicle:actualType") == "LPG" and "Prze??cz na benzyne" or "Prze??cz na gaz"
      end
    end
  end
}

bindKey("lshift", "both", function(_, state)
    local veh = getPedOccupiedVehicle(localPlayer)
  if not veh then return end
  if getElementData(veh, "vehicle.selling") then return end

    if getVehicleController(veh) ~= localPlayer then return end
  if getVehicleName(veh) == "Bike" or getVehicleName(veh) == "BMX" or getVehicleName(veh) == "Mountain Bike" then return end

  if state == "up" then
    if selected == 6 then
      if not int then
        addEventHandler("onClientRender", root, gui)
        addEventHandler("onClientClick", root, clicked)
        addEventHandler("onClientKey", root, key)

        showCursor(true, false)

        tick_int = getTickCount()
        type = "join"
      end
    else
      triggerServerEvent(selected_option[1](veh, selected, true), resourceRoot, veh)
    end

    type_i = "quit";
    tick = getTickCount();

    unbindKey("arrow_r", "down", down)
    unbindKey("mouse_wheel_down", "down", down)
    unbindKey("arrow_l", "down", up)
    unbindKey("mouse_wheel_up", "down", up)
  elseif(state == "down" and not isCursorShowing())then
    if(not isEventHandlerAdded("onClientRender", root, guiInter))then
      addEventHandler("onClientRender", root, guiInter)
    end;
    
    selected = 1;
    tick = getTickCount();
    type_i = "join";
    a1,a2,a3 = 0,0,0;

    bindKey("arrow_r", "down", down)
    bindKey("mouse_wheel_down", "down", down)
    bindKey("arrow_l", "down", up)
    bindKey("mouse_wheel_up", "down", up)
    end
end)

local tbl = {
  [1] = "light",
  [2] = "engine",
  [3] = "handbrake",
  [4] = "leave",
  [5] = "lock",
  [6] = "settings",
  [7] = "reload",
};

function guiInter()
    local v = getPedOccupiedVehicle(localPlayer)
    if not v then
    removeEventHandler("onClientRender", root, guiInter)

    unbindKey("arrow_r", "down", down)
    unbindKey("mouse_wheel_down", "down", down)
    unbindKey("arrow_l", "down", up)
    unbindKey("mouse_wheel_up", "down", up)
        return
  end

  if type_i == "join" then
    a1,a2,a3 = interpolateBetween(a1, a2, a3, 255, 100, 200, (getTickCount()-tick)/500, "Linear");
  elseif type_i == "quit" then
    a1,a2,a3 = interpolateBetween(a1, a2, a3, 0, 0, 0, (getTickCount()-tick)/500, "Linear");

    if(a1 == 0)then
      removeEventHandler("onClientRender", root, guiInter);
    end;
  end;

  dxDrawRectangle(0, 0, sw, sh, tocolor(15, 15, 15, a3), false)
  
  local max = getElementData(v, "vehicle:type") == "LPG" and 7 or 6;
  local x = (960/zoom) - (32/zoom);
  local y = (540/zoom) - (82/zoom);

  if(selected > 1 and selected < max)then
    dxDrawImage(x+100/zoom, y, 64/zoom, 64/zoom, img[tbl[selected+1]], 0, 0, 0, tocolor(255, 255, 255, a2), false);
    dxDrawImage(x, y, 64/zoom, 64/zoom, img[tbl[selected]], 0, 0, 0, tocolor(255, 255, 255, a1), false);
    dxDrawImage(x-100/zoom, y, 64/zoom, 64/zoom, img[tbl[selected-1]], 0, 0, 0, tocolor(255, 255, 255, a2), false);
  elseif(selected == 1)then
    dxDrawImage(x+100/zoom, y, 64/zoom, 64/zoom, img[tbl[2]], 0, 0, 0, tocolor(255, 255, 255, a2), false);
    dxDrawImage(x, y, 64/zoom, 64/zoom, img[tbl[1]], 0, 0, 0, tocolor(255, 255, 255, a1), false);
  elseif(selected == max)then
    dxDrawImage(x, y, 64/zoom, 64/zoom, img[tbl[selected]], 0, 0, 0, tocolor(255, 255, 255, a1), false);
    dxDrawImage(x-100/zoom, y, 64/zoom, 64/zoom, img[tbl[selected-1]], 0, 0, 0, tocolor(255, 255, 255, a2), false);
  end;

  dxDrawText(selected_option[1](v, selected), 1, 10/zoom+1, sw+1, sh+1, tocolor(0, 0, 0, a1), 1, font, "center", "center", false, false, true, true)
  dxDrawText(selected_option[1](v, selected), 0, 10/zoom, sw, sh, tocolor(255, 255, 255, a1), 1, font, "center", "center", false, false, true, true)
end;

function gui()
    local v = getPedOccupiedVehicle(localPlayer)
    if not v then
    tick_int = getTickCount()
    type = "quit"

    showCursor(false)
        return
    end

  if type == "join" then
    a = interpolateBetween(0, 0, 0, 255, 0, 0, (getTickCount()-tick_int)/500, "Linear")

    if a == 255 then
        int = false
    else
        int = true
    end
  elseif type == "quit" then
    a = interpolateBetween(255, 0, 0, 0, 0, 0, (getTickCount()-tick_int)/500, "Linear")

    if a == 0 then
        int = false

        removeEventHandler("onClientRender", root, gui)
        removeEventHandler("onClientClick", root, clicked)
        removeEventHandler("onClientKey", root, key)
    else
        int = true
    end
  end

  dxDrawRectangle(0, 0, sw, sh, tocolor(15, 15, 15, a > 200 and 200 or a), false)

  dxDrawText("Aby anulowa? kliknij dowolny klawisz.", 1, 20/zoom+1, sw+1, sh+1, tocolor(0, 0, 0, a), 1, font2, "center", "top", false, false, true, true, false)
  dxDrawText("Aby anulowa? kliknij dowolny klawisz.", 0, 20/zoom, sw, sh, tocolor(255, 255, 255, a), 1, font2, "center", "top", false, false, true, true, false)

  dxDrawImage(sw/2-650/2/zoom, sh/2-650/2/zoom, 650/zoom, 650/zoom, img["car"], 0, 0, 0, tocolor(255,30,30, a), false)

    if getVehicleDoorOpenRatio(v, 0) == 0 then -- maska
        dxImage(sw/2-50/2/zoom, 190/zoom, 50/zoom, 50/zoom, img["click_on"], a)
    else
        dxImage(sw/2-50/2/zoom, 190/zoom, 50/zoom, 50/zoom, img["click_off"], a)
  end

    if getVehicleDoorOpenRatio(v, 1) == 0 then -- bagaznik
        dxImage(sw/2-50/2/zoom, sh-(240/zoom), 50/zoom, 50/zoom, img["click_on"], a)
    else
        dxImage(sw/2-50/2/zoom, sh-(240/zoom), 50/zoom, 50/zoom, img["click_off"], a)
    end

    if getVehicleDoorOpenRatio(v, 2) == 0 then -- lewo przod
        dxImage(sw/2-190/zoom, sh-(564/zoom), 50/zoom, 50/zoom, img["click_on"], a)
    else
        dxImage(sw/2-190/zoom, sh-(564/zoom), 50/zoom, 50/zoom, img["click_off"], a)
    end

    if getVehicleDoorOpenRatio(v, 3) == 0 then -- prawo przod
        dxImage(sw/2+140/zoom, sh-(564/zoom), 50/zoom, 50/zoom, img["click_on"], a)
    else
        dxImage(sw/2+140/zoom, sh-(564/zoom), 50/zoom, 50/zoom, img["click_off"], a)
    end

    if getVehicleMaxPassengers(v) == 3 then
        if getVehicleDoorOpenRatio(v, 4) == 0 then -- lewy tyl
            dxImage(sw/2-190/zoom, sh-(500/zoom), 50/zoom, 50/zoom, img["click_on"], a)
        else
            dxImage(sw/2-190/zoom, sh-(500/zoom), 50/zoom, 50/zoom, img["click_off"], a)
        end

        if getVehicleDoorOpenRatio(v, 5) == 0 then -- prawy tyl
            dxImage(sw/2+140/zoom, sh-(500/zoom), 50/zoom, 50/zoom, img["click_on"], a)
        else
            dxImage(sw/2+140/zoom, sh-(500/zoom), 50/zoom, 50/zoom, img["click_off"], a)
        end
  end
end

function dxImage(x, y, w, h, img, a)
    if isMouseIn(x, y, w, h) and not int then
        dxDrawImage(x, y, w, h, img, 0, 0, 0, tocolor(255, 255, 255, 200), true)
    else
        dxDrawImage(x, y, w, h, img, 0, 0, 0, tocolor(255, 255, 255, a), true)
    end
end

function key(button, press)
  if button ~= "mouse1" and button ~= "mouse2" and press and not int then
    tick_int = getTickCount()
    type = "quit"

    showCursor(false)
  end
end

function clicked(btn, state)
    if btn ~= "state" and state ~= "down" then return end

    local v = getPedOccupiedVehicle(localPlayer)
    if not v then return end

    if isMouseIn(sw/2-50/2/zoom, 190/zoom, 50/zoom, 50/zoom) then
        triggerServerEvent("wiecejOpcji", resourceRoot, v, 1)
    elseif isMouseIn(sw/2-50/2/zoom, sh-(240/zoom), 50/zoom, 50/zoom) then
        triggerServerEvent("wiecejOpcji", resourceRoot, v, 2)
    elseif isMouseIn(sw/2-190/zoom, sh-(564/zoom), 50/zoom, 50/zoom) then
        triggerServerEvent("wiecejOpcji", resourceRoot, v, 3)
  elseif isMouseIn(sw/2+140/zoom, sh-(564/zoom), 50/zoom, 50/zoom) then
    triggerServerEvent("wiecejOpcji", resourceRoot, v, 4)
    elseif isMouseIn(sw/2-190/zoom, sh-(500/zoom), 50/zoom, 50/zoom) and getVehicleMaxPassengers(v) == 3 then
        triggerServerEvent("wiecejOpcji", resourceRoot, v, 5)
    elseif isMouseIn(sw/2+140/zoom, sh-(500/zoom), 50/zoom, 50/zoom) and getVehicleMaxPassengers(v) == 3 then
        triggerServerEvent("wiecejOpcji", resourceRoot, v, 6)
    end
end

function up()
  tick = getTickCount()
  selected = math.max(selected - 1, 1)
end

function down()
  local v = getPedOccupiedVehicle(localPlayer)
  local max = getElementData(v, "vehicle:type") == "LPG" and 7 or 6

  tick = getTickCount()
  selected = math.min(selected + 1, max)
end
-----------
local function openWindow()
    local veh = getPedOccupiedVehicle(localPlayer)
    if veh then
        local vehType = getVehicleType(veh)
        if vehType ~= "Automobile" and vehType ~= "Monster Truck" then return end
        if getElementData(veh, "vehicle:mileage") then
        if tonumber(getElementData(veh, "vehicle:mileage")) >= 30000 then 
            outputChatBox("* Masz 30,000 przebiegu, Tw?j silnik nie odpali! Udaj si? na zerowanie!", localPlayer, 255, 0, 0)
            return 
        end
    end
        local seat = getPedOccupiedVehicleSeat(localPlayer)
        if seatWindows[seat] and getVehicleDoorState(veh,seat+2) < 2 then
            triggerServerEvent("openWindow",resourceRoot,veh,seat,not isVehicleWindowOpen(veh,seatWindows[seat]))
        end
    end
end

addEvent("windowOpened",true)
local function windowOpened(veh,seat,state)
    setVehicleWindowOpen(veh,seatWindows[seat],state)
end
addEventHandler("windowOpened",resourceRoot,windowOpened)

local function bindInteraction(plr,seat)
    if plr ~= localPlayer then return end
    veh = getPedOccupiedVehicle(plr)
    if getVehicleID(veh) == 605 and tonumber(getElementData(veh, "vehicle:mileage")) >= 500 then 
        outputChatBox("#ff0000&#10008; #ffffff- Twoj pojazd posiada niewymieniony zbiornik, wymie? go aby odpali? silnik!", 255, 0, 0,true)
        return end 
        if getElementData(veh, "vehicle:mileage") then
        if tonumber(getElementData(veh, "vehicle:mileage")) >= 25000 then 
            outputChatBox("* Masz ju? ponad 25.000 przebiegu, je?li osi?gniesz 30.000 przebiegu - Tw?j silnik nie odpali!", 255, 0, 0) end 
        end
    bindKey("lshift","down",openWindow)
    if seat == 0 then
        
        bindKey("lshift","both",wlaczInterakcje)
    end
end
addEventHandler("onClientVehicleEnter",root,bindInteraction)


db3 https://imgur.com/PXpB57k

Postaw piwo autorowi tego posta
 

 
Wysłany: 2020-03-15, 19:31


P.Wiśnia

Programista LUA






Wiek: 25
Na forum: 4185 dni
Posty: 568
Nick w MP: P.Wiśnia

Piwa: 378

Respekt: 100
Respekt: 100

Ja w tym co podes?a?e? nie widz? funkcji na w??czenie silnika.

Postaw piwo autorowi tego posta
 

 
Wysłany: 2020-03-15, 19:44


Mazeusz







Wiek: 31
Na forum: 2814 dni
Posty: 52
Nick w MP: Mazeusz*



Respekt: 50

Ostrzeżeń: 80%
Serwer


local tick = {}


addEvent("switchENGINE", true)
addEventHandler("switchENGINE", resourceRoot, function(veh)
    setVehicleEngineState(veh, not getVehicleEngineState(veh))

    if not tick[client] or tick[client] and (getTickCount() - tick[client]) > 3000 then
        tick[client] = getTickCount()
    elseif tick[client] and (getTickCount() - tick[client]) < 3000 then
        return
    end
    
    local text = getVehicleEngineState(veh) ~= true and "gasi" or "odpala"
end)

addEvent("switchLIGHT", true)
addEventHandler("switchLIGHT", resourceRoot, function(veh)
    setVehicleOverrideLights(veh, (getVehicleOverrideLights(veh) == 2 and 1 or 2))
end)

addEvent("switchHANDBRAKE", true)
addEventHandler("switchHANDBRAKE", resourceRoot, function(veh, _)
        if getElementData(veh, "vehicle:handbrake") and not _ then
            setControlState(client, "handbrake", false)
            setElementData(veh, "vehicle:handbrake", false)
            setElementFrozen(veh, false)

            if not tick[client] or tick[client] and (getTickCount() - tick[client]) > 3000 then
                tick[client] = getTickCount()
            elseif tick[client] and (getTickCount() - tick[client]) < 3000 then
                return
            end
        else
            setControlState(client, "handbrake", true)
            setElementData(veh, "vehicle:handbrake", true)
            setElementFrozen(veh, true)

            if not tick[client] or tick[client] and (getTickCount() - tick[client]) > 3000 then
                tick[client] = getTickCount()
            elseif tick[client] and (getTickCount() - tick[client]) < 3000 then
                return
            end
    end
end)

addEvent("changeLOCKED", true)
addEventHandler("changeLOCKED", resourceRoot, function(veh)
    if isVehicleLocked(veh) == true then
        setVehicleLocked(veh, false)

        if not tick[client] or tick[client] and (getTickCount() - tick[client]) > 3000 then
            tick[client] = getTickCount()
        elseif tick[client] and (getTickCount() - tick[client]) < 3000 then
            return
        end

    else
        for i = 0,5 do
            setVehicleDoorOpenRatio(veh, i, 0, 2500)
        end

        setVehicleLocked(veh, true)

        if not tick[client] or tick[client] and (getTickCount() - tick[client]) > 3000 then
            tick[client] = getTickCount()
        elseif tick[client] and (getTickCount() - tick[client]) < 3000 then
            return
        end

    end
end)

addEvent("changeTYPE", true)
addEventHandler("changeTYPE", resourceRoot, function(veh)
    local newType = getElementData(veh, "vehicle:actualType") == "Benzyna" and "LPG" or "Benzyna"
    setElementData(veh, "vehicle:actualType", newType)
end)

addEvent("kickOCCUPANTS", true)
addEventHandler("kickOCCUPANTS", resourceRoot, function(veh)
    local occupants = getVehicleOccupants(veh)
    for i,v in pairs(occupants) do
        if v ~= client then
            setControlState(v, "enter_exit", true)
            setTimer(function()
                setControlState(v, "enter_exit", false)
            end, 200, 1)

            if not tick[client] or tick[client] and (getTickCount() - tick[client]) > 3000 then
                tick[client] = getTickCount()
            elseif tick[client] and (getTickCount() - tick[client]) < 3000 then
                return
            end

        end
    end
end)

addEventHandler("onVehicleEnter", root, function(player, seat)
    if seat ~= 0 then return end

    if getElementData(source, "vehicle:handbrake") then
        setControlState(player, "handbrake", true)
        setElementFrozen(source, false)
    end

    if getVehicleName(source) == "Bike" or getVehicleName(source) == "BMX" or getVehicleName(source) == "Mountain Bike" then
        setVehicleEngineState(source, true)
        setElementData(source, "vehicle:handbrake", false)
        setControlState(player, "handbrake", false)
    end
end)

addEventHandler("onVehicleStartEnter", root, function(player, seat)
    if seat ~= 0 then return end
    
    if getVehicleController(source) == player then
        setVehicleLocked(source, false)
    end
end)

addEventHandler("onVehicleExit", root, function(player, seat)
    for i = 0,5 do
        if i == 2 then
            setVehicleDoorOpenRatio(source, i, 0, 1000)
        end
    end

    if seat == 0 and getElementData(source, "vehicle:handbrake") then
        setControlState(player, "handbrake", false)
        setElementFrozen(source, true)
        setVehicleLocked(source, false)
    end
end)

addEvent("wiecejOpcji", true)
addEventHandler("wiecejOpcji", resourceRoot, function(veh, x)
    if x == 1 then
        if getVehicleDoorOpenRatio(veh, 0) == 0 then
            setVehicleDoorOpenRatio(veh, 0, 1, 500)
        else
            setVehicleDoorOpenRatio(veh, 0, 0, 500)
        end
    elseif x == 2 then
        if getVehicleDoorOpenRatio(veh, 1) == 0 then
            setVehicleDoorOpenRatio(veh, 1, 1, 500)
        else
            setVehicleDoorOpenRatio(veh, 1, 0, 500)
        end
    elseif x == 3 then
        if getVehicleDoorOpenRatio(veh, 2) == 0 then
            setVehicleDoorOpenRatio(veh, 2, 1, 500)
        else
            setVehicleDoorOpenRatio(veh, 2, 0, 500)
        end
    elseif x == 4 then
        if getVehicleDoorOpenRatio(veh, 3) == 0 then
            setVehicleDoorOpenRatio(veh, 3, 1, 500)
        else
            setVehicleDoorOpenRatio(veh, 3, 0, 500)
        end
    elseif x == 5 then
        if getVehicleDoorOpenRatio(veh, 4) == 0 then
            setVehicleDoorOpenRatio(veh, 4, 1, 500)
        else
            setVehicleDoorOpenRatio(veh, 4, 0, 500)
        end
    elseif x == 6 then
        if getVehicleDoorOpenRatio(veh, 5) == 0 then
            setVehicleDoorOpenRatio(veh, 5, 1, 500)
        else
            setVehicleDoorOpenRatio(veh, 5, 0, 500)
        end
    end
end)


Postaw piwo autorowi tego posta
 

 
Wysłany: 2020-03-15, 19:46


Wilq







Wiek: 24
Na forum: 4569 dni
Posty: 3409

Piwa: 739

Respekt: 1225,8
Respekt: 1225,8

Sprawdzaj przebieg w evencie switchENGINE.
Funkcje od wy??czenia silnika w poje?dzie ju? masz.

Postaw piwo autorowi tego posta
 

 
Wysłany: 2020-03-15, 20:09


Mazeusz







Wiek: 31
Na forum: 2814 dni
Posty: 52
Nick w MP: Mazeusz*



Respekt: 50

Ostrzeżeń: 80%
Nie wiem jak to zrobi? mo?esz co? dopowiedziec

Postaw piwo autorowi tego posta
 

 
Wysłany: 2020-03-15, 23:38


Wilq







Wiek: 24
Na forum: 4569 dni
Posty: 3409

Piwa: 739

Respekt: 1225,8
Respekt: 1225,8

Co tutaj jest niezrozumia?ego, musisz sprawdza? przebieg w evencie switchENGINE. Je?li jest wi?kszy od danej liczby musisz anulowa? reszt? kodu za pomoc? "return end".

Postaw piwo autorowi tego posta
 

 
Tagi: interakcja :: przebieg
Anonymous





Na forum: 245 dni
Posty: 1



Anonymous Koniecznie zajrzyj na:






Skocz do:  
Wyświetl posty z ostatnich:   
GTAONLINE.PL » JĘZYKI PROGRAMOWANIA » LUA » Interakcja, przebieg Odpowiedz do tematu

Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Dodaj temat do Ulubionych
Wersja do druku