diff --git a/OKAYY Framework Basic/kuz_ActionZones/client.lua b/OKAYY Framework Basic/kuz_ActionZones/client.lua new file mode 100644 index 0000000..701a451 --- /dev/null +++ b/OKAYY Framework Basic/kuz_ActionZones/client.lua @@ -0,0 +1,96 @@ +local timer = 0 + +function OnPackageStart() + timer = CreateTimer(Refresh, 500) +end +AddEvent("OnPackageStart", OnPackageStart) + +local cooldown = false +local action = nil +local attr = nil +local callType = nil +function OnKeyPress(key) + if key == "E" and action ~= nil and not cooldown and not GetPlayerPropertyValue(GetPlayerId(), 'cuffed') and not GetPlayerPropertyValue(GetPlayerId(), 'dead') then + + if callType == nil or callType == "server" then + if attr ~= nil then + CallRemoteEvent(action, attr) + else + CallRemoteEvent(action) + end + else + if attr ~= nil then + CallEvent(action, attr) + else + CallEvent(action) + end + end + cooldown = true + Delay(1000, function() + cooldown = false + end) + end +end +AddEvent("OnKeyPress", OnKeyPress) + + + +local last = false +function Refresh() + local got = false + + + local pickups = GetStreamedPickups() + local x,y,z = GetPlayerLocation() + for k,v in pairs(pickups) do + if GetPickupPropertyValue(v, "action") ~= nil then + local px,py,pz = GetPickupLocation(v) + if GetDistance3D(x,y,z,px,py,pz) <= GetPickupPropertyValue(v, "action_range") then + got = true + action = GetPickupPropertyValue(v, "action") + + if GetPickupPropertyValue(v, "action_attr") ~= nil then + attr = GetPickupPropertyValue(v, "action_attr") + end + + if GetPickupPropertyValue(v, "action_type") ~= nil then + callType = GetPickupPropertyValue(v, "action_type") + end + + CallEvent("KNotify:SendPress", GetPickupPropertyValue(v, "action_text")) + end + end + end + + + local objects = GetStreamedObjects() + local x,y,z = GetPlayerLocation() + for k,v in pairs(objects) do + if GetObjectPropertyValue(v, "action") ~= nil then + local px,py,pz = GetObjectLocation(v) + if GetDistance3D(x,y,z,px,py,pz) <= GetObjectPropertyValue(v, "action_range") then + got = true + action = GetObjectPropertyValue(v, "action") + + if GetObjectPropertyValue(v, "action_attr") ~= nil then + attr = GetObjectPropertyValue(v, "action_attr") + end + + if GetObjectPropertyValue(v, "action_type") ~= nil then + callType = GetObjectPropertyValue(v, "action_type") + end + + CallEvent("KNotify:SendPress", GetObjectPropertyValue(v, "action_text")) + end + end + end + + if not got and last then + CallEvent("KNotify:HidePress") + action = nil + attr = 0 + callType = nil + end + last = got + +end \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_ActionZones/package.json b/OKAYY Framework Basic/kuz_ActionZones/package.json new file mode 100644 index 0000000..67b5239 --- /dev/null +++ b/OKAYY Framework Basic/kuz_ActionZones/package.json @@ -0,0 +1,9 @@ +{ + "author": "Kuzkay", + "version": "1.0", + "server_scripts": [], + "client_scripts": [ + "client.lua" + ], + "files": [] +} diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/client.lua b/OKAYY Framework Basic/kuz_Essentials/atm/client.lua new file mode 100644 index 0000000..727a295 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/atm/client.lua @@ -0,0 +1,103 @@ +local ui = 0 +local inside = false +local last_check = false +local refreshTimer = 0 + +local Atms = nil + +local atmOpen = false + +local bank = 0 +local cash = 0 + +function AtmLoadedPlayer() + Delay(3000, function () + ui = Gui_main + Atms = Atm.atms + ExecuteWebJS(ui, "SetFields('"..bank.."','"..cash.."');") + refreshTimer = CreateTimer(CheckInAtm, 100) + end) +end +AddRemoteEvent("Kuzkay:LoadingComplete", AtmLoadedPlayer) + +function OpenAtm() + atmOpen = true + ExecuteWebJS(ui, "SetAmount('"..math.floor(cash).."');") + ExecuteWebJS(ui, "ToggleAtm(true);") + SetWebVisibility(ui, WEB_VISIBLE) + SetIgnoreLookInput(true) + SetIgnoreMoveInput(true) + ShowMouseCursor(true) + SetInputMode(INPUT_GAMEANDUI) +end +AddRemoteEvent('Kuzkay:AtmOpenUI', OpenAtm) + +function CloseAtm() + atmOpen = false + ExecuteWebJS(ui, "ToggleAtm(false);") + SetWebVisibility(ui, WEB_HITINVISIBLE) + SetIgnoreLookInput(false) + SetIgnoreMoveInput(false) + ShowMouseCursor(false) + SetInputMode(INPUT_GAME) +end +AddRemoteEvent('Kuzkay:AtmCloseUI', CloseAtm) + +function CheckInAtm() + + inside = false + local x,y,z = GetPlayerLocation() + local distance = 0 + + local currentAtm = 0 + + local i = 1 + for _ in pairs(Atms) do + if not inside then + if GetDistance3D(x,y,z,Atms[i].x, Atms[i].y, Atms[i].z) <= 120 then + distance = GetDistance3D(x,y,z,Atms[i].x, Atms[i].y, Atms[i].z) + inside = true + + CallEvent("KNotify:SendPress", "Press [E] to open atm") + + currentAtm = i + end + end + i = i + 1 + end + + if not inside or IsPlayerInVehicle() then + if atmOpen then + CloseAtm() + end + end + if last_check and not inside then + CallEvent("KNotify:HidePress") + end + last_check = inside +end + +function OnKeyPress(key) + if key == "E" and inside and not GetPlayerPropertyValue(GetPlayerId(), 'cuffed') and not GetPlayerPropertyValue(GetPlayerId(), 'dead') then + if atmOpen then + CloseAtm() + else + OpenAtm() + end + end +end +AddEvent("OnKeyPress", OnKeyPress) + +AddEvent("Kuzkay:OnWithdraw", function (amount) + CallRemoteEvent("Kuzkay:AtmWithdraw", amount) +end) +AddEvent("Kuzkay:OnDeposit", function (amount) + CallRemoteEvent("Kuzkay:AtmDeposit", amount) +end) + +function UpdateAtmData(money_, bank_, role, level, experience) + bank = bank_ + cash = money_ + ExecuteWebJS(ui, "SetFields('"..math.floor(bank).."','"..math.floor(cash).."');") +end +AddRemoteEvent("Kuzkay:UpdateVisualData", UpdateAtmData) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/config.lua b/OKAYY Framework Basic/kuz_Essentials/atm/config.lua new file mode 100644 index 0000000..52b3433 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/atm/config.lua @@ -0,0 +1,21 @@ +Atm = {} +Atm.atms = {} + + + +Atm.atms = { + + {x=-181944 ,y=-40246,z=1163}, + {x=129099,y=77949,z=1576}, + {x=-15091,y=-2416,z=2065}, + {x=43783,y=133267,z=1569}, + {x=42244,y=137938,z=1581}, + {x=-189247,y=-51745,z=1148}, + {x=212899,y=190039,z=1309}, + {x=213426,y=190578,z=1309} + +} + + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/gui/atm.css b/OKAYY Framework Basic/kuz_Essentials/atm/gui/atm.css new file mode 100644 index 0000000..8f92a19 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/atm/gui/atm.css @@ -0,0 +1,177 @@ +@font-face { + font-family: Yanone Kaffeesatz; + src: url('http://asset/kuz_Essentials/utils/Yanone.ttf'); +} +@font-face { + font-family: bebas-neue; + src: url('http://asset/kuz_Essentials/utils/Bebas.ttf'); +} +html, body{ + margin:0 auto; + overflow: hidden; + font-family: bebas-neue, sans-serif !important; + font-weight: 500; +} +.atm { + user-select: all; + display: none; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: absolute; + font-family: bebas-neue, sans-serif !important; + border-radius: 1vh; + color: white; + margin: 0; + overflow: hidden; + height: 55vh; + width: 50vh; + z-index: 0; + box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.6); + + background: linear-gradient(135deg, #f0f0f0 0%,#8a8a8a 100%); + user-select: none; +} +.topper{ + position: relative; + background: #520707; + width: 100%; + height: 20%; + margin-top: 0; + background-image: url("img/paydaybanking.png"); + background-repeat: no-repeat; + background-attachment: cover; + -webkit-background-size: cover; + -moz-background-size: cover; + -o-background-size: cover; + background-position: center; + background-position: right top; + border-bottom: 1px solid rgba(70,70,70,0.35); +} +.balance{ + position: relative; + width: 100%; + height: 35%; + margin-top: 0; + display: inline; + color: rgb(50,50,50); + text-align: left; + font-size: 3.3vh; +} +.balance div{ + position: relative; + margin-top: 4vh; + margin-left: 7.5%; + margin-right: 7.5%; + background: rgba(100,100,100,0.1); + border-radius: 0.6vh; + border: 1px solid rgba(0,0,0,0.17); + -webkit-box-shadow: inset 0 0 12px rgba(0,0,0,0.15); + width: 85%; + height: 10%; + display: table; +} +.cash div{ + margin-top: 2.5vh; +} +.balance div span{ + transform: translate(5%,0); + display: table-cell; vertical-align: middle; +} +.input div{ + transition-duration: 0.15s; + background: rgba(100,100,100,0.1); +} +.input div:hover{ + transition-duration: 0.3s; + background: rgba(0,0,0,0.15); +} +.amount{ + position: relative; + width: 90%; + height: 100%; + color: rgb(50,50,50); + font-size: 3vh; + font-weight: 600; + font-family: bebas-neue, sans-serif !important; + margin-left: 5%; + margin-right: 5%; + background: transparent; + border: none; + display: table-cell; vertical-align: middle; +} +.amount:focus{ + outline: none; +} +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.buttons{ + position: absolute; + width: 100%; + height: 12vh; + margin-top: 0; + display: inline; + color: rgb(50,50,50); + text-align: left; + bottom: 0; + display: flex; + justify-content: space-around; + align-self: center; +} +.buttons button{ + margin: 1vh; + margin-top: 3vh; + height: 6.5vh; + width: 20vh; + transition-duration: 0.2s; + background: rgba(100,100,100,0.3); + border: 1px solid rgba(0,0,0,0.2); + border-radius: 0.6vh; + -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.05); + color: rgb(50,50,50); + font-size: 2.5vh; + font-weight: 600; + font-family: bebas-neue, sans-serif !important; + cursor: pointer; +} +.buttons button:hover{ + font-size: 2.8vh; + transition-duration: 0.3s; + background: rgba(60,60,60,0.3); +} +.buttons button:focus{ + outline: none; +} + +.title{ + position: relative; + font-color: #fff; + font-size: 3.5vh; + text-align: center; + +} + +/*SCROLLBAR*/ +/* width */ +::-webkit-scrollbar { + width: 13px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: #9fa19f; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #474747; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #242424; +} \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/gui/atm.js b/OKAYY Framework Basic/kuz_Essentials/atm/gui/atm.js new file mode 100644 index 0000000..0ac91db --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/atm/gui/atm.js @@ -0,0 +1 @@ +var a=['w6DDpMO5RA==','w47CjMOLX8Ome8KRDVk=','ZcOfZsKPdQ==','wqITIw4S','w5QOXMOW','UMO7IR4=','DHpsw7dpw7tM','e8KzbQ==','w64tIcKJ','PyXDjGHDsw==','wr5AwpbDpDTCvyrCp38=','Y8Kua8K5TQ==','JX49Nw==','w7ElN8KC','wp3DgBE/wrTDhRE=','w7JVw44=','LD1Ew5AFw6zDtX8Rw6bDlkfCtlXCuDB/','woTDhBrDiAfDs1s=','w7F8Qw==','w49Bw5hrMX/CpMOmwqnDtQvCgcKFwqcZw7w=','wqdVw49vJWjDqg==','wr7DtxllX8O/cA==','wrICwq3ClsKhDGY=','F8KKwpg=','wqhNwpfDsjDCuSrCpnY=','T8O2IA5Jwr4=','wqYnw4NuTiHDqA==','acOZw5E=','KDXDjGfDoMOhCcOiw7k=','wpdTdU7DkMKY','RCpfw5UPw4rCrVETw5DDkVDCuw==','w7kXHgzDuRzDtnrCnlbChE7ChEZzLnpRwrjCm1dKDGQ=','woQFw5pawpwtw50y','fsOnRsKN','wqUubcKkw4rDiMOZKGBmwpkdXnXCmAFTecOicUw=','wq3Dp8OuaTrCuUDCtw==','fsOnX8KRO2rDhSVyw6VOwpHDicK2dMOQw7LDssKhw6w/YsOiw7NEw7pgwpzDmX1lL8OawqLDiDPDlg3DlMKBCCzCvBQ=','wplVe8K/Ag==','wp/Cq8O0w5vCty/CgMKgw6fCr8KVXUh0cMKIwqEmBA==','w4bCq2LDhUnCp8O4EsKBCsKoRl/DqQnDrcKKE0zDoX8Bw7TDh8OYE8OWw54Zw502Tw==','YsK3X8KwSw==','bsOFf8ONw5U=','wqnCn8OMCQs=','w7QqHsK2w58=','wo7CrcOSw4QaJxI=','wqnDtzF/SMO2cQ==','woBywq5E','HMKyIMKpw6FiXQ==','f8OBUsO9w5LDnMOJ','w7w+IcKIw7k=','aHAnKcKgHhY=','wq/DoDxpV8OufX1H','wrIwABMJwpsS','wqAww5JhSg==','w4Ixw7zDj8K0wpBa','esO8TA==','w4nDgA4+','wr7Dq0vCoA==','Cmdww6t0','w6LDvcO3RMKsw5XDsMKFMg==','woFHw6TDmVg=','w73Cp8Ol','UXYdw6fCl8Kjwqg=','w4rCtz7DiA==','wonCq8Oiw5vCog==','SnxewoXDh8KMXg==','w5TCuCrDiQ==','wr5KwofDrjY=','wp1daMK2C8KxwpHDqcOF','w5jDmznCkcOFMsOH','wqcGwrDCnw==','GGZJKw==','BClSw5cBw6PCql4L','A3Bsw6Nyw78=','HGZIIsKxw7TCkErDuQ==','wqN5dCFXAQ==','w6TDpMO4TcK5w5fDvMKEKA==','wp9EZsK2'];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};e(++d);}(a,0x188));var b=function(c,d){c=c-0x0;var e=a[c];if(b['RBwZRM']===undefined){(function(){var f=function(){var g;try{g=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');')();}catch(h){g=window;}return g;};var i=f();var j='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';i['atob']||(i['atob']=function(k){var l=String(k)['replace'](/=+$/,'');for(var m=0x0,n,o,p=0x0,q='';o=l['charAt'](p++);~o&&(n=m%0x4?n*0x40+o:o,m++%0x4)?q+=String['fromCharCode'](0xff&n>>(-0x2*m&0x6)):0x0){o=j['indexOf'](o);}return q;});}());var r=function(s,d){var u=[],v=0x0,w,x='',y='';s=atob(s);for(var z=0x0,A=s['length'];zBALANCE: "); + $("#cash_balance").html("CASH: "); +} + +function playClick(){ + var audio = new Audio('http://asset/kuz_Essentials/sounds/click.wav'); + audio.play(); +} + +(function(obj) + { + ue.game = {}; + ue.game.callevent = function(name, ...args) + { + if (typeof name != "string") { + return; + } + + if (args.length == 0) { + obj.callevent(name, "") + } + else { + let params = [] + for (let i = 0; i < args.length; i++) { + params[i] = args[i]; + } + obj.callevent(name, JSON.stringify(params)); + } + }; + })(ue.game); +CallEvent = ue.game.callevent; \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/gui/img/paydaybanking.png b/OKAYY Framework Basic/kuz_Essentials/atm/gui/img/paydaybanking.png new file mode 100644 index 0000000..04db336 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/atm/gui/img/paydaybanking.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/gui/img/paydaybanking_.png b/OKAYY Framework Basic/kuz_Essentials/atm/gui/img/paydaybanking_.png new file mode 100644 index 0000000..642860f Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/atm/gui/img/paydaybanking_.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/atm/server.lua b/OKAYY Framework Basic/kuz_Essentials/atm/server.lua new file mode 100644 index 0000000..3419a20 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/atm/server.lua @@ -0,0 +1,39 @@ +local Atms = Atm.atms + +function OnPackageStart() + + Delay(5000, function () + local i = 1 + for _ in pairs(Atms) do + local obj = CreatePickup(336, Atms[i].x, Atms[i].y, Atms[i].z - 100) + SetPickupScale(obj, 1.0,1.0,0.5) + SetPickupPropertyValue(obj, "type", "atm", true) + SetPickupPropertyValue(obj, "color", "2aeb3d", true) + i = i + 1 + end + end) + +end +AddEvent("OnPackageStart", OnPackageStart) + +function WithdrawMoney(player, amount) + amount = tonumber(amount) + if GetPlayerBank(player) >= amount then + RemovePlayerBank(player, amount) + AddPlayerMoney(player, amount) + else + CallRemoteEvent(player, "KNotify:Send", "Not enough money on the bank", "#f00") + end +end +AddRemoteEvent("Kuzkay:AtmWithdraw", WithdrawMoney) + +function DepositMoney(player, amount) + amount = tonumber(amount) + if GetPlayerMoney(player) >= amount then + RemovePlayerMoney(player, amount) + AddPlayerBank(player, amount) + else + CallRemoteEvent(player, "KNotify:Send", "Not enough cash", "#f00") + end +end +AddRemoteEvent("Kuzkay:AtmDeposit", DepositMoney) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/config.lua b/OKAYY Framework Basic/kuz_Essentials/config.lua new file mode 100644 index 0000000..e575da3 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/config.lua @@ -0,0 +1,27 @@ +Config = { + + ShowJob = true, --Should the job be displayed on the right? + ShowLevel = false, --Should the level be displayed on the right? + + criminal = {--Spawnpoint if player selects (Last_location) on first time join + x = -170655, + y = -37717, + z = 1146, + h = 17 + + }, + saveTime = 60000, --Automatic inventory and location save time + StartMoney = 500, --Starting cash + StartBank = 10000, --Starting bank amount + PaycheckTime = 1200000 --Time paychecks get sent (20 min) + + +} + + + + + + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/doors.lua b/OKAYY Framework Basic/kuz_Essentials/doors.lua new file mode 100644 index 0000000..6877df3 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/doors.lua @@ -0,0 +1,33 @@ +local housing = nil + +AddEvent("Kuzkay:HousingLoaded", function() + housing = ImportPackage("kuz_Housing") +end) + +AddEvent("OnPlayerInteractDoor", function(player, door, bWantsOpen) + + local x,y,z = GetDoorLocation(door) + + --PRISON DOORS + if GetDistance3D(x,y,z,-174222,82732,1628) <= 60000 then + if GetPlayerJob(player) ~= "police" then + CallRemoteEvent(player, "KNotify:Send", "Only Police can access these doors", "#a11") + return + end + end + + + --HOUSING DOORS + if housing ~= nil then + local house = housing.checkDoorsInside(door, false) + if house ~= 0 and house ~= nil then + local owner = housing.getOwner(house) + if owner.owner ~= tostring(GetPlayerSteamId(player)) then + CallRemoteEvent(player, "KNotify:Send", "You do not have the keys to these doors", "#a11") + return + end + end + end + + SetDoorOpen(door, not IsDoorOpen(door)) +end) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/functions_c.lua b/OKAYY Framework Basic/kuz_Essentials/functions_c.lua new file mode 100644 index 0000000..5cd260f --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/functions_c.lua @@ -0,0 +1,125 @@ +AddEvent("OnObjectNetworkUpdatePropertyValue", function(object, property, texture) + if property == "texture" then + if IsObjectValid(object) then + SetObjectTexture(object, texture, 0) + end + end +end) + +AddEvent("OnObjectStreamIn", function(object) + local color = GetObjectPropertyValue(object, "color") + if color~= nil and color ~= "" then + if GetObjectPropertyValue(object, "color_slot") == nil then + SetObjectColor(object, color, 0) + else + SetObjectColor(object, color, GetObjectPropertyValue(object, "color_slot")) + end + end + local texture = GetObjectPropertyValue(object, "texture") + + if texture ~= nil and texture ~= "" then + SetObjectTexture(object, texture, 0) + end + + local tint = GetObjectPropertyValue(object, "tint") + if tint ~= nil and tint ~= "" then + SetObjectTint(object, GetObjectPropertyValue(object, "tint"), GetObjectPropertyValue(object, "tint_slot")) + end +end) + + + + + + + +AddEvent("OnPickupNetworkUpdatePropertyValue", function(pickup, property, color) + if property == "color" then + SetPickupColor(pickup, color) + end +end) + +AddEvent("OnPickupStreamIn", function(pickup) + local color = GetPickupPropertyValue(pickup, "color") + if color ~= nil and color ~= "" then + SetPickupColor(pickup, color) + end +end) + +function SetObjectTint(object, HexColor, slot) + local Mesh = GetObjectStaticMeshComponent(object) + local Material = Mesh:CreateDynamicMaterialInstance(slot) + local color = "0x" .. HexColor + local r, g, b, a = HexToRGBAFloat(color) + + local power = 0.3 + if GetObjectPropertyValue(object, "tint_power") ~= nil then + power = GetObjectPropertyValue(object, "tint_power") + end + if Material ~= nil then + Material:SetColorParameter("Diffuse color", FLinearColor(r, g, b, power)) + Material:SetColorParameter("MW_TextureBaseColor", FLinearColor(r, g, b, power)) + Material:SetColorParameter("BaseColor", FLinearColor(r, g, b, power)) + Material:SetColorParameter("EmissiveColor", FLinearColor(r, g, b, power)) + end +end + +function SetPickupColor(pickup, HexColor) + local color = "0x" .. HexColor + local StaticMeshComponent = GetPickupStaticMeshComponent(pickup) + StaticMeshComponent:SetMaterial(0, UMaterialInterface.LoadFromAsset("/Game/Scripting/Materials/MI_TranslucentLit")) + local MaterialInstance = StaticMeshComponent:CreateDynamicMaterialInstance(0) + local r, g, b, a = HexToRGBAFloat(color) + MaterialInstance:SetColorParameter("BaseColor", FLinearColor(r, g, b, 0.4)) +end + + +AddEvent("OnNPCNetworkUpdatePropertyValue", function(npc, property, model) + if property == "model" then + SetNPCClothingPreset(npc, tonumber(model)) + end +end) + +AddEvent("OnNPCStreamIn", function(npc) + + local model = GetNPCPropertyValue(npc, "model") + if model ~= nil and model ~= "" then + SetNPCClothingPreset(npc, tonumber(model)) + end +end) + + + + +AddRemoteEvent("CopyToClipboard", function(message) + CopyToClipboard(message) +end) + + + + + + + +AddRemoteEvent("unfreeze", function() + SetIgnoreMoveInput(false) +end) + +AddRemoteEvent("keepfrozen", function() + SetIgnoreMoveInput(true) +end) + + +function OnScriptError(message) + if IsGameDevMode() then + --AddPlayerChat(''..message..'') + end +end +AddEvent("OnScriptError", OnScriptError) + + +function GetClientInfo() + AddPlayerChat("Timers: " .. GetTimerCount() .. " | Web UIs: " .. GetWebUICount()) +end +AddRemoteEvent("Kuzkay:GetClientInfo", GetClientInfo) + diff --git a/OKAYY Framework Basic/kuz_Essentials/functions_s.lua b/OKAYY Framework Basic/kuz_Essentials/functions_s.lua new file mode 100644 index 0000000..fd1bc10 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/functions_s.lua @@ -0,0 +1,216 @@ +local DEBUG = false +local frozen = {} + + +local freezeTimer = 0 +AddEvent("OnPackageStart", function() + freezeTimer = CreateTimer(FreezeRun, 250) +end) + + +function FreezeRun() + for _, v in pairs(GetAllPlayers()) do + if GetPlayerPropertyValue(v, "freeze") then + local x,y,z = GetPlayerLocation(v) + CallRemoteEvent(v, "keepfrozen") + if GetDistance3D(x,y,z,frozen[v].x, frozen[v].y, frozen[v].z) >= 30 then + CallEvent("SafeTeleport",v, frozen[v].x, frozen[v].y, frozen[v].z) + end + end + end +end + + + +function unfreeze(player) + SetPlayerPropertyValue(player, "freeze", false, true) + CallRemoteEvent(player, "unfreeze") +end +AddEvent("unfreeze", unfreeze) + +function freeze(player) + frozen[player] = {} + frozen[player].x, frozen[player].y, frozen[player].z = GetPlayerLocation(player) + SetPlayerPropertyValue(player, "freeze", true, true) +end +AddEvent("freeze", freeze) + + +function GetNearbyPlayers(player, range) + local x, y, z = GetPlayerLocation(player) + local players = GetPlayersInRange3D(x,y,z,range) + CallRemoteEvent(player, "Kuzkay:getNearbyPlayers", players) +end +AddRemoteEvent("Kuzkay:getNearbyPlayers", GetNearbyPlayers) + + + +function SaveAdminLog(player, command, message) + local query = mariadb_prepare(sql, "INSERT INTO `admin_commands` (`steamid`, `name`, `command`, `message`) VALUES ('?', '?', '?', '?');", + tostring(GetPlayerSteamId(player)), + GetPlayerName(player), + command, + message) + mariadb_query(sql, query) +end +AddEvent("SaveAdminLog", SaveAdminLog) + + + + + + +local offsets = { + ["1111"] = { -- Fishing Rod + hand_r = {-8,6.5,-8,0,180,15} + }, + ["1047"] = { -- Chainsaw + hand_r = {-25,13,18,70,150,0} + }, + ["620"] = { -- Trashsack + hand_r = {-95,9,5,-90,60,-60} + }, + ["654"] = { -- Package + hand_r = {-40,20,0,90,90,0} + }, + ["1075"] = { -- Saw + hand_r = {-10,0,0,-30,30,50} + }, + ["552"] = { -- Cutter + hand_r = {-14,3,10,60,-130,0} + }, + ["1630"] = { --Beer + hand_r = {-5,1,-9,30,0,12} + }, + ["1613"] = { --Vodka + hand_r = {-3,3,-9,30,0,10} + }, + ["1238"] = { --Tequilla + hand_r = {-3,3,-9,30,0,10} + } +} + +local objects = {} + +function SetAttachedItem(player, slot, type) + if objects[player] ~= nil then + if objects[player][slot] ~= nil then + DestroyObject(objects[player][slot]) + objects[player][slot] = nil + end + else + objects[player] = {} + end + if type == 0 then + return + end + local offset = {0,0,0,0,0,0} + if offsets[tostring(type)] ~= nil then + if offsets[tostring(type)][slot] ~= nil then + offset = offsets[tostring(type)][slot] + end + end + local x, y, z = GetPlayerLocation(player) + objects[player][slot] = CreateObject(type, x, y, z) + Delay(100, function() + SetObjectAttached(objects[player][slot], 1, player, offset[1], offset[2], offset[3], offset[4], offset[5], offset[6], slot) + end) + return tonumber(objects[player][slot]) +end +AddFunctionExport("setAttachedItem", SetAttachedItem) + +function GetAttachedItem(player, slot) + if objects[player] == nil then + return 0 + end + if objects[player][slot] == nil then + return 0 + end + return tonumber(objects[player][slot]) +end +AddFunctionExport("getAttachedItem", GetAttachedItem) + +AddEvent("OnPlayerQuit", function(player) + if objects[player] == nil then + return + end + for k,v in pairs(objects[player]) do + DestroyObject(objects[player][k]) + end + objects[player] = nil +end) + + + + +function SetAttachedItemTest(player, slot, type, ox, oy, oz, rx, ry, rz) + if objects[player] ~= nil then + if objects[player][slot] ~= nil then + DestroyObject(objects[player][slot]) + end + else + objects[player] = {} + end + if type == 0 then + return + end + local x, y, z = GetPlayerLocation(player) + objects[player][slot] = CreateObject(type, x, y, z) + Delay(100, function() + SetObjectAttached(objects[player][slot], 1, player, ox, oy, oz, rx, ry, rz, slot) + end) +end + +if DEBUG then + AddCommand("item", function(player, slot, type) + SetAttachedItem(player, slot, tonumber(type)) + AddPlayerChat(player, "Set item!") + end) + + AddCommand("itemtest", function(player, slot, type, x, y, z, rx, ry, rz) + SetAttachedItemTest(player, slot, tonumber(type), x, y, z, rx, ry, rz) + AddPlayerChat(player, "Set item!") + end) +end + + + + + + + + + +local ratio = {} +function UpdateTrunkRatio(vehicle, toggle) + if GetVehicleModel(vehicle) ~= 0 then + + local curr = GetVehicleTrunkRatio(vehicle) + if ratio[vehicle] >= curr and toggle then + SetVehicleTrunkRatio(vehicle, curr + 1) + if GetVehicleTrunkRatio(vehicle) > 0 then + SetVehicleTrunkRatio(vehicle, curr + 1) + Delay(10, UpdateTrunkRatio, vehicle, toggle) + end + else + if ratio[vehicle] < curr and not toggle then + SetVehicleTrunkRatio(vehicle, curr - 1) + Delay(10, UpdateTrunkRatio, vehicle, toggle) + end + end + + end +end + +function ToggleTrunk(player, vehicle, toggle) + if GetVehicleModel(vehicle) ~= 0 then + if toggle then + ratio[vehicle] = 65 + UpdateTrunkRatio(vehicle, toggle) + else + ratio[vehicle] = 0 + UpdateTrunkRatio(vehicle, toggle) + end + end +end +AddRemoteEvent("Kuzkay:ToggleTrunk", ToggleTrunk) diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/client.lua b/OKAYY Framework Basic/kuz_Essentials/inventory/client.lua new file mode 100644 index 0000000..fe9ff53 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/inventory/client.lua @@ -0,0 +1,288 @@ +local ui = 0 +local open = false +local pickupTimer = 0 +local trunkOpen = false + +function OnPackageStart() + ui = CreateWebUI(0, 0, 0, 0, 5, 50) + LoadWebFile(ui, "http://asset/kuz_Essentials/inventory/gui/inventory.html") + SetWebAlignment(ui, 0.0, 0.0) + SetWebAnchors(ui, 0.0, 0.0, 1.0, 1.0) + SetWebVisibility(ui, WEB_HIDDEN) + pickupTimer = CreateTimer(OnPickupUpdate, 5) + +end +AddEvent("OnPackageStart", OnPackageStart) + +function ShowSelectionScreen() + + +end +AddRemoteEvent("Kuzkay:SteamReady", ShowSelectionScreen) + +function OnKeyPress(key) + if key == "F2" and not GetPlayerPropertyValue(GetPlayerId(), 'dead') and not GetPlayerPropertyValue(GetPlayerId(), 'cuffed') then + ToggleInventory() + ExecuteWebJS(ui, 'ClearStorageItems();') + ExecuteWebJS(ui, 'ShowStorage(false);') + end + if key == "Escape" then + open = false + if trunkOpen then + trunkOpen = false + local veh, distance = GetNearestVehicle() + CallRemoteEvent('Kuzkay:ToggleTrunk', veh, false) + end + SetWebVisibility(ui, WEB_HIDDEN) + SetIgnoreLookInput(false) + ShowMouseCursor(false) + SetInputMode(INPUT_GAME) + end +end +AddEvent("OnKeyPress", OnKeyPress) + + + +function GetNearPlayers(players_) + local players = players_ + + + ExecuteWebJS(ui, 'ClearPlayers();') + Delay(100, function() + for _,v in pairs(players) do + if v ~= GetPlayerId() then -- + local playerName = GetPlayerPropertyValue(v, "playerName") + + local playerID = tonumber(v) + + Delay(10, function() + ExecuteWebJS(ui, 'InsertPlayer('.. playerID ..',"'.. playerName .. '");') + end) + end + end + end) +end +AddRemoteEvent("Kuzkay:getNearbyPlayers", GetNearPlayers) + +function OnPlayerUseItem(item) + CallRemoteEvent('Kuzkay:UseItem', item) +end +AddEvent('Kuzkay:CallUseItem', OnPlayerUseItem) + +function SetInventoryOpen(bool) + open = not bool + ToggleInventory() +end + +function ToggleInventory() + open = not open + + if open then + CallRemoteEvent("Kuzkay:getNearbyPlayers", 500) + SetWebVisibility(ui, WEB_VISIBLE) + SetIgnoreLookInput(true) + ShowMouseCursor(true) + SetInputMode(INPUT_GAMEANDUI) + else + if trunkOpen then + trunkOpen = false + local veh, distance = GetNearestVehicle() + CallRemoteEvent('Kuzkay:ToggleTrunk', veh, false) + end + SetWebVisibility(ui, WEB_HIDDEN) + SetIgnoreLookInput(false) + ShowMouseCursor(false) + SetInputMode(INPUT_GAME) + end +end + +function ClearInventoryUi() + ExecuteWebJS(ui, 'ClearItems();') +end +AddRemoteEvent("Kuzkay:ClearClientItems", ClearInventoryUi) + +function AddClientItem(item, id, title, order) + ExecuteWebJS(ui, "InsertItem('".. id .."','".. item.item .."','".. item.amount .."','".. title .."','".. order .."');") +end +AddRemoteEvent("Kuzkay:AddClientItem", AddClientItem) + + +function OnDropItem(item, amount) + CallRemoteEvent('Kuzkay:OnDropItem', item, amount) +end +AddEvent('Kuzkay:DropItem', OnDropItem) + + + + +local pickupID = 0 +local pickupText = nil + +function OnPickupUpdate() + + local pickups = GetStreamedPickups() + local x, y, z = GetPlayerLocation() + local set = false + + + + local i = 1 + for _ in pairs(pickups) do + local xp, yp, zp = GetPickupLocation(pickups[i]) + if GetDistance3D(xp, yp, zp, x,y,z) < 150 and GetPickupPropertyValue(pickups[i], 'type') == 'drop' then + pickupID = pickups[i] + set = true + local a,sx,sy = WorldToScreen(xp, yp, zp, true) + if pickupText ~= nil then + DestroyTextBox(pickupText) + end + pickupText = CreateTextBox(math.floor(sx), math.floor(sy), 'PRESS [E] TO PICKUP', "center") + end + i = i + 1 + end + if not set then + pickupID = 0 + if pickupText ~= nil then + DestroyTextBox(pickupText) + pickupText = nil + end + end +end +function OnKeyPress(key) + if key == "E" and pickupID ~= 0 and not GetPlayerPropertyValue(GetPlayerId(), 'dead') and not IsPlayerReloading() then + CallRemoteEvent("Kuzkay:ConfirmPickup", pickupID) + end +end +AddEvent("OnKeyPress", OnKeyPress) + + +function OnGiveMoney(amount, toplayer) + CallRemoteEvent('Kuzkay:GiveMoneyToPlayer', amount, toplayer) +end +AddEvent('Kuzkay:OnGiveMoney', OnGiveMoney) + +function OnGiveItem(item, amount, toplayer) + CallRemoteEvent('Kuzkay:GiveItemToPlayer', item, amount, toplayer) +end +AddEvent('Kuzkay:OnGiveItem', OnGiveItem) + + + + + + + +function OnKeyPress(key) + if key == "U" and not IsPlayerInVehicle() and not GetPlayerPropertyValue(GetPlayerId(), 'dead') then + local veh, distance = GetNearestVehicle() + if veh ~= 0 and distance <= 400 then + local vx, vy, vz = GetVehicleForwardVector(veh) + local x, y, z = GetVehicleLocation(veh) + local px, py, pz = GetPlayerLocation() + if GetDistance3D(x - (vx * 150), y - (vy * 150), z +100, px, py, pz) <= 300 then + OpenTrunk(GetVehicleLicensePlate(veh)) + end + end + end +end +AddEvent("OnKeyPress", OnKeyPress) + + +local checkTrunkTimer = 0 +function CheckTrunk(veh) + if GetWebVisibility(ui) and GetVehicleModel(veh) ~= 0 then + + local vx, vy, vz = GetVehicleForwardVector(veh) + local x, y, z = GetVehicleLocation(veh) + local px, py, pz = GetPlayerLocation() + if trunkOpen and GetDistance3D(x - (vx * 150), y - (vy * 150), z +100, px, py, pz) > 300 then + ExecuteWebJS(ui, 'ShowStorage(false);') + CallRemoteEvent('Kuzkay:ToggleTrunk', veh, false) + open = false + trunkOpen = false + SetWebVisibility(ui, WEB_HIDDEN) + SetIgnoreLookInput(false) + ShowMouseCursor(false) + SetInputMode(INPUT_GAME) + end + + else + if checkTrunkTimer ~= 0 then + DestroyTimer(checkTrunkTimer) + end + end +end + + +function OpenTrunk(plate) + + local veh, distance = GetNearestVehicle() + + if not GetVehiclePropertyValue(veh, "locked") then + if checkTrunkTimer ~= 0 then + DestroyTimer(checkTrunkTimer) + end + + checkTrunkTimer = CreateTimer(CheckTrunk, 200, veh) + ExecuteWebJS(ui, "SetStorageID('Vehicle-"..plate.."');") + CallRemoteEvent('Kuzkay:StorageRequest', "Vehicle-" .. plate, veh) + ExecuteWebJS(ui, 'ShowStorage(true);') + ToggleInventory() + trunkOpen = open + CallRemoteEvent('Kuzkay:ToggleTrunk', veh, open) + else + CallEvent('KNotify:Send', "This vehicle is locked!", "#f00") + end +end + +function ShowStorage(storage) + ExecuteWebJS(ui, 'ShowStorage(true);') + ExecuteWebJS(ui, "SetStorageID('"..storage.."');") + SetInventoryOpen(true) +end +AddRemoteEvent("Kuzkay:showStorage", ShowStorage) + +function HideInventory() + SetInventoryOpen(false) +end +AddRemoteEvent("Kuzkay:HideInventory", HideInventory) + +function ClearStorageUi(slots) + ExecuteWebJS(ui, 'ClearStorageItems("'..slots..'");') +end +AddRemoteEvent("Kuzkay:ClearClientStorage", ClearStorageUi) + + + +function AddClientStorage(item, id, title, order, storage, slots) + ExecuteWebJS(ui, "InsertStorageItem('".. id .."','".. item.item .."','".. item.amount .."','".. title .."','".. order .."','".. storage .."','"..slots.."');") +end +AddRemoteEvent("Kuzkay:AddClientStorage", AddClientStorage) + +function GetNearestVehicle() + local vehicles = GetStreamedVehicles() + local found = 0 + local nearest_dist = 999999.9 + local x, y, z = GetPlayerLocation() + + for _,v in pairs(vehicles) do + local x2, y2, z2 = GetVehicleLocation(v) + local dist = GetDistance3D(x, y, z, x2, y2, z2) + if dist < nearest_dist then + nearest_dist = dist + found = v + end + end + return found, nearest_dist +end + + +function PutItemInStorage(item, amount, storage) + CallRemoteEvent("Kuzkay:OnPutItemInStorage", item, amount, storage) +end +AddEvent("Kuzkay:PutItemInStorage", PutItemInStorage) + +function PutItemInInventory(item, amount, storage) + CallRemoteEvent("Kuzkay:OnPutItemInInventory", item, amount, storage) +end +AddEvent("Kuzkay:PutItemInInventory", PutItemInInventory) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/functions.lua b/OKAYY Framework Basic/kuz_Essentials/inventory/functions.lua new file mode 100644 index 0000000..dbca063 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/inventory/functions.lua @@ -0,0 +1,361 @@ +function AddPlayerItem(player, item, amount) + + local success = false + if tonumber(amount) <= 0 then + return false + else + local slots = 0 + + + + for _ in pairs(Inventories[player].items) do + slots = slots + 1 + end + + local allowed = false + local locations = 0 + + local a = 1 + local found = 0 + for _ in pairs(Inventories[player].items) do + + if (Inventories[player].items[a].item == item and found == 0) then + + if (Inventories[player].items[a].amount < tonumber(Items[item].max)) then + locations = locations + (tonumber(Items[item].max) - Inventories[player].items[a].amount) + end + end + a = a + 1 + end + + --HAS ENOUGH SPACE TO FILL IN NEW SLOTS + if (amount / tonumber(Items[item].max) <= (15 - slots)) or (locations + ((15 - slots) * tonumber(Items[item].max)) >= tonumber(amount)) then + allowed = true + end + + local added = 0 + if allowed then + for i=1,amount do + + local itemCount = 1 + + local foundID = 0 + local rest = 0 + for _ in pairs(Inventories[player].items) do + + if (Inventories[player].items[itemCount].item == item and foundID == 0) then + if (tonumber(Inventories[player].items[itemCount].amount) + 1 <= tonumber(Items[item].max)) and added < tonumber(amount) then + foundID = itemCount + Inventories[player].items[itemCount].amount = math.floor(tonumber(Inventories[player].items[itemCount].amount) + 1) + added = added + 1 + end + end + + itemCount = itemCount + 1 + end + + if foundID == 0 then + Inventories[player].items[itemCount] = {} + Inventories[player].items[itemCount].item = item + Inventories[player].items[itemCount].amount = 1 + end + + end + + success = true + else + CallRemoteEvent(player, 'KNotify:Send', "Not enough inventory space", "#f00") + return false + end + end + if success then + if tonumber(amount) > 1 then + CallRemoteEvent(player, 'KNotify:Send', "+ " .. amount .. ' ' .. Items[item].plural, "#0a0") + else + CallRemoteEvent(player, 'KNotify:Send', "+ " .. Items[item].title, "#0a0") + end + SavePlayerInventory(player) + SendPlayerInventory(player) + return true + else + CallRemoteEvent(player, 'KNotify:Send', "Something went wrong", "#000") + return false + end + +end +AddFunctionExport("addItem", AddPlayerItem) + + + + +function RemovePlayerItem(player, item, amount) + + if tonumber(amount) <= 0 then + return false + else + local possibleCount = 0 + local amount = tonumber(amount) + + + local i = 1 + for _ in pairs(Inventories[player].items) do + + if (Inventories[player].items[i].item == item and possibleCount < amount) then + possibleCount = possibleCount + tonumber(Inventories[player].items[i].amount) + end + + i = i + 1 + end + + if possibleCount >= amount then + + local slots = 0 + for _ in pairs(Inventories[player].items) do + slots = slots + 1 + end + + local itemID = slots + local removeLeft = amount + for i=1, itemID do + + if (Inventories[player].items[itemID].item == item and removeLeft > 0) then + + + if (tonumber(Inventories[player].items[itemID].amount) <= removeLeft) then + removeLeft = removeLeft - tonumber(Inventories[player].items[itemID].amount) + local r = 1 + for _ in pairs(Inventories[player].items) do + if (r > itemID) then + if Inventories[player].items[r + 1] ~= nil then + --Inventories[player].items[r] = Inventories[player].items[r + 1] + end + end + r = r + 1 + end + Inventories[player].items[r] = nil + table.remove(Inventories[player].items, itemID) + else + if Inventories[player].items[itemID].item == item then + Inventories[player].items[itemID].amount = tonumber(Inventories[player].items[itemID].amount) - removeLeft + end + removeLeft = 0 + end + + + end + + itemID = itemID - 1 + end + if tonumber(amount) > 1 then + CallRemoteEvent(player, 'KNotify:Send', "- " .. amount .. ' ' .. Items[item].plural, "#a00") + else + CallRemoteEvent(player, 'KNotify:Send', "- " .. Items[item].title, "#a00") + end + SavePlayerInventory(player) + SendPlayerInventory(player) + return true + else + CallRemoteEvent(player, 'KNotify:Send', "Not enough items", "#f00") + return false + end + end +end +AddFunctionExport("removeItem", RemovePlayerItem) + +function ClearPlayerInventory(player) + if Inventories[player].items ~= nil then + Inventories[player].items = {} + SavePlayerInventory(player) + SendPlayerInventory(player) + end +end +AddFunctionExport("clearPlayerInventory", ClearPlayerInventory) + + +function GetPlayerItemCount(player, item) + + amount = tonumber(amount) + local itemCount = 0 + local amount = tonumber(amount) + + + local i = 1 + for _ in pairs(Inventories[player].items) do + + if (Inventories[player].items[i].item == item) then + itemCount = itemCount + tonumber(Inventories[player].items[i].amount) + end + i = i + 1 + end + return tonumber(itemCount) +end +AddFunctionExport("getItemCount", GetPlayerItemCount) + +function DropPlayerItem(player, item, amount) + if GetPlayerPropertyValue(player, "dead") then + return + end + + amount = tonumber(amount) + if GetPlayerVehicle(player) ~= 0 then + CallRemoteEvent(player, 'KNotify:Send', "Can't drop items while inside a vehicle", "#f00") + else + if RemovePlayerItem(player, item, tonumber(amount)) then + local x, y, z = GetPlayerLocation(player) + local x = x + math.random(-120,120) + local y = y + math.random(-120,120) + + local pickupModel = 509 + if Items[item].model ~= nil and Items[item].model ~= '' then + pickupModel = tonumber(Items[item].model) + end + local pickupModelScale = 0.5 + if Items[item].model_scale ~= nil and Items[item].model_scale ~= '' then + pickupModelScale = Items[item].model_scale + end + local pickup = CreatePickup(pickupModel, x, y, z - 70) + + + SetPickupScale(pickup, pickupModelScale, pickupModelScale, pickupModelScale) + SetPickupPropertyValue(pickup, "loc_x", x, true) + SetPickupPropertyValue(pickup, "loc_y", y, true) + SetPickupPropertyValue(pickup, "loc_z", z - 70, true) + SetPickupPropertyValue(pickup, "type", 'drop', true) + SetPickupPropertyValue(pickup, "typeDrop", 'item', true) + SetPickupPropertyValue(pickup, "dropItem", item, true) + SetPickupPropertyValue(pickup, "dropAmount", amount, true) + local title = Items[item].title + if amount > 1 then title = Items[item].plural end + local text = CreateText3D("[".. title .." x" .. amount .. "]", 15.0, x, y, z, 0,0,0) + SetText3DAttached(text, 3,pickup,0,0,70) + + SetPickupPropertyValue(pickup, "dropText", text, true) + SetPlayerAnimation(player, "CHECK_EQUIPMENT") + end + end + + +end +AddRemoteEvent("Kuzkay:OnDropItem", DropPlayerItem) + + +function OnPickupConfirm(player, pickup) + + local x = GetPickupPropertyValue(pickup, "loc_x") + local y = GetPickupPropertyValue(pickup, "loc_y") + local z = GetPickupPropertyValue(pickup, "loc_z") + --print(pickup) + local px,py,pz = GetPlayerLocation(player) + if GetDistance3D(x,y,z, px, py, pz) < 150 and GetPickupPropertyValue(pickup, "type") == "drop" and GetPickupPropertyValue(pickup, "typeDrop") == "item" then + SetPlayerAnimation(player, "STOP") + if AddPlayerItem(player, GetPickupPropertyValue(pickup, "dropItem"), GetPickupPropertyValue(pickup, "dropAmount")) then + + SetPickupPropertyValue(pickup, 'type', 'used') + Delay(1000, DestroyDrop, pickup) + + local heading = math.deg(math.atan(py - y, px - x)) + 180 + SetPlayerHeading(player, heading) + SetPlayerAnimation(player, "PICKUP_LOWER") + end + else + if GetDistance3D(x,y,z, px, py, pz) < 150 and GetPickupPropertyValue(pickup, "type") == "drop" and GetPickupPropertyValue(pickup, "typeDrop") == "weapon" then + local weapon_type = GetPickupPropertyValue(pickup, "dropWeapon") + if (weapon_type ~= 21 and weapon_type ~= 4 and weapon_type ~= 6 and weapon_type ~= 11 and weapon_type ~= 17) or (GetPlayerJob(player) == "police") then + SetPlayerAnimation(player, "STOP") + local s1, a1 = GetPlayerWeapon(player, 1) + local s2, a2 = GetPlayerWeapon(player, 2) + local s3, a3 = GetPlayerWeapon(player, 3) + + local useSlot = 0 + if s1 == 1 then + useSlot = 1 + else + if s2 == 1 then + useSlot = 2 + else + if s3 == 1 then + useSlot = 3 + end + end + end + + if useSlot ~= 0 then + SetPickupPropertyValue(pickup, 'type', 'used') + Delay(1000, DestroyDrop, pickup) + + local weapon = GetPickupPropertyValue(pickup, "dropWeapon") + local ammo = GetPickupPropertyValue(pickup, "dropAmmo") + SetPlayerWeapon(player, weapon, ammo, false, useSlot) + local heading = math.deg(math.atan(py - y, px - x)) + 180 + SetPlayerHeading(player, heading) + SetPlayerAnimation(player, "PICKUP_LOWER") + + SavePlayerInventory(player) + else + CallRemoteEvent(player, 'KNotify:Send', "No free space for the weapon", "#f00") + end + else + CallRemoteEvent(player, 'KNotify:Send', "This is a police only weapon!", "#f00") + end + end + end +end +AddRemoteEvent("Kuzkay:ConfirmPickup", OnPickupConfirm) + +function UseItem(player, item) + if GetPlayerItemCount(player, item) > 0 then + CallEvent('Kuzkay:UseItem:' .. item, player, item) + end +end +AddRemoteEvent("Kuzkay:UseItem", UseItem) + +function DestroyDrop(pickup) + if GetPickupPropertyValue(pickup, "dropText") ~= nil then + DestroyText3D(GetPickupPropertyValue(pickup, "dropText")) + end + DestroyPickup(pickup) +end + + + +function GiveItemToPlayer(player, item, amount, toplayer) + amount = tonumber(amount) + toplayer = tonumber(toplayer) + if amount <= 0 then + CallRemoteEvent(player, 'KNotify:Send', "Try me bitch", "#000") + else + if RemovePlayerItem(player, item, amount) then + if AddPlayerItem(toplayer, item, amount) then + if tonumber(amount) > 1 then + CallRemoteEvent(player, 'KNotify:Send', "You gave " .. amount .. ' ' .. Items[item].plural .. " to " .. GetPlayerName(toplayer), "#77f") + else + CallRemoteEvent(player, 'KNotify:Send', "You gave " .. Items[item].title .. " to " .. GetPlayerName(toplayer), "#77f") + end + + if tonumber(amount) > 1 then + CallRemoteEvent(toplayer, 'KNotify:Send', "You recieved " .. amount .. ' ' .. Items[item].plural .. " from " .. GetPlayerName(player), "#77f") + else + CallRemoteEvent(toplayer, 'KNotify:Send', "You recieved " .. Items[item].title .. " from " .. GetPlayerName(player), "#77f") + end + else + AddPlayerItem(player, item, amount) + CallRemoteEvent(player, 'KNotify:Send', "Player does'nt have enough inventory space", "#f00") + end + end + end + +end +AddRemoteEvent("Kuzkay:GiveItemToPlayer", GiveItemToPlayer) + + + + +function GetItemNames(item) + return Items[item].title, Items[item].plural +end +AddFunctionExport("getItemNames", GetItemNames) + + + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/gui/inventory.css b/OKAYY Framework Basic/kuz_Essentials/inventory/gui/inventory.css new file mode 100644 index 0000000..8b64385 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/inventory/gui/inventory.css @@ -0,0 +1,580 @@ +@font-face { + font-family: Yanone Kaffeesatz; + src: url('http://asset/kuz_Essentials/utils/Yanone.ttf'); +} +html, body{ + margin:0 auto; + overflow: hidden; + font-family: 'Yanone Kaffeesatz', sans-serif !important; +} +.inv { + top: 45%; + left: 10%; + position: absolute; + cursor: move; + /*background-color: rgba(20,20,20,0.7);*/ + font-family: 'Yanone Kaffeesatz', sans-serif !important; + border-radius: 0.5vh; + color: white; + margin: 0; + overflow: hidden; + display: block; + height: 33vh; + width: 46vh; + z-index: 0; + box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.6); + + background: linear-gradient(135deg, rgba(50,50,50,0.75) 0%,rgba(10,10,10,0.8) 100%); + user-select: none; +} + + + +.title{ + font-color: #fff; + font-size: 3vh; + text-align: center; + margin: 0.5vh; + margin-top: 1vh; +} +.container{ + display: inline-flex; + flex-wrap: wrap; + justify-content: flex-start; + align-content: flex-start; + height: 25.5vh; + width: 42.5vh; + + margin-bottom: 0.5vh; + margin-top: 0.5vh; + margin-left: 1.5vh; + margin-right: 1.5vh; + float: left; + border-radius: 0.7vh; + z-index: 1; + cursor: default; + + border-top: 2px solid white; + border-bottom: 2px solid white; + + background: -webkit-linear-gradient(left, rgba(0,0,0,0) 0%,rgba(5,1,1,0.22) 25%,rgba(10,1,1,0.3) 50%,rgba(5,1,1,0.22) 75%,rgba(0,0,0,0) 100%); /* Chrome10-25,Safari5.1-6 */ + +} +.itemDrag{ + height: 8.5vh; + width: 8.5vh; +} + +.item{ + opacity: 0.9; + width: 8vh; + height: 8vh; + position: relative; + border-radius: 0.3vh; + background-color: rgba(70, 70, 70, 0.6); + transition-duration: 0.5s; + text-align: bottom; + margin: 0.25vh; + -webkit-box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.4); + -moz-box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.4); + box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.4); + cursor: -webkit-grabbing; +} + + +.itemText{ + text-shadow: 0px 0px 3px rgba(0,0,0,0.5); + transition-duration: 0.5s; + margin: 0; + position: absolute; + z-index: 5; + width: 100%; + top: 100%; + height: 20%; + transform: translate(0%, -100%); + overflow: none; +} +.itemName{ + font-size: 1.6vh; + margin-left: 5%; + margin-bottom: 1%; + margin-top: 10%; + text-align: center; + opacity: 1.0; + color: white; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + position: relative; +} +.itemAmount{ + font-size: 2.4vh; + margin-right: 6%; + margin-bottom: 8%; + margin-top: -8%; + text-align: center; + opacity: 1.0; + color: white; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + position: fixed; + float: right; + transform: rotate(6deg); +} +.itemAmount label{ + font-size: 1.5vh; +} +.itemIcon{ + opacity: 0.9; + height: 90%; + width: 90%; + margin: 5%; + position: relative; + text-align: center; + border-radius: 1vh; + z-index: 4; +} +.exitButton{ + opacity: 0.85; + height: 4vh; + width: 4vh; + float:right; + margin-top: 1vh; + margin-right: 1vh; +} +.signature{ + position: relative; + font-size: 1.2vh; + left: 1.5%; + color: rgba(255,255,255,0.3); + cursor: move; +} +.options_player{ + position: absolute; + opacity: 0.9; + background-color: rgba(130,130,130,0.9); + height: 4.5vh; + width: 11vh; + z-index: 10; +} +.options{ + position: absolute; + opacity: 0.9; + background-color: rgba(130,130,130,0.9); + height: 7.5vh; + width: 11vh; + z-index: 10; +} +.options_player_btn{ + position: relative; + width: 100%; + height: 55%; + + background-color: rgba(50,50,50,0.9); + color: white; + border: 1px solid rgba(100,100,100,0.9); + cursor: pointer; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + font-size: 110%; +} +.options_player_btn:hover{ + background-color: rgba(80,80,80,0.9); +} +.options_player_btn:active{ + background-color: rgba(30,30,30,0.9); +} +.options_player_btn:focus{ + outline: 0; +} +.options_btn{ + position: relative; + width: 100%; + height: 33.3%; + + background-color: rgba(50,50,50,0.9); + color: white; + border: 1px solid rgba(100,100,100,0.9); + cursor: pointer; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + font-size: 110%; +} +.options_btn:hover{ + background-color: rgba(80,80,80,0.9); +} +.options_btn:active{ + background-color: rgba(30,30,30,0.9); +} +.options_btn:focus{ + outline: 0; +} +.options_name{ + height: 30%; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + color: white; + text-align: center; + font-size: 100%; + padding-top: 5%; + position: relative; + justify-content: center; +} +.dropAmountWindow{ + display: block; + visibility: hidden; + position: absolute; + height: 20vh; + width: 35vh; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + margin: 0 auto; + background-color: rgba(70,70,70,0.9); + overflow: hidden; + border-radius: 1.5vh; + z-index: 15; + box-shadow: 0px 0px 250px 25px rgba(0,0,0,0.4); +} +.dropAmountTitle{ + text-align: center; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + color: white; + font-size: 4vh; + margin: 0; + margin-top: 1.1vh; + +} +.allAmountBtn{ + position: absolute; + display: block; + height: 4vh; + width: 6vh; + left: 12.5%; + top: 50%; + transform: translate(-50%, -50%); + text-align: center; + background-color: rgba(50,50,50,0.7); + color: white; + -webkit-border-radius: 3px; + border-radius: 3px; + border: 1px solid rgba(100,100,100,0.2); + cursor: pointer; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + font-size: 100%; +} +.halfAmountBtn{ + position: absolute; + display: block; + height: 4vh; + width: 6vh; + left: 87.5%; + top: 50%; + transform: translate(-50%, -50%); + text-align: center; + background-color: rgba(50,50,50,0.7); + color: white; + -webkit-border-radius: 3px; + border-radius: 3px; + border: 1px solid rgba(100,100,100,0.2); + cursor: pointer; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + font-size: 100%; +} +.dropAmountBtn{ + position: relative; + width: 50%; + height: 33.34%; + margin-top: 25%; + background-color: rgba(50,50,50,0.7); + color: white; + border: 0; + border-top: 1px solid rgba(100,100,100,0.8); + cursor: pointer; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + font-size: 100%; +} +.dropAmountBtn:hover, .allAmountBtn:hover, .halfAmountBtn:hover{ + background-color: rgba(80,80,80,0.8); +} +.dropAmountBtn:active, .allAmountBtn:active, .halfAmountBtn:active{ + background-color: rgba(30,30,30,0.7); +} +.dropAmountBtn:focus, .allAmountBtn:focus, .halfAmountBtn:focus{ + outline: 0; +} +.dropAmountInput{ + position: absolute; + display: block; + height: 4vh; + width: 18vh; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + text-align: center; + outline: 0; + border: 1px solid rgba(0,0,0,0.13); + -webkit-border-radius: 5px; + border-radius: 5px; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + font-size: 3vh; + color: rgba(255,255,255,1); + -o-text-overflow: clip; + text-overflow: clip; + background: rgba(138,138,138,1); + -webkit-box-shadow: 1px 1px 1px 0 rgba(0,0,0,0.61) inset; +} +.dropAmountInput:focus{ + outline: 0; +} +input[type=number]::-webkit-inner-spin-button, +input[type=number]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + + + + + + + + +.nearest { + top: 55vh; + opacity: 0.8; + left: 150vh; + position: absolute; + cursor: move; + /*background-color: rgba(20,20,20,0.7);*/ + font-family: 'Yanone Kaffeesatz', sans-serif !important; + border-radius: 0.5vh; + color: white; + margin: 0; + overflow: hidden; + display: block; + height: 40vh; + width: 20vh; + z-index: 0; + + + box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.6); + + + background: linear-gradient(135deg, rgba(50,50,50,0.75) 0%,rgba(10,10,10,0.8) 100%); + user-select: none; +} +.nearest_container{ + display: block; + justify-content: flex-start; + align-content: flex-start; + height: 33vh; + width: 18vh; + padding-top: 0.5vh; + + margin-bottom: 4vh; + margin-top: 0vh; + margin-left: 1vh; + margin-right: 1vh; + float: left; + border-radius: 1vh; + z-index: 1; + cursor: default; + + border-top: 2px solid white; + border-bottom: 2px solid white; + + background: -moz-linear-gradient(left, rgba(0,0,0,0) 0%, rgba(5,1,1,0.22) 25%, rgba(10,1,1,0.3) 50%, rgba(5,1,1,0.22) 75%, rgba(0,0,0,0) 100%); /* FF3.6-15 */ + background: -webkit-linear-gradient(left, rgba(0,0,0,0) 0%,rgba(5,1,1,0.22) 25%,rgba(10,1,1,0.3) 50%,rgba(5,1,1,0.22) 75%,rgba(0,0,0,0) 100%); /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(to right, rgba(0,0,0,0) 0%,rgba(5,1,1,0.22) 25%,rgba(10,1,1,0.3) 50%,rgba(5,1,1,0.22) 75%,rgba(0,0,0,0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ +} +.near_player{ + height: 11%; + width: 95%; + margin-left: 2.5%; + margin-right: 2.5%; + margin-top: 2%; + margin-bottom: 2%; + border-radius: 0.4vh; + background-color: rgba(70, 70, 70, 0.8); + text-align: center; + display: table; + transition-duration: 0.5s; +} +.near_player_hover{ + transition-duration: 0.3s; + height: 13%; + margin-top: 0%; + margin-bottom: 0%; + background-color: rgba(100, 100, 100, 0.8); +} +.near_name{ + font-size: 2vh; + display: table-cell; + vertical-align: middle; +} + + + + + +.storage{ + top: 45%; + left: 55%; + position: absolute; + cursor: move; + /*background-color: rgba(20,20,20,0.7);*/ + font-family: 'Yanone Kaffeesatz', sans-serif !important; + border-radius: 0.5vh; + color: white; + margin: 0; + overflow: hidden; + display: none; + height: 35vh; + width: 49vh; + z-index: 0; + + + box-shadow: 4px 4px 8px -4px rgba(0,0,0,0.6); + + + background: linear-gradient(135deg, rgba(50,50,50,0.75) 0%,rgba(10,10,10,0.8) 100%); + user-select: none; +} + +.storage_title{ + font-color: #fff; + font-size: 2.1vh; + text-align: center; + margin: 0.36vh; + margin-top: 1.08vh; +} +.storage_container{ + display: inline-flex; + flex-wrap: wrap; + justify-content: flex-start; + align-content: flex-start; + height: 30.24vh; + width: calc(45.36vh + 13px); + + overflow: auto; + overflow-y:scroll; + margin-bottom: 1.08vh; + margin-top: 0.3vh; + margin-left: 1.16vh; + margin-right: 1.16vh; + float: left; + border-radius: 0.72vh; + z-index: 1; + cursor: default; + + border-top: 2px solid white; + border-bottom: 2px solid white; + + background: -moz-linear-gradient(left, rgba(0,0,0,0) 0%, rgba(5,1,1,0.22) 25%, rgba(10,1,1,0.3) 50%, rgba(5,1,1,0.22) 75%, rgba(0,0,0,0) 100%); /* FF3.6-15 */ + background: -webkit-linear-gradient(left, rgba(0,0,0,0) 0%,rgba(5,1,1,0.22) 25%,rgba(10,1,1,0.3) 50%,rgba(5,1,1,0.22) 75%,rgba(0,0,0,0) 100%); /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(to right, rgba(0,0,0,0) 0%,rgba(5,1,1,0.22) 25%,rgba(10,1,1,0.3) 50%,rgba(5,1,1,0.22) 75%,rgba(0,0,0,0) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ +} + + + +.itemStorageDrag{ + height: 7.56vh; + width: 7.56vh; +} + +.itemStorage{ + opacity: 0.9; + width: 7.2vh; + height: 7.2vh; + position: relative; + border-radius: 0.25vh; + background-color: rgba(70, 70, 70, 0.6); + transition-duration: 0.5s; + text-align: bottom; + margin: 0.3vh; + -webkit-box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.58); + -moz-box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.58); + box-shadow: 5px 5px 9px -5px rgba(0,0,0,0.58); + cursor: -webkit-grabbing; +} +.itemStorageText{ + text-shadow: 0px 0px 3px rgba(0,0,0,0.5); + transition-duration: 0.5s; + margin: 0; + position: absolute; + z-index: 5; + width: 100%; + top: 100%; + height: 20%; + transform: translate(0%, -100%); + overflow: none; +} +.itemStorageName{ + font-size: 1.15vh; + margin-left: 5%; + margin-bottom: 1%; + margin-top: 10%; + text-align: center; + opacity: 1.0; + color: white; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + position: relative; +} +.itemStorageAmount{ + font-size: 1.7vh; + margin-right: 6%; + margin-bottom: 8%; + margin-top: -8%; + text-align: center; + opacity: 1.0; + color: white; + font-family: 'Yanone Kaffeesatz', sans-serif !important; + position: relative; + float: right; + transform: rotate(6deg); +} +.itemStorageAmount label{ + font-size: 1vh; +} + +.optionsStorage{ + position: absolute; + opacity: 0.9; + background-color: rgba(130,130,130,0.9); + height: 5vh; + width: 11vh; + z-index: 10; +} +.empty_slot{ + height: 7.56vh; + width: 7.56vh; + position: relative; + background: rgba(0,0,0,0); + order: 99999; +} +.filled_slot{ + height: 7.56vh; + width: 7.56vh; + position: relative; + background: rgba(12,0,0,0.35); + order: 99999; +} + + +/*SCROLLBAR*/ +/* width */ +::-webkit-scrollbar { + width: 13px; + margin-left: 2px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: rgba(0,0,0,0.3); +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: rgba(170,170,170,0.4); + border-radius: 4px; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: rgba(130,130,130,0.4); +} \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/gui/inventory.html b/OKAYY Framework Basic/kuz_Essentials/inventory/gui/inventory.html new file mode 100644 index 0000000..53f7c70 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/inventory/gui/inventory.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/acetone.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/acetone.png new file mode 100644 index 0000000..8f5c633 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/acetone.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/ammo.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/ammo.png new file mode 100644 index 0000000..4425c8f Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/ammo.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/asphalt.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/asphalt.png new file mode 100644 index 0000000..fae565d Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/asphalt.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/bandage.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/bandage.png new file mode 100644 index 0000000..1b3ad44 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/bandage.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/bigfirework.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/bigfirework.png new file mode 100644 index 0000000..c721a68 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/bigfirework.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/calcium.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/calcium.png new file mode 100644 index 0000000..abcd210 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/calcium.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cannabis.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cannabis.png new file mode 100644 index 0000000..09a5455 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cannabis.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/coca.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/coca.png new file mode 100644 index 0000000..a6a69c5 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/coca.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cocaine.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cocaine.png new file mode 100644 index 0000000..c92a937 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cocaine.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cuffs.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cuffs.png new file mode 100644 index 0000000..75945b2 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/cuffs.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/empty.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/empty.png new file mode 100644 index 0000000..2367d76 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/empty.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/exit.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/exit.png new file mode 100644 index 0000000..6395d24 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/exit.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/firework.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/firework.png new file mode 100644 index 0000000..144f31b Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/firework.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/garbage.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/garbage.png new file mode 100644 index 0000000..310754a Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/garbage.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/gas.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/gas.png new file mode 100644 index 0000000..4ec9076 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/gas.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/heroin.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/heroin.png new file mode 100644 index 0000000..06ef722 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/heroin.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/medkit.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/medkit.png new file mode 100644 index 0000000..b5183c3 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/medkit.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/meth.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/meth.png new file mode 100644 index 0000000..b7b95f1 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/meth.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/poppy.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/poppy.png new file mode 100644 index 0000000..b088581 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/poppy.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/repairkit.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/repairkit.png new file mode 100644 index 0000000..2e6e499 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/repairkit.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/unknown.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/unknown.png new file mode 100644 index 0000000..490c64e Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/unknown.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/weed.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/weed.png new file mode 100644 index 0000000..a3aa9c4 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/weed.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/icons/ziptie.png b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/ziptie.png new file mode 100644 index 0000000..804377a Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/inventory/icons/ziptie.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/server.lua b/OKAYY Framework Basic/kuz_Essentials/inventory/server.lua new file mode 100644 index 0000000..bcf2798 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/inventory/server.lua @@ -0,0 +1,253 @@ +local SERVER_ID = 1 + +Items = {} + +Inventories = {} + +Storages = {} + +local wep_loaded = {} + +function OnPackageStart() + Delay(1000, function() + local query = mariadb_prepare(sql, "SELECT * FROM items ORDER BY title;") + mariadb_query(sql, query, GetAllItems) + + local query = mariadb_prepare(sql, "SELECT * FROM `storages` WHERE `server` = '?';", SERVER_ID) + mariadb_query(sql, query, GetStorages) + end) + +end +AddEvent("OnPackageStart", OnPackageStart) + + +function OnRoleSelect(player, role) + + SetPlayerPropertyValue(player, "playerName", GetPlayerName(player), true) + Inventories[player] = {} + Inventories[player].items = {} + Inventories[player].weapons = {} + local query = mariadb_prepare(sql, "SELECT inventory FROM profiles WHERE `steamid` = '?' AND `role` = '?' LIMIT 1;", + tostring(GetPlayerSteamId(player)), + role) + + + mariadb_query(sql, query, GetPlayerInventory, player) +end +AddEvent("Kuzkay:RoleSelected", OnRoleSelect) + +function GetAllItems() + local i = 1 + for i = 1,mariadb_get_row_count() do + local result = mariadb_get_assoc(i) + + Items[result.item] = {} + + Items[result.item].item = result.item + Items[result.item].title = result.title + Items[result.item].plural = result.title_plural + Items[result.item].max = result.max + Items[result.item].order = i; + Items[result.item].model = result.model + Items[result.item].model_scale = result.model_scale + i = i + 1 + end +end + +function GetPlayerInventory(player) + if mariadb_get_row_count() > 0 then + local result = mariadb_get_assoc(1) + if result.inventory ~= nil then + Inventories[player] = jsondecode(result.inventory) + + if Inventories[player].items ~= nil then + local i = 1 + for _ in pairs(Inventories[player].items) do + if Items[Inventories[player].items[i].item] == nil then + print("removed bugged item: " .. Inventories[player].items[i].item) + table.remove(Inventories[player].items, i) + end + i = i + 1 + end + end + + end + wep_loaded[player] = false + if Inventories[player].items == nil then + Inventories[player].items = {} + end + Delay(8000, SetPlayerWeapons, player) + Delay(10500, SendPlayerInventory, player) + end +end + + + +function SendPlayerInventory(player) + CallRemoteEvent(player, "Kuzkay:ClearClientItems") + + if Inventories[player].items ~= nil then + local i = 1 + for _ in pairs(Inventories[player].items) do + CallRemoteEvent(player, "Kuzkay:AddClientItem", Inventories[player].items[i], i, Items[Inventories[player].items[i].item].title, Items[Inventories[player].items[i].item].order) + i = i + 1 + end + end + SavePlayerInventory(player) +end + +function SetPlayerWeapons(player) + if Inventories[player] ~= nil then + if Inventories[player].weapons ~= nil then + if Inventories[player].weapons[1] ~= nil then + SetPlayerWeapon(player, Inventories[player].weapons[1].weapon, Inventories[player].weapons[1].ammo, true, 1) + else + SetPlayerWeapon(player, 1, 1, true, 1) + end + + if Inventories[player].weapons[2] ~= nil then + SetPlayerWeapon(player, Inventories[player].weapons[2].weapon, Inventories[player].weapons[2].ammo, false, 2) + else + SetPlayerWeapon(player, 1, 1, false, 2) + end + + if Inventories[player].weapons[3] ~= nil then + SetPlayerWeapon(player, Inventories[player].weapons[3].weapon, Inventories[player].weapons[3].ammo, false, 3) + else + SetPlayerWeapon(player, 1, 1, false, 3) + end + end + + end + + wep_loaded[player] = true +end + +function SavePlayerInventory(player) + if loaded[player] and wep_loaded[player] then + Inventories[player].weapons = {} + local w, a= GetPlayerWeapon(player, 1) + Inventories[player].weapons[1] = {} + Inventories[player].weapons[1].weapon = w + Inventories[player].weapons[1].ammo = a + local w, a = GetPlayerWeapon(player, 2) + Inventories[player].weapons[2] = {} + Inventories[player].weapons[2].weapon = w + Inventories[player].weapons[2].ammo = a + local w, a= GetPlayerWeapon(player, 3) + Inventories[player].weapons[3] = {} + Inventories[player].weapons[3].weapon = w + Inventories[player].weapons[3].ammo = a + + + local query = mariadb_prepare(sql, "UPDATE `profiles` SET `inventory` = '?' WHERE `steamid` = '?' and `role` = '?';", + jsonencode(Inventories[player]), + + + tostring(GetPlayerSteamId(player)), + PlayerData[player].role) + mariadb_query(sql, query) + end +end + + +function OnPlayerQuit(player) + SavePlayerInventory(player) + Delay(50, function() + Inventories[player] = nil + end) + +end +AddEvent("OnPlayerQuit", OnPlayerQuit) + + + +function SendStorageInventory(player, storage, vehicle) + if Storages[storage] == nil and Storages ~= {} then + CreateStorageInventory(player, storage, vehicle) + else + if vehicle ~= nil then + CallRemoteEvent(player, "Kuzkay:ClearClientStorage", Config.VehicleSlots[GetVehicleModel(vehicle)]) + else + CallRemoteEvent(player, "Kuzkay:ClearClientStorage", Storages[storage].slots) + end + if vehicle ~= nil then + Storages[storage].vehicle = vehicle + end + local i = 1 + for _ in pairs(Storages[storage].items) do + if vehicle ~= nil then + Storages[storage].slots = Config.VehicleSlots[GetVehicleModel(vehicle)] + end + CallRemoteEvent(player, "Kuzkay:AddClientStorage", Storages[storage].items[i], i, Items[Storages[storage].items[i].item].title, Items[Storages[storage].items[i].item].order, storage, Storages[storage].slots) + i = i + 1 + end + SaveStorageInventory(storage) + + end + +end +AddRemoteEvent("Kuzkay:StorageRequest", SendStorageInventory) +AddEvent("Kuzkay:StorageRequest", SendStorageInventory) + +function GetStorages() + local i = 1 + for i = 1,mariadb_get_row_count() do + local result = mariadb_get_assoc(i) + + Storages[result.storage] = {} + if result.inventory ~= nil then + Storages[result.storage] = jsondecode(result.inventory) + end + Storages[result.storage].slots = result.slots + Storages[result.storage].vehicle = 0 + + i = i + 1 + + end + print("kuz_Essentials: Done loading all storages") +end + + +function SaveStorageInventory(storage) + + local query = mariadb_prepare(sql, "UPDATE `storages` SET `inventory` = '?' WHERE `storage` = '?' AND `server` = '?';", + jsonencode(Storages[storage]), + + + storage, + SERVER_ID) + mariadb_query(sql, query, OnSaveStorageInventory, storage) +end +function OnSaveStorageInventory(storage) + +end + +function CreateStorageInventory(player, storage, vehicle, slots_) + local slots = 12 + if vehicle ~= nil then + slots = Config.VehicleSlots[GetVehicleModel(vehicle)] + end + if slots_ ~= nil then + slots = slots_ + end + + if Storages[storage] == nil and storage ~= nil then + Storages[storage] = {} + Storages[storage].items = {} + Storages[storage].slots = slots + local query = mariadb_prepare(sql, "INSERT INTO `storages` (`server`, `inventory`, `storage`, `slots`) VALUES ('?', '?', '?', '?');", + SERVER_ID, + jsonencode(Storages[storage]), + storage, + slots) + mariadb_query(sql, query, OnCreateStorageInventory, storage) + + CallRemoteEvent(player, "Kuzkay:ClearClientStorage", Storages[storage].slots) + end +end +function OnCreateStorageInventory(storage) + print('Created storage save for ' .. storage) +end + + diff --git a/OKAYY Framework Basic/kuz_Essentials/inventory/storages_functions.lua b/OKAYY Framework Basic/kuz_Essentials/inventory/storages_functions.lua new file mode 100644 index 0000000..0e03a12 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/inventory/storages_functions.lua @@ -0,0 +1,264 @@ +function AddStorageItem(storage, item, amount, player) + + local success = false + if tonumber(amount) <= 0 then + return false + else + local slots = 0 + + for _ in pairs(Storages[storage].items) do + slots = slots + 1 + end + + local allowed = false + local locations = 0 + + local a = 1 + local found = 0 + for _ in pairs(Storages[storage].items) do + + if (Storages[storage].items[a].item == item and found == 0) then + + if (Storages[storage].items[a].amount < tonumber(Items[item].max)) then + locations = locations + (tonumber(Items[item].max) - Storages[storage].items[a].amount) + end + end + a = a + 1 + end + + --HAS ENOUGH SPACE TO FILL IN NEW SLOTS + if (amount / tonumber(Items[item].max) <= (Storages[storage].slots - slots)) or (locations + ((Storages[storage].slots - slots) * tonumber(Items[item].max)) >= tonumber(amount)) then + allowed = true + end + + local added = 0 + if allowed then + for i=1,amount do + + local itemCount = 1 + + local foundID = 0 + local rest = 0 + for _ in pairs(Storages[storage].items) do + + if (Storages[storage].items[itemCount].item == item and foundID == 0) then + if (tonumber(Storages[storage].items[itemCount].amount) + 1 <= tonumber(Items[item].max)) and added < tonumber(amount) then + foundID = itemCount + Storages[storage].items[itemCount].amount = math.floor(tonumber(Storages[storage].items[itemCount].amount) + 1) + added = added + 1 + end + end + + itemCount = itemCount + 1 + end + + if foundID == 0 then + Storages[storage].items[itemCount] = {} + Storages[storage].items[itemCount].item = item + Storages[storage].items[itemCount].amount = 1 + end + + end + + success = true + else + return false + end + end + if success then + SaveStorageInventory(storage) + if player ~= nil then + SendStorageInventory(player, storage) + end + return true + else + return false + end + +end +AddFunctionExport("addStorageItem", AddStorageItem) + + + + +function RemoveStorageItem(storage, item, amount, player) + + if tonumber(amount) <= 0 then + return false + else + local possibleCount = 0 + local amount = tonumber(amount) + + + local i = 1 + for _ in pairs(Storages[storage].items) do + + if (Storages[storage].items[i].item == item and possibleCount < amount) then + possibleCount = possibleCount + tonumber(Storages[storage].items[i].amount) + end + + i = i + 1 + end + + if possibleCount >= amount then + + local slots = 0 + for _ in pairs(Storages[storage].items) do + slots = slots + 1 + end + + local itemID = slots + local removeLeft = amount + for i=1, itemID do + + if (Storages[storage].items[itemID].item == item and removeLeft > 0) then + + + if (tonumber(Storages[storage].items[itemID].amount) <= removeLeft) then + removeLeft = removeLeft - tonumber(Storages[storage].items[itemID].amount) + table.remove(Storages[storage].items, itemID) + local r = 1 + for _ in pairs(Storages[storage].items) do + if (r > itemID) then + if Storages[storage].items[r + 1] ~= nil then + Storages[storage].items[r] = Storages[storage].items[r + 1] + end + end + r = r + 1 + end + Storages[storage].items[r] = nil + else + Storages[storage].items[itemID].amount = tonumber(Storages[storage].items[itemID].amount) - removeLeft + removeLeft = 0 + end + + + end + + itemID = itemID - 1 + end + SaveStorageInventory(storage) + if player ~= nil then + SendStorageInventory(player, storage) + end + return true + else + return false + end + end +end +AddFunctionExport("removeStorageItem", RemoveStorageItem) + +function GetStorageItemCount(storage, item) + + amount = tonumber(amount) + local itemCount = 0 + local amount = tonumber(amount) + + + local i = 1 + for _ in pairs(Storages[storage].items) do + + if (Storages[storage].items[i].item == item) then + itemCount = itemCount + tonumber(Storages[storage].items[i].amount) + end + i = i + 1 + end + return tonumber(itemCount) +end +AddFunctionExport("getStorageItemCount", GetStorageItemCount) + +function CreateStorage(storage, player, slots) + if Storages[storage] == nil then + CreateStorageInventory(player, storage, nil, slots) + end +end +AddFunctionExport("createStorage", CreateStorage) + + +function ClearStorage(storage, player) + + local i = 1 + Storages[storage].items = {} + + SaveStorageInventory(storage) + if player ~= nil then + SendStorageInventory(player, storage) + end +end +AddFunctionExport("clearStorage", ClearStorage) + + + + +function split(pString, pPattern) + local Table = {} -- NOTE: use {n = 0} in Lua-5.0 + local fpat = "(.-)" .. pPattern + local last_end = 1 + local s, e, cap = pString:find(fpat, 1) + while s do + if s ~= 1 or cap ~= "" then + table.insert(Table,cap) + end + last_end = e+1 + s, e, cap = pString:find(fpat, last_end) + end + if last_end <= #pString then + cap = pString:sub(last_end) + table.insert(Table, cap) + end + return Table +end + + +local housing = nil +AddEvent("Kuzkay:HousingLoaded", function() + housing = ImportPackage("kuz_Housing") +end) + + +function PutItemInStorage(player, item, amount, storage) + if string.match(storage, "HOUSING-") then + local house = split(storage, "-")[2] + local owner = housing.getOwner(house) + if owner.owner ~= tostring(GetPlayerSteamId(player)) then + CallRemoteEvent(player, "KNotify:Send", "You can't access this storage", "#000") + return + end + end + + if GetPlayerItemCount(player, item) >= tonumber(amount) then + if AddStorageItem(storage, item, tonumber(amount), player) then + RemovePlayerItem(player, item, amount) + else + CallRemoteEvent(player, 'KNotify:Send', "Storage is full", "#f00") + end + else + CallRemoteEvent(player, 'KNotify:Send', "Not enough items", "#f00") + end +end +AddRemoteEvent("Kuzkay:OnPutItemInStorage", PutItemInStorage) + + + + + +function PutItemInInventory(player, item, amount, storage) + if string.match(storage, "HOUSING-") then + local house = split(storage, "-")[2] + local owner = housing.getOwner(house) + if owner.owner ~= tostring(GetPlayerSteamId(player)) then + CallRemoteEvent(player, "KNotify:Send", "You can't access this storage", "#000") + return + end + end + + if GetStorageItemCount(storage, item) >= tonumber(amount) then + if AddPlayerItem(player, item, tonumber(amount)) then + RemoveStorageItem(storage, item, amount, player) + end + else + CallRemoteEvent(player, 'KNotify:Send', "Not enough items in storage", "#f00") + end +end +AddRemoteEvent("Kuzkay:OnPutItemInInventory", PutItemInInventory) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/locations.sql b/OKAYY Framework Basic/kuz_Essentials/locations.sql new file mode 100644 index 0000000..94ed58e --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/locations.sql @@ -0,0 +1,30 @@ +-- -------------------------------------------------------- +-- Host: 127.0.0.1 +-- Server version: 10.1.35-MariaDB - mariadb.org binary distribution +-- Server OS: Win32 +-- HeidiSQL Version: 9.5.0.5338 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!50503 SET NAMES utf8mb4 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; + + +CREATE TABLE IF NOT EXISTS `positions` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `steamid` varchar(50) NOT NULL DEFAULT '0', + `steam_name` varchar(50) NOT NULL DEFAULT '0', + `x` float NOT NULL DEFAULT '0', + `y` float NOT NULL DEFAULT '0', + `z` float NOT NULL DEFAULT '0', + `h` float NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1; + + + +/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; +/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/OKAYY Framework Basic/kuz_Essentials/package.json b/OKAYY Framework Basic/kuz_Essentials/package.json new file mode 100644 index 0000000..65ac4cf --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/package.json @@ -0,0 +1,94 @@ +{ + "author": "Kuzkay", + "version": "1.0", + "server_scripts": [ + "config.lua", + "trunks.lua", + "utils/json.lua", + "atm/config.lua", + "shops/config.lua", + "../database.lua", + "profile/main.lua", + "profile/functions.lua", + "inventory/server.lua", + + "inventory/functions.lua", + "inventory/storages_functions.lua", + + "scoreboard/scoreboard_s.lua", + "atm/server.lua", + "shops/server.lua", + "wtsync/server.lua", + "speedo/server.lua", + "functions_s.lua", + "doors.lua" + ], + "client_scripts": [ + "config.lua", + "atm/config.lua", + "shops/config.lua", + "profile/client.lua", + "inventory/client.lua", + + "scoreboard/scoreboard_c.lua", + "atm/client.lua", + "shops/client.lua", + "wtsync/client.lua", + "speedo/client.lua", + "functions_c.lua" + ], + "files": [ + "inventory/icons/exit.png", + "inventory/icons/unknown.png", + "inventory/icons/empty.png", + "inventory/icons/cannabis.png", + "inventory/icons/coca.png", + "inventory/icons/meth.png", + "inventory/icons/cocaine.png", + "inventory/icons/weed.png", + "inventory/icons/bandage.png", + "inventory/icons/garbage.png", + "inventory/icons/asphalt.png", + "inventory/icons/acetone.png", + "inventory/icons/gas.png", + "inventory/icons/poppy.png", + "inventory/icons/heroin.png", + "inventory/icons/medkit.png", + "inventory/icons/firework.png", + "inventory/icons/bigfirework.png", + "inventory/icons/ammo.png", + "inventory/icons/calcium.png", + "inventory/icons/repairkit.png", + "inventory/icons/ziptie.png", + "inventory/icons/cuffs.png", + + "utils/jquery.js", + "utils/jquery-ui.js", + "utils/Yanone.ttf", + "utils/Bebas.ttf", + + "sounds/drop.wav", + "sounds/click.wav", + + "profile/login_gui/roleSelect.html", + "profile/login_gui/roleSelect.js", + "profile/login_gui/image.png", + "profile/login_gui/loading.gif", + + + "profile/main_gui/main.html", + "profile/main_gui/main.css", + "profile/main_gui/main.js", + "profile/main_gui/img/money.png", + "profile/main_gui/img/bank.png", + "profile/main_gui/img/speedo.png", + + + "inventory/gui/inventory.html", + + + "atm/gui/atm.css", + "atm/gui/atm.js", + "atm/gui/img/paydaybanking.png" + ] +} diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/client.lua b/OKAYY Framework Basic/kuz_Essentials/profile/client.lua new file mode 100644 index 0000000..577a75a --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/client.lua @@ -0,0 +1,138 @@ +local roleSelect = 0 +local mainGui = 0 + +Gui_main = 0 + +function OnPackageStart() + StartCameraFade(1.0, 1.0, 600.0, '#000') +end +AddEvent("OnPackageStart", OnPackageStart) + +function ShowSelectionScreen() + roleSelect = CreateWebUI(0, 0, 0, 0, 5, 30) + LoadWebFile(roleSelect, "http://asset/kuz_Essentials/profile/login_gui/roleSelect.html") + SetWebAlignment(roleSelect, 0.0, 0.0) + SetWebAnchors(roleSelect, 0.0, 0.0, 1.0, 1.0) + SetWebVisibility(roleSelect, WEB_VISIBLE) + + SetIgnoreMoveInput(true) + SetIgnoreLookInput(true) + Delay(1000, function () + SetInputMode(INPUT_GAMEANDUI) + ShowMouseCursor(true) + end) + +end +AddRemoteEvent("Kuzkay:SteamReady", ShowSelectionScreen) + +function SelectRole(role, location) + CallRemoteEvent('Kuzkay:OnRoleSelect', role, location) +end +AddEvent("Kuzkay:OnSelectRole", SelectRole) + + +function OnLoadingComplete() + StartCameraFade(1.0, 0.0, 4.0, "#000") + SetIgnoreMoveInput(false) + SetIgnoreLookInput(false) + ShowMouseCursor(false) + SetInputMode(INPUT_GAME) + SetWebVisibility(roleSelect, WEB_HIDDEN) + DestroyWebUI(roleSelect) + ShowMainUi() + + + SetPostEffect("Global", "Gamma", 0.95,0.95,0.95,0.9) + SetPostEffect("Global", "Gain", 0.95,0.95,0.95,1.0) + SetPostEffect("Global", "Saturation", 1.05,1.05,1.05,1.05) + + SetPostEffect("WhiteBalance", "Temp", 7500) + SetPostEffect("WhiteBalance", "Tint", 0.0) + + + SetPostEffect("Chromatic", "Intensity", 0.0) + SetPostEffect("Chromatic", "StartOffset", 0.0) + + SetPostEffect("MotionWhiteBalanceBlur", "Temp", 7500) + + SetPostEffect("MotionBlur", "Amount", 0.05) + SetPostEffect("MotionBlur", "Max", 1.0) + + SetPostEffect("Bloom", "Insensity", 1.0) + + SetPostEffect("DepthOfField", "DepthBlurRadius", 0.02) + SetPostEffect("DepthOfField", "Distance", 500.0) + SetPostEffect("DepthOfField", "DepthBlurSmoothKM", 0.5) + + SetPostEffect("ImageEffects", "GrainIntensity", 0.0) + SetPostEffect("ImageEffects", "GrainJitter", 1.0) + SetPostEffect("ImageEffects", "VignetteIntensity", 0.4) +end +AddRemoteEvent("Kuzkay:LoadingComplete", OnLoadingComplete) + + +function ShowMainUi() + mainGui = CreateWebUI(0, 0, 0, 0, 5, 45) + LoadWebFile(mainGui, "http://asset/kuz_Essentials/profile/main_gui/main.html") + SetWebAlignment(mainGui, 0.0, 0.0) + SetWebAnchors(mainGui, 0, 0, 1.0, 1.0) + SetWebVisibility(mainGui, WEB_HITINVISIBLE) + Gui_main = mainGui + +end + +local _money = 0 +local _bank = 0 +local _role = "" +local _level = 0 +local _experience = 0 + +function UpdateVisualData(money, bank, role, level, experience) + if mainGui ~= 0 then + _money = money + _bank = bank + _role = role + _level = level + _experience = experience + UpdateWebData() + else + Delay(1000, UpdateVisualData, money, bank, role, level, experience) + end +end +AddRemoteEvent("Kuzkay:UpdateVisualData", UpdateVisualData) + +AddEvent("OnWebLoadComplete", function(ui) + if ui == mainGui then + UpdateWebData() + CallEvent("Kuzkay:MainGuiLoaded", mainGui) + end +end) + +function UpdateWebData() + ExecuteWebJS(mainGui, "UpdateData('".. math.floor(_money) .."','".. math.floor(_bank) .."','".. _role .."','".. math.floor(_level) .."','".. math.floor(_experience) .."');") + if not Config.ShowJob then + ExecuteWebJS(mainGui, "hideJob();") + end + if not Config.ShowLevel then + ExecuteWebJS(mainGui, "hideLevel();") + end + SetWebVisibility(mainGui, WEB_HITINVISIBLE) +end + + +local blind = false + +function ToggleBlindness(key) + if key == "F8" then + blind = not blind + if blind then + StopCameraFade() + else + StartCameraFade(1.0,1.0,5,"ffffff") + end + end +end +AddEvent('OnKeyPress', ToggleBlindness) + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/functions.lua b/OKAYY Framework Basic/kuz_Essentials/profile/functions.lua new file mode 100644 index 0000000..08d1fd5 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/functions.lua @@ -0,0 +1,224 @@ +function SavePlayer(player) + SavePlayerData(player) + SavePlayerInventory(player) + SendPlayerInventory(player) +end +AddFunctionExport("savePlayer", SavePlayer) + +--PlayerData + +function GetPlayerData(player) + return PlayerData[player] +end +AddFunctionExport("getPlayerData", GetPlayerData) + +--ROLE +function GetPlayerRole(player) + if PlayerData[player] ~= nil then + return PlayerData[player].role + else + return "" + end +end +AddFunctionExport("getPlayerRole", GetPlayerRole) + +--JOB +function SetPlayerJob(player, job, grade) + grade = tonumber(grade) + if Jobs[job] ~= nil and Jobs[job].grades[grade] ~= nil and PlayerData[player] ~= nil then + PlayerData[player].job = job + PlayerData[player].job_grade = grade + PlayerData[player].job_title = Jobs[job].title + PlayerData[player].job_grade_title = Jobs[job].grades[tonumber(grade)].grade_title + CallEvent("OnJobChange", player, job, grade) + CallRemoteEvent(player, "OnJobChange", job, grade) + SavePlayerData(player) + return true + else + return false + end +end +AddFunctionExport("setPlayerJob", SetPlayerJob) + +function GetPlayerJob(player) + if PlayerData[player] ~= nil then + + if PlayerData[player].job ~= nil then + return PlayerData[player].job + else + return '' + end + else + return '' + end +end +AddFunctionExport("getPlayerJob", GetPlayerJob) + +function GetPlayerJobGrade(player) + if PlayerData[player] ~= nil then + + if PlayerData[player].job_grade ~= nil then + return tonumber(PlayerData[player].job_grade) + else + return 1 + end + else + return 1 + end +end +AddFunctionExport("getPlayerJobGrade", GetPlayerJobGrade) + +--MONEY + +function GetPlayerMoney(player) + return tonumber(PlayerData[player].money) +end +AddFunctionExport("getMoney", GetPlayerMoney) + + +function AddPlayerMoney(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].money = PlayerData[player].money + amount + SavePlayerData(player) + end +end +AddFunctionExport("addMoney", AddPlayerMoney) + + +function RemovePlayerMoney(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].money = PlayerData[player].money - amount + SavePlayerData(player) + end +end +AddFunctionExport("removeMoney", RemovePlayerMoney) + + +--BANK + +function GetPlayerBank(player) + return tonumber(PlayerData[player].bank) +end +AddFunctionExport("getBank", GetPlayerBank) + + +function AddPlayerBank(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].bank = PlayerData[player].bank + amount + SavePlayerData(player) + end +end +AddFunctionExport("addBank", AddPlayerBank) + + +function RemovePlayerBank(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].bank = PlayerData[player].bank - amount + SavePlayerData(player) + end +end +AddFunctionExport("removeBank", RemovePlayerBank) + + +-- LEVEL + +function GetPlayerLevel(player) + return PlayerData[player].level +end +AddFunctionExport("getLevel", GetPlayerLevel) + + +function AddPlayerLevel(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].level = PlayerData[player].level + amount + SavePlayerData(player) + end +end +AddFunctionExport("addLevel", AddPlayerLevel) + + +function RemovePlayerLevel(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].level = PlayerData[player].level - amount + PlayerData[player].experience = 0 + SavePlayerData(player) + end +end +AddFunctionExport("removeLevel", RemovePlayerLevel) + + +-- EXPERIENCE + +function GetPlayerExperience(player) + return PlayerData[player].experience +end +AddFunctionExport("getExperience", GetPlayerExperience) + + +function AddPlayerExperience(player, amount) + amount = tonumber(amount) + if amount > 0 then + + if (PlayerData[player].experience + amount) >= (PlayerData[player].level * (PlayerData[player].level/2) * 50) then + + local restXP = (PlayerData[player].experience + amount) - (PlayerData[player].level * (PlayerData[player].level/2) * 50) + print(restXP) + PlayerData[player].level = PlayerData[player].level + 1 + PlayerData[player].experience = restXP + SavePlayerData(player) + else + amount = math.floor(amount) + PlayerData[player].experience = PlayerData[player].experience + amount + SavePlayerData(player) + end + + + end +end +AddFunctionExport("addExperience", AddPlayerExperience) + + +function RemovePlayerExperience(player, amount) + amount = tonumber(amount) + if amount > 0 then + amount = math.floor(amount) + PlayerData[player].experience = PlayerData[player].experience - amount + SavePlayerData(player) + end +end +AddFunctionExport("removeExperience", RemovePlayerExperience) + + + +function GiveMoneyToPlayer(player, amount, toplayer) + amount = tonumber(amount) + toplayer = tonumber(toplayer) + if amount <= 0 then + CallRemoteEvent(player, 'KNotify:Send', "Try me bitch", "#000") + else + if GetPlayerMoney(player) >= amount then + RemovePlayerMoney(player, amount) + AddPlayerMoney(toplayer, amount) + CallRemoteEvent(player, 'KNotify:Send', "You gave $" .. amount .. ' to ' .. GetPlayerName(toplayer), "#77f") + CallRemoteEvent(toplayer, 'KNotify:Send', "You recieved $" .. amount .. ' to ' .. GetPlayerName(player), "#77f") + else + CallRemoteEvent(player, 'KNotify:Send', "You don't have enough cash", "#f00") + end + end + +end +AddRemoteEvent("Kuzkay:GiveMoneyToPlayer", GiveMoneyToPlayer) + + diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/image.png b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/image.png new file mode 100644 index 0000000..a901a9f Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/image.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/loading.gif b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/loading.gif new file mode 100644 index 0000000..4e60de9 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/loading.gif differ diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/roleSelect.html b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/roleSelect.html new file mode 100644 index 0000000..dc91b3d --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/roleSelect.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/roleSelect.js b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/roleSelect.js new file mode 100644 index 0000000..987ed5b --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/login_gui/roleSelect.js @@ -0,0 +1 @@ +var a=['SwERw6/Cv1Y/','Lz8NXMOWdQ==','dx7DhsK3w69WNcKqw68=','wpjDtA/CiMOP','w5BQRcKZw6LDl8OrADs=','SMO3w43CtQ==','OcKUwqvDqBd1w7R0woA=','wq4Cw71ww6U=','ecKawozDmAk=','w5VFWw==','w4TCn8OHw50bF8OeeQ==','BMKqw5c=','NX3CuU7CtMKxdzk5N1/ClxMHXTs=','w5vDnsKFwq7CrcKAw5Y=','aAHDuA==','DMKFYMK+YMOlw6M=','wo7CsMOzw65D','I8Kyw63DrUA=','wqbDkMOKw7zDkcKE','TcOWGsOXLhkiNcKT','Sh7CqA==','flrDm8OVeh80QSjDtsOqPnXDoMOxVkrCv8OBfzjCon/Ckw==','w4FFVMKbw6vDgsOtEyzCgcOqw6Y8w6wnw6w=','RMK1w4XClwBhB1URw4XCj1PCu8Ki','WcKvdx/DpsO+SsOUcg==','BlLDl8KIwqvCvXw/aAXCjcOYbg==','LsKsw63DokTDl3nDm8OPOcKZw5zDqgDClcKJ','wphjaA==','AQpJG15Yw5DCosO9EA0Xw5g=','AcKZYMKxaMOyw6/CssK2ICPDmDnCuMK4w5k=','fcK2wpw=','w6LCoVE=','dsOYwrIzwqglIsKRwoLDsVQPw5jCv8KmGQ==','YMOJwp/CrsOXSw==','MMOWwpXDqsOBVjzCug92cx9LKMK9CXTCs8Oyw4IMWxTCnsOt','w5rDtBbCisOTwpHCj8KAwpg=','wpvDgsKDwqHCrw==','UsKdQw==','wpvDncKZ','w4fDo1c=','wpZ5w7sEwrTDqg==','RsKdTDplTcKew4Edw6ELwoZbTDnCqw==','w51aQsO9w4cKFzLDo8KscRDDq3AR','LcOtwqnCnA49','eVnDiMKGFcKXdMOF','EcK4w4g=','EB5Y','TcO5w5LCtMOMw7E=','LzzCtlQHS8Kmw4E2wrRnwqc1F8Ky','w6AdajNMwoI=','wp1NWMK8wpxXTm7Cq8K8L0fCpSAQeMKXw7gNOEPDhhXDsHA=','NHDCs0bCuA==','wpDDhcOww4LDgA==','w5HCjMOC','J8OWJcK6XU1Nw6DCjsKgFMKaasKJdcKv','dwzDmQ==','S8KwQGU9J1Nwwo8edGhxw6lKw44=','a8ObKcKyW0tLw7rCjsKbSsKcacKAecKp','JD7DvcK3DMOXwqnCqMKWYx7Cv8ONSik=','d8OKwqI=','BQxH','QsOPMMKyXUAew4DCjsKsAsKTY8KPYsKJA8Opbw==','A8O6w6rCi8O4','w4tUU8OswoNZWw==','M1bDh8KAFsKd','wqECdDZQ','w5fCszE7w5g=','UMKSwpXCh8Kx','D8OFGMOSOg==','wpvDgcKEwrHCq8KPw5Y=','CcKzSA==','w6cKezJZwoQxZ8KK','WsO/I0pM','RMOGCH5t','RSMow4jClw==','B8KQQDJjS8KYw5sd','wqDDnsOK','SwzCuMKHKhsTFMOFRsKKZsOGCMOKWA==','w5XCisOMw5FaScKTJRFjw5pUw5o=','JSIS','GMKiexfDoMO4TMOOcsOZO3skMcOfbA==','WwrCucKNZVtJVMKHEsKLNcKFVcKM','OQLDs8Opw7vCgMKGwoYJbcKYwrwOwqE/w7MNUMK3w7UYbcOWwqo/','CBAFGRkGwo/DpsKjVUJTwp5Mw7TDqzDDhwLClXLDp0bCr8O/w55ywqHCiEJFbg==','PcK3woDCs8KR','KzrCuA==','EsOvw7DCjMO6wr9UT8OOfMOmEMKEHcK4QQ==','KsOKJcK1VVpB','LMOtwrXCiwQjwr4=','FMKtw5bCjRpZAlwL','ShoQw7DCoQ==','wrXDkMOIw6bDncKNDw==','wrZTQA==','ITjDrcK4','w6HDnCkkBg==','YhzDrcKm','w4BLWcKDw6PDnMOn','w7rCliY9w7w=','MmTCuUDCo8K3cSM5','wqLDjcOHw7bDlw==','ecKkwoLCug==','Z8Khw6/DpA==','wotTZcKRMQ==','wqbCqcOgw6ZJwqdTwr/Dq8KMw6PDicKZcHlUSMKBag==','wrZTRl9ww4PChA=='];(function(c,d){var e=function(f){while(--f){c['push'](c['shift']());}};e(++d);}(a,0x141));var b=function(c,d){c=c-0x0;var e=a[c];if(b['zCHlvw']===undefined){(function(){var f;try{var g=Function('return\x20(function()\x20'+'{}.constructor(\x22return\x20this\x22)(\x20)'+');');f=g();}catch(h){f=window;}var i='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';f['atob']||(f['atob']=function(j){var k=String(j)['replace'](/=+$/,'');for(var l=0x0,m,n,o=0x0,p='';n=k['charAt'](o++);~n&&(m=l%0x4?m*0x40+n:n,l++%0x4)?p+=String['fromCharCode'](0xff&m>>(-0x2*l&0x6)):0x0){n=i['indexOf'](n);}return p;});}());var q=function(r,d){var t=[],u=0x0,v,w='',x='';r=atob(r);for(var y=0x0,z=r['length'];y") + end + Jobs[result.job].grades[tonumber(result.job_grade)] = {} + + Jobs[result.job].grades[tonumber(result.job_grade)].grade = result.job_grade + Jobs[result.job].grades[tonumber(result.job_grade)].grade_title = result.job_grade_title + Jobs[result.job].grades[tonumber(result.job_grade)].paycheck = result.paycheck + + i = i + 1 + end + paycheckTimer = CreateTimer(SendPaychecks, Config.PaycheckTime) + print("kuz_Essentials: Loaded all jobs and job grades") + +end + +AddEvent("OnPlayerJoin", function (player) + loaded[player] = false +end) + +function SendPaychecks() + for _, v in pairs(GetAllPlayers()) do + local job = GetPlayerJob(v) + local grade = GetPlayerJobGrade(v) + local paycheck = tonumber(Jobs[job].grades[tonumber(grade)].paycheck) + if paycheck > 0 then + AddPlayerBank(v, paycheck) + CallRemoteEvent(v, "KNotify:Send", "Recieved paycheck [$" .. paycheck .. "]", "#e69c09") + end + end +end + + + +function SteamAuthenticated(player) + CallRemoteEvent(player, "Kuzkay:SteamReady") +end +AddEvent("OnPlayerSteamAuth", SteamAuthenticated) + +function OnRoleSelect(player, role, location) + loaded[player] = false + if role == "criminal" then + CreatePlayerData(player) + + SetPlayerPropertyValue(player, "playerName", GetPlayerName(player), true) + print(GetPlayerPropertyValue(player, "playerName") .. " loaded in as a " .. role) + + PlayerData[player].role = role + PlayerData[player].load_location = location + local query = mariadb_prepare(sql, "SELECT `id` FROM `profiles` WHERE `steamid` = '?' AND `role` = '?' LIMIT 1;", + tostring(GetPlayerSteamId(player)), + PlayerData[player].role) + + mariadb_query(sql, query, GetPlayerProfile, player, location) + + SetPlayerSpawnLocation(player, Config.criminal.x, Config.criminal.y, Config.criminal.z + 200, Config.criminal.h) + end +end +AddRemoteEvent("Kuzkay:OnRoleSelect", OnRoleSelect) + +function GetPlayerProfile(player, location) + + if (mariadb_get_row_count() == 0) then + CreateProfile(player) + else + Delay(500,LoadProfile,player) + end +end + + +function LoadProfile(player) + local query = mariadb_prepare(sql, "SELECT * FROM profiles WHERE steamid = '?' AND `role` = '?' LIMIT 1;", + tostring(GetPlayerSteamId(player)), + PlayerData[player].role + ) + + mariadb_query(sql, query, OnProfileLoaded, player) +end + +function OnProfileLoaded(player) + + local result = mariadb_get_assoc(1) + + local location = PlayerData[player].load_location + + PlayerData[player].money = result['money'] + PlayerData[player].bank = result['bank'] + PlayerData[player].level = result['level'] + PlayerData[player].experience = result['experience'] + + PlayerData[player].dead = result['dead'] + PlayerData[player].donator = result['donator'] + + + + if Jobs[result['job']] ~= nil then + PlayerData[player].job = result['job'] + PlayerData[player].job_grade = result['job_grade'] + PlayerData[player].job_title = Jobs[result['job']].title + PlayerData[player].job_grade_title = Jobs[result['job']].grades[tonumber(result['job_grade'])].grade_title + + CallEvent("OnJobChange", player, PlayerData[player].job, PlayerData[player].job_grade) + CallRemoteEvent(player, "OnJobChange", PlayerData[player].job, PlayerData[player].job_grade) + + else + PlayerData[player].job = "unemployed" + PlayerData[player].job_grade = 1 + PlayerData[player].job_title = Jobs['unemployed'].title + PlayerData[player].job_grade_title = Jobs['unemployed'].grades[1].grade_title + end + + if location == "last_location" then + PlayerData[player].position = result['position'] + else + PlayerData[player].position = locations[tonumber(location)] + end + ApplyData(player) +end + +function ApplyData(player) + + + local position = PlayerData[player].position + local x, y, z, h = position:match("([^,]+),([^,]+),([^,]+),([^,]+)") + CallEvent("SafeTeleport", player, x, y, z + 200) + SetPlayerHeading(player, h) + SetPlayerPropertyValue(player, 'job', PlayerData[player].job, true) + + CallEvent("Kuzkay:RoleSelected", player, PlayerData[player].role) + + loaded[player] = true + Delay(8000, function () + CallRemoteEvent(player, "Kuzkay:UpdateVisualData", PlayerData[player].money, PlayerData[player].bank, (PlayerData[player].job_title .. " - " .. PlayerData[player].job_grade_title), PlayerData[player].level, PlayerData[player].experience) + SetPlayerPropertyValue(player, 'loaded', true, true) + CallRemoteEvent(player, 'Kuzkay:LoadingComplete') + CallEvent("Kuzkay:LoadingComplete", player) + if tonumber(PlayerData[player].dead) == 1 then + CallEvent("Kuzkay:RejoinDeath", player) + end + if tonumber(PlayerData[player].donator) >= 1 then + CallRemoteEvent(player, "Kuzkay:EnableVIPAnimations") + end + end) + + +end + +function CreateProfile(player) + + local job = "unemployed" + + local savePosition = Config.criminal.x .. ',' .. Config.criminal.y .. ',' .. Config.criminal.z .. ',' .. Config.criminal.h + if PlayerData[player].role == 'police' then + job = "police" + savePosition = Config.police.x .. ',' .. Config.police.y .. ',' .. Config.police.z .. ',' .. Config.police.h + end + + + + + print("creating") + local query = mariadb_prepare(sql, "INSERT INTO `profiles` (`steamid`, `name`, `money`, `bank`, `level`, `experience`, `position`, `inventory`, `role`, `job`, `donator`) VALUES ('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?');", + tostring(GetPlayerSteamId(player)), + GetPlayerName(player), + Config.StartMoney, + Config.StartBank, + 1, + 0, + savePosition, + "[]", + PlayerData[player].role, + job, + 0 + ) + mariadb_query(sql, query, OnProfileCreated, player) + +end +function OnProfileCreated(player) + LoadProfile(player) +end + + + +function SaveAllData() + for _, player in ipairs(GetAllPlayers()) do + if loaded[player] then + SavePlayerData(player) + Delay(5000, SavePlayerInventory, player) + end + end +end + +function SavePlayerData(player) + if loaded[player] then + local x,y,z = GetPlayerLocation(player) + local h = GetPlayerHeading(player) + + local position = x .. ',' .. y .. ',' .. z .. ',' .. h + + + + local query = mariadb_prepare(sql, "UPDATE `profiles` SET `money` = '?', `bank` = '?' , `position` = '?', `level` = '?', `experience` = '?', `job` = '?', `job_grade` = '?' WHERE `steamid` = '?' and `role` = '?';", + math.floor(PlayerData[player].money), + math.floor(PlayerData[player].bank), + position, + PlayerData[player].level, + PlayerData[player].experience, + PlayerData[player].job, + PlayerData[player].job_grade, + + tostring(GetPlayerSteamId(player)), + PlayerData[player].role) + + mariadb_query(sql, query, OnSavePlayerData, player) + + end +end +function OnSavePlayerData(player) + CallRemoteEvent(player, "Kuzkay:UpdateVisualData", PlayerData[player].money, PlayerData[player].bank , (PlayerData[player].job_title .. " - " .. PlayerData[player].job_grade_title), PlayerData[player].level, PlayerData[player].experience) +end + +function CreatePlayerData(player) + PlayerData[player] = {} + PlayerData[player].money = 0 + PlayerData[player].bank = 0 + PlayerData[player].level = 1 + PlayerData[player].experience = 0 + PlayerData[player].position = '' + PlayerData[player].role = '' + PlayerData[player].job = '' + PlayerData[player].job_grade = 0 + PlayerData[player].job_title = '' + PlayerData[player].job_grade_title = '' + PlayerData[player].dead = 0 + PlayerData[player].donator = 0 +end + + +function OnPlayerQuit(player) + SavePlayerData(player) + Delay(50, function() + PlayerData[player] = nil + loaded[player] = false + end) +end +AddEvent("OnPlayerQuit", OnPlayerQuit) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/bank.png b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/bank.png new file mode 100644 index 0000000..6fa2e9f Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/bank.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/money.png b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/money.png new file mode 100644 index 0000000..d09d30a Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/money.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/speedo.png b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/speedo.png new file mode 100644 index 0000000..e479ade Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/img/speedo.png differ diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.css b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.css new file mode 100644 index 0000000..1de0bb4 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.css @@ -0,0 +1,316 @@ +@font-face { + font-family: Yanone Kaffeesatz; + src: url('http://asset/kuz_Essentials/utils/Yanone.ttf'); +} +@font-face { + font-family: bebas-neue; + src: url('http://asset/kuz_Essentials/utils/Bebas.ttf'); +} +html{ + overflow: hidden; + user-select: none; +} +body { + transition-duration: 2s; + font-family: "Arial"; + color: white; + margin: 0; + overflow: hidden; + +} +h1{ + font-color: #fff; + font-size: 1.9vh; + margin: 0; + margin-left: 35%; + margin-top: 1vh; + clear: both; +} +.role h1{ + margin-left: 15%; +} +h2{ + font-color: #fff; + font-size: 1.7vh; + margin-left: 35%; + position: absolute; + z-index: 5; + margin: 0; + margin-left: 35%; + margin-top: 0.7vh; +} +.discord{ + position: fixed; + right: 4vw; + top: 0px; + background-color: rgba(70,70,70,0.15); +} +.discord label{ + color: white; + font-size: 1.5vh; +} + +.dImage{ + float: right; + margin-bottom: 0vh; + margin-top: -2.9vh; + margin-right: 1vh; + width: 2.5vh; + height: auto; + clear: both; +} +.level{ + position: relative; + + height: 2.5vh; +} +.container{ + position: fixed; + right: 0; + top: 0%; + height: 15%; + width: 10%; + display:block; + overflow: hidden; + background: -moz-linear-gradient(360deg, rgba(255,255,255,0) 0%, rgba(0,0,0,0.3) 100%); /* ff3.6+ */ + background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255,255,255,0)), color-stop(100%, rgba(0,0,0,0.55))); /* safari4+,chrome */ + background: -webkit-linear-gradient(360deg, rgba(255,255,255,0) 0%, rgba(0,0,0,0.3) 100%); /* safari5.1+,chrome10+ */ + background: -o-linear-gradient(360deg, rgba(255,255,255,0) 0%, rgba(0,0,0,0.3) 100%); /* opera 11.10+ */ + background: -ms-linear-gradient(360deg, rgba(255,255,255,0) 0%, rgba(0,0,0,0.3) 100%); /* ie10+ */ + background: linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(0,0,0,0.3) 100%); /* w3c */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#000000',GradientType=1 ); /* ie6-9 */ + padding-bottom: 0.5vh; + padding-top: 8%; +} + +.block{ + position: relative; + height: 3.2vh; + margin-bottom: 0.8vh; + margin-top: 0.8vh; + overflow: hidden; +} +.border{ + border:1px solid rgba(255,255,255,0.7)!important; + height: 2vh; + margin-right: 5%; + margin-left: 5%; + margin-top: 0.5vh; + margin-bottom: 0.5vh; + border-radius: 0.65vh; + overflow: hidden; +} +.levelBar{ + background-color: rgba(252, 107, 3, 0.6) !important; + overflow: hidden; + position: relative; + z-index: 1; + height: 100%; +} + + +.deathscreen{ + position: fixed; + margin: 0; + display: none; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.85); +} +.deathscreen h1{ + position: fixed; + font-size: 5vh; + margin: 0; + top: 10%; + left: 50%; + transform: translate(-50%, 0); +} + + + + + + +.speedo{ + overflow: visible !important; + opacity: 0.6; + background: url(http://asset/kuz_Essentials/profile/main_gui/img/speedo.png); + background-repeat: no-repeat; + background-size: cover; + width: 34vh; + height: 16vh; + position: fixed; + bottom: 0; + left: 50%; + transform: translate(-50%, 5%); + + font-family: "Arial"; + color: white; + display: none; + justify-content: space-around; + align-items: center; +} + +.speed{ + background-color: red; + width: 1vh; + height: 1vh; + border-radius: 50%; + transition-duration: 0.2s; + transform: translate(0.1vh, 0); +} +.speed::after{ + content: ''; + display: block; + background-color: red; + height: 7vh; + width: 0.3vh; + transform: translate(0.3vh, 0%); +} + + +.rpm{ + transform: translate(0.1vh, 0); + background-color: red; + width: 1vh; + height: 1vh; + border-radius: 50%; + transition-duration: 0.2s; +} +.rpm::after{ + content: ''; + display: block; + background-color: red; + height: 6.8vh; + width: 0.3vh; + transform: translate(0.3vh, 0%); +} + + +.scoreboard_main{ + display: none; +} +.scoreboard_container{ + display: inline-block; + background: url("http://asset/kuz_Essentials/profile/login_gui/image.png"), linear-gradient(to left, #000000, #f78d1b); + color: white; + border-radius: 0.7vh; + font-family: bebas-neue, sans-serif !important; + opacity: 0.85; + margin: 0vh; + padding: 0.5vh; + max-height: 80vh; +} + +#playertable, .keybind_table{ + font-family: bebas-neue, sans-serif !important; + border-collapse: collapse; + width: 100%; + color: white; + font-size: 1.8vh; +} + +.scoreboard_container table{ + max-height: 78vh; + overflow: scroll !important; +} + +#playertable tr td, #playertable tr th, .keybind_table thead tr td, .keybind_table thead tr th, .keybind_table tbody tr td, .keybind_table tbody tr th { + border-top: 1px solid #dddddd; + text-align: left; + padding: 6px; +} +#playertable tr:nth-child(even), .keybind_table thead tr:nth-child(even), .keybind_table tbody tr:nth-child(even){ + background-color: rgba(0, 0, 0, 0.1); + color: white; +} +.scoreboard{ + position: fixed; + top: 5%; + margin-right: 35vw; + margin-left: 35vw; + bottom: 5%; + height: 90%; + width: 30vw; + display: flex; + justify-content: center; + align-items: center; +} + +#playercount { + float: right; +} +.ping{ + width: 1.5vh; + height: 1.5vh; + border-radius: 2vh; + background: #ff0000; +} +#servername{ + font-size: 2vh; + margin-bottom: 0.4vh; +} +#playercount{ + font-size: 2vh; + margin-bottom: 0.4vh; +} + +.keybinds{ + font-size: 1.8vh; + opacity: 0.85; + position: fixed; + float: right; + margin: 0; + top: 100%; + color: white; + height: auto; + transform: translate(0,-100%); + width: 20%; + background: rgba(50,50,50,0.3); +} +.keybinds table{ + height: 100%; +} + + + + + + + + + + + + + + + +.signature.gar{ + position: relative; + font-size: 1.2vh; + left: 1.5%; + color: rgba(255,255,255,0.3); + cursor: move; +} + +/*SCROLLBAR*/ +/* width */ +::-webkit-scrollbar { + width: 13px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: #9fa19f; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + background: #474747; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #242424; +} \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.html b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.html new file mode 100644 index 0000000..2ce9f04 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.html @@ -0,0 +1,164 @@ + + + + + + + + + + +
+
+
+

+
+
+

+
+
+

+
+
+

+
+
+
+
+
+ + + +
+
+
+
+
+ BALANCE: +
+
+
+
+ CASH: +
+
+
+
+ +
+
+
+
+ + +
+
+
+ +
+

You are unconscious

+
+ +
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionKeybind
InteractE
Pickup Item/WeaponE
Toggle InventoryF2
Toggle PhoneF1 or Ctrl + P
Open TrunkU
Toggle HandsupX (+ CTRL to kneel)
Drop WeaponCTRL + G
Toggle vehicle lockCTRL + L
Animations menuB (Double tap to repeat)
Housing menuCTRL + H
+
+ + + +
+
+ Servername + 0 / 10 + + + + + + + + + + + + + + +
IDPlayerJobPing
----
+
+
+
+ + + + + \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.js b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.js new file mode 100644 index 0000000..f4040e9 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/profile/main_gui/main.js @@ -0,0 +1,183 @@ +function UpdateData(money, bank, role, level, experience) { + + var role = role.charAt(0).toUpperCase() + role.slice(1); + + + var str = '$' + parseInt(money).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); + var newStr = str.substring(0, str.length - 3); + + $("#money").text(newStr); + + var str = '$' + parseInt(bank).toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); + var newStr = str.substring(0, str.length - 3); + + $("#bank").text(newStr); + + + + $('#role').text(role); + $('#level').text('Level ' + level); + var xpPercentage = experience / (level * (level/2) * 50) * 100; + if(xpPercentage > 100){ + xpPercentage = 100; + } + $('#levelBar').css("width", xpPercentage + "%"); + $('#container').css('transform', "translate(0%, 0px)"); + +} +function hideJob(){ + $(".role").hide(); +} +function hideLevel(){ + $(".level").hide(); +} + + + +function SetVehicleSpeed(speed, rpm) { + var speed = Math.abs(speed) / 1.609; + $(".speed").css("transform", "rotate("+ (speed + 39) +"deg)"); + $(".rpm").css("transform", "rotate("+ ((rpm / 37) + 33) +"deg)"); + + //$('#speed').text(speed); + $('#rpm').text(rpm); +} + +function ToggleSpeedo(bool){ + if(bool){ + $(".speedo").fadeIn(400).css("display","flex");; + }else{ + $(".speedo").fadeOut(400); + } +} + +function ToggleScoreboard(bool){ + if(bool){ + $(".scoreboard_main").fadeIn(200); + }else{ + $(".scoreboard_main").fadeOut(150); + } +} + +function SetServerName(name) { + $('#servername').html(name); +} + +function SetPlayerCount(count, max) { + $('#playercount').text(count + " / " + max); +} + +function RemovePlayers() { + $('.player').remove(); +} + +function AddPlayer(id, name, job, ping) { + + var color = "#555555"; + if(ping < 50){ + color = "#63f250"; + }else if(ping < 75){ + color = "#f2ef50"; + }else if(ping < 125){ + color = "#f29c50"; + }else{ + color = "#f25050"; + } + + var job_ = job.charAt(0).toUpperCase() + job.slice(1) + $('#playertable').append(''+id+''+name+''+job_+'
'); +} + + + +function ToggleAnimations(bool) { + if(bool){ + $(".animations").fadeIn(50); + }else{ + $(".animations").fadeOut(30); + } +} + +function ShowVipAnimations(){ + $(".vip").show(); +} + +function PlayAnimation(anim){ + $(".anim-sub-menu").css("height", "0vh"); + CallEvent("Kuzkay:PlayAnim",anim); +} + +$(document).ready(function(){ + $(".anim-category").mouseover(function(e){ + $(".anim-sub-menu").css("height", "0vh"); + $(this).find('.anim-sub-menu').css("height", "100vh"); + }); +}); + + + + + + + + + + + + + + + + + + + + +function ToggleGarage(bool) { + if(bool){ + $(".garage").show(); + }else + { + $(".garage").hide(); + } +} + +function InsertVehicle(id, model, car_name, plate){ + + $(".gar-container").append('

'+car_name+'

'+plate+'

'); + +} + +function UpdateColor(id, bool) +{ + if(bool == "in"){ + $("#" + id).css("background", "linear-gradient(90deg, rgba(55,55,55,1) 0%, rgba(110,110,110,1) 100%)"); + }else{ + $("#" + id).css("background", "linear-gradient(90deg, rgba(70,55,55,1) 0%, rgba(130,110,110,1) 100%)"); + } +} + +function TakeOut(e){ + var plate = $(e).parent().parent().attr("vehicle_plate"); + var id = $(e).parent().parent().attr("vehicle_id"); + CallEvent("Kuzkay:GarageTakeOut", plate, id); + playClick(); +} +function Store(e){ + var plate = $(e).parent().parent().attr("vehicle_plate"); + var id = $(e).parent().parent().attr("vehicle_id"); + CallEvent("Kuzkay:GarageStore", plate, id); + playClick(); +} +function Locate(e){ + var plate = $(e).parent().parent().attr("vehicle_plate"); + var id = $(e).parent().parent().attr("vehicle_id"); + CallEvent("Kuzkay:GarageLocate", plate, id); + playClick(); +} + + +function playClick(){ + var audio = new Audio('http://asset/kuz_Garage/sounds/click.wav'); + audio.play(); +} \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/scoreboard/scoreboard_c.lua b/OKAYY Framework Basic/kuz_Essentials/scoreboard/scoreboard_c.lua new file mode 100644 index 0000000..d0ac55f --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/scoreboard/scoreboard_c.lua @@ -0,0 +1,39 @@ +local sb_timer = 0 + + +function OnKeyPress(key) + if key == "Tab" then + if IsValidTimer(sb_timer) then + DestroyTimer(sb_timer) + end + sb_timer = CreateTimer(UpdateScoreboardData, 1500) + UpdateScoreboardData() + ExecuteWebJS(Gui_main, "ToggleScoreboard(true);") + end +end +AddEvent("OnKeyPress", OnKeyPress) + +function OnKeyRelease(key) + if key == "Tab" then + DestroyTimer(sb_timer) + ExecuteWebJS(Gui_main, "ToggleScoreboard(false);") + end +end +AddEvent("OnKeyRelease", OnKeyRelease) + +function UpdateScoreboardData() + CallRemoteEvent("UpdateScoreboardData") +end + +function OnGetScoreboardData(servername, count, maxplayers, players) + --print(servername, count, maxplayers) + + ExecuteWebJS(Gui_main, "SetServerName('"..servername.."')") + ExecuteWebJS(Gui_main, "SetPlayerCount("..count..", "..maxplayers..")") + ExecuteWebJS(Gui_main, "RemovePlayers()") + --print("OnGetScoreboardData "..#players) + for k, v in ipairs(players) do + ExecuteWebJS(Gui_main, "AddPlayer("..v[4].." , '"..v[1].."', '"..v[2].."', '"..v[3].."')") + end +end +AddRemoteEvent("OnGetScoreboardData", OnGetScoreboardData) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/scoreboard/scoreboard_s.lua b/OKAYY Framework Basic/kuz_Essentials/scoreboard/scoreboard_s.lua new file mode 100644 index 0000000..d4894a4 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/scoreboard/scoreboard_s.lua @@ -0,0 +1,34 @@ +function UpdateScoreboardData(playerid) + local PlayerTable = { } + + local i = 1 + for _, v in ipairs(GetAllPlayers()) do + + local job = GetPlayerJob(v) + --local job = 'none' + + if job == nil then + job = "#" + end + + if IsValidPlayer(v) then + PlayerTable[i] = { + GetPlayerName(v), + job, + GetPlayerPing(v), + v + } + i = i + 1 + end + end + + CallRemoteEvent(playerid, "OnGetScoreboardData", "OKAYY FRAMEWORK (" .. math.floor(GetServerTickRate()) .."Hz)", GetPlayerCount(), GetMaxPlayers(), PlayerTable) +end +AddRemoteEvent("UpdateScoreboardData", UpdateScoreboardData) + + +function cmd_stoppack(player, package_) + + StopPackage(package_) +end +AddCommand("stoppack", cmd_stoppack) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/shops/client.lua b/OKAYY Framework Basic/kuz_Essentials/shops/client.lua new file mode 100644 index 0000000..0930685 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/shops/client.lua @@ -0,0 +1,77 @@ +local ui = 0 +local inside = false +local last_check = false +local refreshTimer = 0 + +local Shops = nil +local Selling = nil +local Buying = nil + +local currentType + +function OnPackageStart() + ui = CreateWebUI(0, 0, 0, 0, 5, 60) + LoadWebFile(ui, "http://asset/kuz_Essentials/shops/gui/shops.html") + SetWebAlignment(ui, 0.0, 0.0) + SetWebAnchors(ui, 0.0, 0.0, 1.0, 1.0) + SetWebVisibility(ui, WEB_HIDDEN) + + + Delay(10000, function () + refreshTimer = CreateTimer(CheckInShop, 500) + Shops = Shop.Shops + Selling = Shop.Selling + Buying = Shop.Buying + end) + +end +AddEvent("OnPackageStart", OnPackageStart) + + +function CheckInShop() + + + local x,y,z = GetPlayerLocation() + local got = false + + + local i = 1 + for _ in pairs(Shops) do + if GetDistance3D(x,y,z,Shops[i].x, Shops[i].y, Shops[i].z) <= 200 then + inside = true + got = true + + CallEvent("KNotify:SendPress", "Press [E] to open shop") + currentType = Shops[i].type + end + i = i + 1 + end + + + + if last_check and not inside then + CallEvent("KNotify:HidePress") + end + + if not got then + inside = false + end + + if not inside then + currentType = 0 + end + + last_check = inside +end + +local cooldown = false +function OnKeyPress(key) + if key == "E" and inside and currentType ~= 0 and not cooldown then + cooldown = true + CallRemoteEvent("Kuzkay:ShopOpenShopMenu", currentType) + Delay(500, function() + cooldown = false + end) + end +end +AddEvent("OnKeyPress", OnKeyPress) diff --git a/OKAYY Framework Basic/kuz_Essentials/shops/config.lua b/OKAYY Framework Basic/kuz_Essentials/shops/config.lua new file mode 100644 index 0000000..56ffdbe --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/shops/config.lua @@ -0,0 +1,57 @@ +Shop = {} +Shop.Shops = {} +Shop.Selling = {} +Shop.Buying = {} + + +Shop.Shops = { + + {x=-169095,y=-39441,z=1149,h=57,npc_model=15,name="[Shop]",type="gas",robbery_id=1}, + {x=128736,y=77620,z=1576,h=88,npc_model=15,name="[Shop]",type="gas",robbery_id=2}, + {x=171062,y=203568,z=1413,h=162,npc_model=15,name="[Shop]",type="gas",robbery_id=3}, + {x=-15400,y=-2773,z=2065,h=90,npc_model=15,name="[Shop]",type="gas",robbery_id=4}, + {x=42678,y=137926,z=1581,h=33,npc_model=15,name="[Shop]",type="gas",robbery_id=5}, + {x=49288,y=133307,z=1578,h=-179,npc_model=7,name="[Bartender]",type="bar",robbery_id=6} + +} + + + +Shop.Selling["gas"] = { + + {item="bandage",label="Bandage",price=200}, + {item="repairkit",label="Repair kit",price=400}, + {item="firework",label="Firworks",price=100}, + {item="bigfirework",label="Fireworks Pack",price=550}, + {item="gas",label="Gasoline",price=110} + +} +Shop.Buying["gas"] = { + + +} + +Shop.Selling["bar"] = { + {item="beer",label="Beer",price=40}, + {item="tequilla",label="Tequilla",price=100}, + {item="vodka",label="Vodka",price=130} +} + +Shop.Buying["bar"] = { + +} + + +Shop.Selling["dealer"] = { + {item="cocaine",label="Cocaine",price=600}, + {item="weed",label="Weed",price=400}, + {item="ammo",label="Ammo box",price=500} +} +Shop.Buying["dealer"] = { + {item="coca",label="Coca leaf",price=12}, + {item="cocaine",label="Cocaine",price=235}, + {item="heroin",label="Heroin",price=310} +} + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/shops/server.lua b/OKAYY Framework Basic/kuz_Essentials/shops/server.lua new file mode 100644 index 0000000..f0c3877 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/shops/server.lua @@ -0,0 +1,168 @@ +local Shops = Shop.Shops +local Selling = Shop.Selling +local Buying = Shop.Buying + +function OnPackageStart() + + Delay(5000, function () + local i = 1 + for _ in pairs(Shops) do + Shops[i].npc = CreateNPC(Shops[i].x, Shops[i].y, Shops[i].z, Shops[i].h) + + SetNPCPropertyValue(Shops[i].npc, 'model', Shops[i].npc_model, true) + + SetNPCAnimation(Shops[i].npc, "CROSSARMS", true) + SetNPCHealth(Shops[i].npc, 999999999) + CreateText3D(Shops[i].name, 16, Shops[i].x, Shops[i].y, Shops[i].z + 130, 0,0,0) + i = i + 1 + end + end) + +end +AddEvent("OnPackageStart", OnPackageStart) + + + +function OpenShopMenu(player, shop_type) + local range = false + local hasType = false + local x,y,z = GetPlayerLocation(player) + for k,v in pairs(Shops) do + if v.type == shop_type then + hasType = true + if GetDistance3D(v.x, v.y, v.z, x, y, z) <= 500 then + range = true + end + end + end + if not range and hasType then + return + end + + CallRemoteEvent(player, "KUI:Create", "shop", "STORE") + + local i = 1 + for _ in pairs(Selling[shop_type]) do + + local buy = Selling[shop_type][i] + + local color = "lightgreen" + if GetPlayerMoney(player) < tonumber(buy.price) then + color = "red" + end + + + local item = {item=buy.item,shop_type=shop_type,type="buy"} + CallRemoteEvent(player, "KUI:AddOption", jsonencode(item), buy.label, '', "Purchase") + i = i + 1 + end + + + local i = 1 + for _ in pairs(Buying[shop_type]) do + + local sell = Buying[shop_type][i] + + local color = "gold" + + local item = {item=sell.item,shop_type=shop_type,type="sell"} + CallRemoteEvent(player, "KUI:AddOption", jsonencode(item), sell.label, '', "Sell") + i = i + 1 + end + + + CallRemoteEvent(player, 'KUI:Show', 'shop', true) + +end +AddRemoteEvent("Kuzkay:ShopOpenShopMenu", OpenShopMenu) +AddEvent("Kuzkay:ShopOpenShopMenu", OpenShopMenu) + +function OnShopOptionPress(player, params_) + local params = jsondecode(params_) + local item = params.item + local shop_type = params.shop_type + local type = params.type + + if type == "buy" then + PurchaseItem(player, item, shop_type) + else + SellItem(player, item, shop_type) + end + +end +AddRemoteEvent("KUI:OptionClick_shop", OnShopOptionPress) + +function PurchaseItem(player, item, shop_type) + amount = 1 + local i = 1 + for _ in pairs(Selling[shop_type]) do + local itemData = Selling[shop_type][i] + + local hasType = false + local verified = false + local x,y,z = GetPlayerLocation(player) + local k = 1 + for _ in pairs(Shops) do + if Shops[k].type == shop_type then + if GetDistance3D(x,y,z, Shops[k].x,Shops[k].y,Shops[k].z) <= 600 then + verified = true + end + hasType = true + end + k = k + 1 + end + if not hasType then + verified = true + end + + if itemData.item == item and amount >= 1 and verified then + if GetPlayerMoney(player) >= (tonumber(itemData.price) * amount) then + if AddPlayerItem(player, item, amount) then + RemovePlayerMoney(player, math.floor(itemData.price * amount)) + end + else + CallRemoteEvent(player, 'KNotify:Send', "You can't afford this", "#f00") + end + end + i = i + 1 + end +end +AddRemoteEvent("Kuzkay:ShopsBuy", PurchaseItem) + +function SellItem(player, item, shop_type) + amount = 1 + local i = 1 + for _ in pairs(Buying[shop_type]) do + local itemData = Buying[shop_type][i] + + if itemData.item == item and amount >= 1 then + if RemovePlayerItem(player, item, amount) then + AddPlayerMoney(player, math.floor(amount * tonumber(itemData.price))) + end + end + i = i + 1 + end +end +AddRemoteEvent("Kuzkay:ShopsSell", SellItem) + +AddEvent("Kuzkay:RobberyStarted", function(id) + local i = 1 + for _ in pairs(Shops) do + if Shops[i].robbery_id == id then + SetNPCAnimation(Shops[i].npc, "HANDSUP_KNEEL", true) + end + i = i + 1 + end +end) + +AddEvent("Kuzkay:RobberyEnded", function(id) + Delay(5000, function() + local i = 1 + for _ in pairs(Shops) do + if Shops[i].robbery_id == id then + SetNPCAnimation(Shops[i].npc, "CROSSARMS", true) + end + i = i + 1 + end + end) +end) \ No newline at end of file diff --git a/OKAYY Framework Basic/kuz_Essentials/sounds/click.wav b/OKAYY Framework Basic/kuz_Essentials/sounds/click.wav new file mode 100644 index 0000000..8046128 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/sounds/click.wav differ diff --git a/OKAYY Framework Basic/kuz_Essentials/sounds/drop.wav b/OKAYY Framework Basic/kuz_Essentials/sounds/drop.wav new file mode 100644 index 0000000..9ad44fb Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/sounds/drop.wav differ diff --git a/OKAYY Framework Basic/kuz_Essentials/speedo/client.lua b/OKAYY Framework Basic/kuz_Essentials/speedo/client.lua new file mode 100644 index 0000000..fd05239 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/speedo/client.lua @@ -0,0 +1,49 @@ +local speed_timer = 0 + + +local vehicle = nil + + +function OnPackageStart() + Delay(1000, function() + speed_timer = CreateTimer(GetSpeedData, 150) + end) + +end +AddEvent("OnPackageStart", OnPackageStart) + + +function GetSpeedData() + if vehicle ~= 0 and vehicle ~= nil and vehicle ~= '0' then + local speed = math.floor(GetVehicleForwardSpeed(vehicle)) + local rpm = math.floor(GetVehicleEngineRPM(vehicle)) + ExecuteWebJS(Gui_main, "SetVehicleSpeed('".. speed .."','".. rpm .."')") + end + +end + + +function OnGetVehicle(_vehicle) + vehicle = _vehicle + if vehicle ~= 0 then + ExecuteWebJS(Gui_main, "ToggleSpeedo(true);") + else + ExecuteWebJS(Gui_main, "ToggleSpeedo(false);") + end + +end +AddRemoteEvent("Kuzkay:ReturnVehicle", OnGetVehicle) + +function EnableSpeedStep(key) + if key == "W" and IsPlayerInVehicle() then + speedStep = true + end +end +AddEvent('OnKeyPress', EnableSpeedStep) +function DisableSpeedStep(key) + if key == "W" and IsPlayerInVehicle() then + speedStep = false + end +end +AddEvent('OnKeyRelease', DisableSpeedStep) + diff --git a/OKAYY Framework Basic/kuz_Essentials/speedo/server.lua b/OKAYY Framework Basic/kuz_Essentials/speedo/server.lua new file mode 100644 index 0000000..795447a --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/speedo/server.lua @@ -0,0 +1,21 @@ +function GetVehicle(player) + local vehicle = GetPlayerVehicle(player) + CallRemoteEvent(player, "Kuzkay:ReturnVehicle", vehicle) +end +AddRemoteEvent("Kuzkay:GetVehicle", GetVehicle) + + + +function OnEnterVehicle(player, _vehicle, seat) + CallRemoteEvent(player, "Kuzkay:ReturnVehicle", _vehicle) +end +AddEvent("OnPlayerEnterVehicle", OnEnterVehicle) + +function OnLeaveVehicle(player, _vehicle, seat) + CallRemoteEvent(player, "Kuzkay:ReturnVehicle", 0) +end +AddEvent("OnPlayerLeaveVehicle", OnLeaveVehicle) + + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/trunks.lua b/OKAYY Framework Basic/kuz_Essentials/trunks.lua new file mode 100644 index 0000000..be3b917 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/trunks.lua @@ -0,0 +1,32 @@ +Config.VehicleSlots = { + [1] = 14, + [2] = 14, + [3] = 14, + [4] = 17, + [5] = 12, + [6] = 3, + [7] = 32, + [8] = 15, + [9] = 21, + [10] = 6, + [11] = 7, + [12] = 9, + [13] = 17, + [14] = 17, + [15] = 17, + [16] = 17, + [17] = 66, + [18] = 66, + [19] = 14, + [20] = 6, + [21] = 12, + [22] = 42, + [23] = 42, + [24] = 30, + [25] = 7 + +} + + + + diff --git a/OKAYY Framework Basic/kuz_Essentials/utils/Bebas.ttf b/OKAYY Framework Basic/kuz_Essentials/utils/Bebas.ttf new file mode 100644 index 0000000..76e22b8 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/utils/Bebas.ttf differ diff --git a/OKAYY Framework Basic/kuz_Essentials/utils/Yanone.ttf b/OKAYY Framework Basic/kuz_Essentials/utils/Yanone.ttf new file mode 100644 index 0000000..612c4e4 Binary files /dev/null and b/OKAYY Framework Basic/kuz_Essentials/utils/Yanone.ttf differ diff --git a/OKAYY Framework Basic/kuz_Essentials/utils/jquery-ui.js b/OKAYY Framework Basic/kuz_Essentials/utils/jquery-ui.js new file mode 100644 index 0000000..0213552 --- /dev/null +++ b/OKAYY Framework Basic/kuz_Essentials/utils/jquery-ui.js @@ -0,0 +1,18706 @@ +/*! jQuery UI - v1.12.1 - 2016-09-14 +* http://jqueryui.com +* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +(function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define([ "jquery" ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}(function( $ ) { + +$.ui = $.ui || {}; + +var version = $.ui.version = "1.12.1"; + + +/*! + * jQuery UI Widget 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Widget +//>>group: Core +//>>description: Provides a factory for creating stateful widgets with a common API. +//>>docs: http://api.jqueryui.com/jQuery.widget/ +//>>demos: http://jqueryui.com/widget/ + + + +var widgetUuid = 0; +var widgetSlice = Array.prototype.slice; + +$.cleanData = ( function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { + try { + + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } + + // Http://bugs.jquery.com/ticket/8235 + } catch ( e ) {} + } + orig( elems ); + }; +} )( $.cleanData ); + +$.widget = function( name, base, prototype ) { + var existingConstructor, constructor, basePrototype; + + // ProxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + var proxiedPrototype = {}; + + var namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; + var fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + if ( $.isArray( prototype ) ) { + prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); + } + + // Create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + + // Allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + + // Allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + // Extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + + // Copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + + // Track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + } ); + + basePrototype = new base(); + + // We need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( !$.isFunction( value ) ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = ( function() { + function _super() { + return base.prototype[ prop ].apply( this, arguments ); + } + + function _superApply( args ) { + return base.prototype[ prop ].apply( this, args ); + } + + return function() { + var __super = this._super; + var __superApply = this._superApply; + var returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + } )(); + } ); + constructor.prototype = $.widget.extend( basePrototype, { + + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + } ); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // Redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, + child._proto ); + } ); + + // Remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); + + return constructor; +}; + +$.widget.extend = function( target ) { + var input = widgetSlice.call( arguments, 1 ); + var inputIndex = 0; + var inputLength = input.length; + var key; + var value; + + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string"; + var args = widgetSlice.call( arguments, 1 ); + var returnValue = this; + + if ( isMethodCall ) { + + // If this is an empty collection, we need to have the instance method + // return undefined instead of the jQuery instance + if ( !this.length && options === "instance" ) { + returnValue = undefined; + } else { + this.each( function() { + var methodValue; + var instance = $.data( this, fullName ); + + if ( options === "instance" ) { + returnValue = instance; + return false; + } + + if ( !instance ) { + return $.error( "cannot call methods on " + name + + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + + if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + + " widget instance" ); + } + + methodValue = instance[ options ].apply( instance, args ); + + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + } ); + } + } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat( args ) ); + } + + this.each( function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + $.data( this, fullName, new object( options, this ) ); + } + } ); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
", + + options: { + classes: {}, + disabled: false, + + // Callbacks + create: null + }, + + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = widgetUuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + this.classesElementLookup = {}; + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + } ); + this.document = $( element.style ? + + // Element within the document + element.ownerDocument : + + // Element is window or document + element.document || element ); + this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); + } + + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this._create(); + + if ( this.options.disabled ) { + this._setOptionDisabled( this.options.disabled ); + } + + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + + _getCreateOptions: function() { + return {}; + }, + + _getCreateEventData: $.noop, + + _create: $.noop, + + _init: $.noop, + + destroy: function() { + var that = this; + + this._destroy(); + $.each( this.classesElementLookup, function( key, value ) { + that._removeClass( value, key ); + } ); + + // We can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .off( this.eventNamespace ) + .removeData( this.widgetFullName ); + this.widget() + .off( this.eventNamespace ) + .removeAttr( "aria-disabled" ); + + // Clean up events and states + this.bindings.off( this.eventNamespace ); + }, + + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + var parts; + var curOption; + var i; + + if ( arguments.length === 0 ) { + + // Don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + + // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + + _setOption: function( key, value ) { + if ( key === "classes" ) { + this._setOptionClasses( value ); + } + + this.options[ key ] = value; + + if ( key === "disabled" ) { + this._setOptionDisabled( value ); + } + + return this; + }, + + _setOptionClasses: function( value ) { + var classKey, elements, currentElements; + + for ( classKey in value ) { + currentElements = this.classesElementLookup[ classKey ]; + if ( value[ classKey ] === this.options.classes[ classKey ] || + !currentElements || + !currentElements.length ) { + continue; + } + + // We are doing this to create a new jQuery object because the _removeClass() call + // on the next line is going to destroy the reference to the current elements being + // tracked. We need to save a copy of this collection so that we can add the new classes + // below. + elements = $( currentElements.get() ); + this._removeClass( currentElements, classKey ); + + // We don't use _addClass() here, because that uses this.options.classes + // for generating the string of classes. We want to use the value passed in from + // _setOption(), this is the new value of the classes option which was passed to + // _setOption(). We pass this value directly to _classes(). + elements.addClass( this._classes( { + element: elements, + keys: classKey, + classes: value, + add: true + } ) ); + } + }, + + _setOptionDisabled: function( value ) { + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this._removeClass( this.hoverable, null, "ui-state-hover" ); + this._removeClass( this.focusable, null, "ui-state-focus" ); + } + }, + + enable: function() { + return this._setOptions( { disabled: false } ); + }, + + disable: function() { + return this._setOptions( { disabled: true } ); + }, + + _classes: function( options ) { + var full = []; + var that = this; + + options = $.extend( { + element: this.element, + classes: this.options.classes || {} + }, options ); + + function processClassString( classes, checkOption ) { + var current, i; + for ( i = 0; i < classes.length; i++ ) { + current = that.classesElementLookup[ classes[ i ] ] || $(); + if ( options.add ) { + current = $( $.unique( current.get().concat( options.element.get() ) ) ); + } else { + current = $( current.not( options.element ).get() ); + } + that.classesElementLookup[ classes[ i ] ] = current; + full.push( classes[ i ] ); + if ( checkOption && options.classes[ classes[ i ] ] ) { + full.push( options.classes[ classes[ i ] ] ); + } + } + } + + this._on( options.element, { + "remove": "_untrackClassesElement" + } ); + + if ( options.keys ) { + processClassString( options.keys.match( /\S+/g ) || [], true ); + } + if ( options.extra ) { + processClassString( options.extra.match( /\S+/g ) || [] ); + } + + return full.join( " " ); + }, + + _untrackClassesElement: function( event ) { + var that = this; + $.each( that.classesElementLookup, function( key, value ) { + if ( $.inArray( event.target, value ) !== -1 ) { + that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); + } + } ); + }, + + _removeClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, false ); + }, + + _addClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, true ); + }, + + _toggleClass: function( element, keys, extra, add ) { + add = ( typeof add === "boolean" ) ? add : extra; + var shift = ( typeof element === "string" || element === null ), + options = { + extra: shift ? keys : extra, + keys: shift ? element : keys, + element: shift ? this.element : element, + add: add + }; + options.element.toggleClass( this._classes( options ), add ); + return this; + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement; + var instance = this; + + // No suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // No element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + + // Allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // Copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^([\w:-]*)\s*(.*)$/ ); + var eventName = match[ 1 ] + instance.eventNamespace; + var selector = match[ 2 ]; + + if ( selector ) { + delegateElement.on( eventName, selector, handlerProxy ); + } else { + element.on( eventName, handlerProxy ); + } + } ); + }, + + _off: function( element, eventName ) { + eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; + element.off( eventName ).off( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); + }, + mouseleave: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); + } + } ); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); + }, + focusout: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); + } + } ); + }, + + _trigger: function( type, event, data ) { + var prop, orig; + var callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + + // The original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // Copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + + var hasOptions; + var effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + + if ( options.delay ) { + element.delay( options.delay ); + } + + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue( function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + } ); + } + }; +} ); + +var widget = $.widget; + + +/*! + * jQuery UI Position 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/position/ + */ + +//>>label: Position +//>>group: Core +//>>description: Positions elements relative to other elements. +//>>docs: http://api.jqueryui.com/position/ +//>>demos: http://jqueryui.com/position/ + + +( function() { +var cachedScrollbarWidth, + max = Math.max, + abs = Math.abs, + rhorizontal = /left|center|right/, + rvertical = /top|center|bottom/, + roffset = /[\+\-]\d+(\.[\d]+)?%?/, + rposition = /^\w+/, + rpercent = /%$/, + _position = $.fn.position; + +function getOffsets( offsets, width, height ) { + return [ + parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), + parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) + ]; +} + +function parseCss( element, property ) { + return parseInt( $.css( element, property ), 10 ) || 0; +} + +function getDimensions( elem ) { + var raw = elem[ 0 ]; + if ( raw.nodeType === 9 ) { + return { + width: elem.width(), + height: elem.height(), + offset: { top: 0, left: 0 } + }; + } + if ( $.isWindow( raw ) ) { + return { + width: elem.width(), + height: elem.height(), + offset: { top: elem.scrollTop(), left: elem.scrollLeft() } + }; + } + if ( raw.preventDefault ) { + return { + width: 0, + height: 0, + offset: { top: raw.pageY, left: raw.pageX } + }; + } + return { + width: elem.outerWidth(), + height: elem.outerHeight(), + offset: elem.offset() + }; +} + +$.position = { + scrollbarWidth: function() { + if ( cachedScrollbarWidth !== undefined ) { + return cachedScrollbarWidth; + } + var w1, w2, + div = $( "
" + + "
" ), + innerDiv = div.children()[ 0 ]; + + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[ 0 ].clientWidth; + } + + div.remove(); + + return ( cachedScrollbarWidth = w1 - w2 ); + }, + getScrollInfo: function( within ) { + var overflowX = within.isWindow || within.isDocument ? "" : + within.element.css( "overflow-x" ), + overflowY = within.isWindow || within.isDocument ? "" : + within.element.css( "overflow-y" ), + hasOverflowX = overflowX === "scroll" || + ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), + hasOverflowY = overflowY === "scroll" || + ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); + return { + width: hasOverflowY ? $.position.scrollbarWidth() : 0, + height: hasOverflowX ? $.position.scrollbarWidth() : 0 + }; + }, + getWithinInfo: function( element ) { + var withinElement = $( element || window ), + isWindow = $.isWindow( withinElement[ 0 ] ), + isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, + hasOffset = !isWindow && !isDocument; + return { + element: withinElement, + isWindow: isWindow, + isDocument: isDocument, + offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, + scrollLeft: withinElement.scrollLeft(), + scrollTop: withinElement.scrollTop(), + width: withinElement.outerWidth(), + height: withinElement.outerHeight() + }; + } +}; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // Make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, + target = $( options.of ), + within = $.position.getWithinInfo( options.within ), + scrollInfo = $.position.getScrollInfo( within ), + collision = ( options.collision || "flip" ).split( " " ), + offsets = {}; + + dimensions = getDimensions( target ); + if ( target[ 0 ].preventDefault ) { + + // Force left top to allow flipping + options.at = "left top"; + } + targetWidth = dimensions.width; + targetHeight = dimensions.height; + targetOffset = dimensions.offset; + + // Clone to reuse original targetOffset later + basePosition = $.extend( {}, targetOffset ); + + // Force my and at to have valid horizontal and vertical positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[ this ] || "" ).split( " " ), + horizontalOffset, + verticalOffset; + + if ( pos.length === 1 ) { + pos = rhorizontal.test( pos[ 0 ] ) ? + pos.concat( [ "center" ] ) : + rvertical.test( pos[ 0 ] ) ? + [ "center" ].concat( pos ) : + [ "center", "center" ]; + } + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; + + // Calculate offsets + horizontalOffset = roffset.exec( pos[ 0 ] ); + verticalOffset = roffset.exec( pos[ 1 ] ); + offsets[ this ] = [ + horizontalOffset ? horizontalOffset[ 0 ] : 0, + verticalOffset ? verticalOffset[ 0 ] : 0 + ]; + + // Reduce to just the positions without the offsets + options[ this ] = [ + rposition.exec( pos[ 0 ] )[ 0 ], + rposition.exec( pos[ 1 ] )[ 0 ] + ]; + } ); + + // Normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + if ( options.at[ 0 ] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[ 0 ] === "center" ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[ 1 ] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[ 1 ] === "center" ) { + basePosition.top += targetHeight / 2; + } + + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); + basePosition.left += atOffset[ 0 ]; + basePosition.top += atOffset[ 1 ]; + + return this.each( function() { + var collisionPosition, using, + elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseCss( this, "marginLeft" ), + marginTop = parseCss( this, "marginTop" ), + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + + scrollInfo.width, + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + + scrollInfo.height, + position = $.extend( {}, basePosition ), + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); + + if ( options.my[ 0 ] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[ 0 ] === "center" ) { + position.left -= elemWidth / 2; + } + + if ( options.my[ 1 ] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[ 1 ] === "center" ) { + position.top -= elemHeight / 2; + } + + position.left += myOffset[ 0 ]; + position.top += myOffset[ 1 ]; + + collisionPosition = { + marginLeft: marginLeft, + marginTop: marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[ i ] ] ) { + $.ui.position[ collision[ i ] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], + my: options.my, + at: options.at, + within: within, + elem: elem + } ); + } + } ); + + if ( options.using ) { + + // Adds feedback as second argument to using callback, if present + using = function( props ) { + var left = targetOffset.left - position.left, + right = left + targetWidth - elemWidth, + top = targetOffset.top - position.top, + bottom = top + targetHeight - elemHeight, + feedback = { + target: { + element: target, + left: targetOffset.left, + top: targetOffset.top, + width: targetWidth, + height: targetHeight + }, + element: { + element: elem, + left: position.left, + top: position.top, + width: elemWidth, + height: elemHeight + }, + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" + }; + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { + feedback.horizontal = "center"; + } + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { + feedback.vertical = "middle"; + } + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { + feedback.important = "horizontal"; + } else { + feedback.important = "vertical"; + } + options.using.call( this, props, feedback ); + }; + } + + elem.offset( $.extend( position, { using: using } ) ); + } ); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, + outerWidth = within.width, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = withinOffset - collisionPosLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, + newOverRight; + + // Element is wider than within + if ( data.collisionWidth > outerWidth ) { + + // Element is initially over the left side of within + if ( overLeft > 0 && overRight <= 0 ) { + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - + withinOffset; + position.left += overLeft - newOverRight; + + // Element is initially over right side of within + } else if ( overRight > 0 && overLeft <= 0 ) { + position.left = withinOffset; + + // Element is initially over both left and right sides of within + } else { + if ( overLeft > overRight ) { + position.left = withinOffset + outerWidth - data.collisionWidth; + } else { + position.left = withinOffset; + } + } + + // Too far left -> align with left edge + } else if ( overLeft > 0 ) { + position.left += overLeft; + + // Too far right -> align with right edge + } else if ( overRight > 0 ) { + position.left -= overRight; + + // Adjust based on position and margin + } else { + position.left = max( position.left - collisionPosLeft, position.left ); + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, + outerHeight = data.within.height, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = withinOffset - collisionPosTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, + newOverBottom; + + // Element is taller than within + if ( data.collisionHeight > outerHeight ) { + + // Element is initially over the top of within + if ( overTop > 0 && overBottom <= 0 ) { + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - + withinOffset; + position.top += overTop - newOverBottom; + + // Element is initially over bottom of within + } else if ( overBottom > 0 && overTop <= 0 ) { + position.top = withinOffset; + + // Element is initially over both top and bottom of within + } else { + if ( overTop > overBottom ) { + position.top = withinOffset + outerHeight - data.collisionHeight; + } else { + position.top = withinOffset; + } + } + + // Too far up -> align with top + } else if ( overTop > 0 ) { + position.top += overTop; + + // Too far down -> align with bottom edge + } else if ( overBottom > 0 ) { + position.top -= overBottom; + + // Adjust based on position and margin + } else { + position.top = max( position.top - collisionPosTop, position.top ); + } + } + }, + flip: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.offset.left + within.scrollLeft, + outerWidth = within.width, + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = collisionPosLeft - offsetLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + data.at[ 0 ] === "right" ? + -data.targetWidth : + 0, + offset = -2 * data.offset[ 0 ], + newOverRight, + newOverLeft; + + if ( overLeft < 0 ) { + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - + outerWidth - withinOffset; + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { + position.left += myOffset + atOffset + offset; + } + } else if ( overRight > 0 ) { + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + + atOffset + offset - offsetLeft; + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { + position.left += myOffset + atOffset + offset; + } + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.offset.top + within.scrollTop, + outerHeight = within.height, + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = collisionPosTop - offsetTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, + top = data.my[ 1 ] === "top", + myOffset = top ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + data.at[ 1 ] === "bottom" ? + -data.targetHeight : + 0, + offset = -2 * data.offset[ 1 ], + newOverTop, + newOverBottom; + if ( overTop < 0 ) { + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - + outerHeight - withinOffset; + if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { + position.top += myOffset + atOffset + offset; + } + } else if ( overBottom > 0 ) { + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + + offset - offsetTop; + if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { + position.top += myOffset + atOffset + offset; + } + } + } + }, + flipfit: { + left: function() { + $.ui.position.flip.left.apply( this, arguments ); + $.ui.position.fit.left.apply( this, arguments ); + }, + top: function() { + $.ui.position.flip.top.apply( this, arguments ); + $.ui.position.fit.top.apply( this, arguments ); + } + } +}; + +} )(); + +var position = $.ui.position; + + +/*! + * jQuery UI :data 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :data Selector +//>>group: Core +//>>description: Selects elements which have data stored under the specified key. +//>>docs: http://api.jqueryui.com/data-selector/ + + +var data = $.extend( $.expr[ ":" ], { + data: $.expr.createPseudo ? + $.expr.createPseudo( function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + } ) : + + // Support: jQuery <1.8 + function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + } +} ); + +/*! + * jQuery UI Disable Selection 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: disableSelection +//>>group: Core +//>>description: Disable selection of text content within the set of matched elements. +//>>docs: http://api.jqueryui.com/disableSelection/ + +// This file is deprecated + + +var disableSelection = $.fn.extend( { + disableSelection: ( function() { + var eventType = "onselectstart" in document.createElement( "div" ) ? + "selectstart" : + "mousedown"; + + return function() { + return this.on( eventType + ".ui-disableSelection", function( event ) { + event.preventDefault(); + } ); + }; + } )(), + + enableSelection: function() { + return this.off( ".ui-disableSelection" ); + } +} ); + + +/*! + * jQuery UI Effects 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Effects Core +//>>group: Effects +// jscs:disable maximumLineLength +//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. +// jscs:enable maximumLineLength +//>>docs: http://api.jqueryui.com/category/effects-core/ +//>>demos: http://jqueryui.com/effect/ + + + +var dataSpace = "ui-effects-", + dataSpaceStyle = "ui-effects-style", + dataSpaceAnimated = "ui-effects-animated", + + // Create a local jQuery because jQuery Color relies on it and the + // global may not exist with AMD and a custom build (#10199) + jQuery = $; + +$.effects = { + effect: {} +}; + +/*! + * jQuery Color Animations v2.1.2 + * https://github.com/jquery/jquery-color + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * Date: Wed Jan 16 08:47:09 2013 -0600 + */ +( function( jQuery, undefined ) { + + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + + "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", + + // Plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + + // A set of RE's that can match strings and generate color tuples. + stringParsers = [ { + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ] * 2.55, + execResult[ 2 ] * 2.55, + execResult[ 3 ] * 2.55, + execResult[ 4 ] + ]; + } + }, { + + // This regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ) + ]; + } + }, { + + // This regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ] / 100, + execResult[ 3 ] / 100, + execResult[ 4 ] + ]; + } + } ], + + // JQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + props: { + red: { + idx: 0, + type: "byte" + }, + green: { + idx: 1, + type: "byte" + }, + blue: { + idx: 2, + type: "byte" + } + } + }, + + hsla: { + props: { + hue: { + idx: 0, + type: "degrees" + }, + saturation: { + idx: 1, + type: "percent" + }, + lightness: { + idx: 2, + type: "percent" + } + } + } + }, + propTypes = { + "byte": { + floor: true, + max: 255 + }, + "percent": { + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + support = color.support = {}, + + // Element for support tests + supportElem = jQuery( "

" )[ 0 ], + + // Colors = jQuery.Color.names + colors, + + // Local aliases of functions called often + each = jQuery.each; + +// Determine rgba support immediately +supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; +support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; + +// Define cache name and alpha properties +// for rgba and hsla spaces +each( spaces, function( spaceName, space ) { + space.cache = "_" + spaceName; + space.props.alpha = { + idx: 3, + type: "percent", + def: 1 + }; +} ); + +function clamp( value, prop, allowEmpty ) { + var type = propTypes[ prop.type ] || {}; + + if ( value == null ) { + return ( allowEmpty || !prop.def ) ? null : prop.def; + } + + // ~~ is an short way of doing floor for positive numbers + value = type.floor ? ~~value : parseFloat( value ); + + // IE will pass in empty strings as value for alpha, + // which will hit this case + if ( isNaN( value ) ) { + return prop.def; + } + + if ( type.mod ) { + + // We add mod before modding to make sure that negatives values + // get converted properly: -10 -> 350 + return ( value + type.mod ) % type.mod; + } + + // For now all property types without mod have min and max + return 0 > value ? 0 : type.max < value ? type.max : value; +} + +function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; + + string = string.toLowerCase(); + + each( stringParsers, function( i, parser ) { + var parsed, + match = parser.re.exec( string ), + values = match && parser.parse( match ), + spaceName = parser.space || "rgba"; + + if ( values ) { + parsed = inst[ spaceName ]( values ); + + // If this was an rgba parse the assignment might happen twice + // oh well.... + inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; + rgba = inst._rgba = parsed._rgba; + + // Exit each( stringParsers ) here because we matched + return false; + } + } ); + + // Found a stringParser that handled it + if ( rgba.length ) { + + // If this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( rgba.join() === "0,0,0,0" ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } + + // Named colors + return colors[ string ]; +} + +color.fn = jQuery.extend( color.prototype, { + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red.jquery || red.nodeType ) { + red = jQuery( red ).css( green ); + green = undefined; + } + + var inst = this, + type = jQuery.type( red ), + rgba = this._rgba = []; + + // More than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; + } + + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } + + if ( type === "array" ) { + each( spaces.rgba.props, function( key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + } ); + return this; + } + + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + } ); + } else { + each( spaces, function( spaceName, space ) { + var cache = space.cache; + each( space.props, function( key, prop ) { + + // If the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // If the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( key === "alpha" || red[ key ] == null ) { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // This is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + } ); + + // Everything defined but alpha? + if ( inst[ cache ] && + jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + + // Use the default of 1 + inst[ cache ][ 3 ] = 1; + if ( space.from ) { + inst._rgba = space.from( inst[ cache ] ); + } + } + } ); + } + return this; + } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + inst = this; + + each( spaces, function( _, space ) { + var localCache, + isCache = is[ space.cache ]; + if ( isCache ) { + localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + } ); + } + return same; + } ); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + } ); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + startColor = this.alpha() === 0 ? color( "transparent" ) : this, + start = startColor[ space.cache ] || space.to( startColor._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // If null, don't override start value + if ( endValue === null ) { + return; + } + + // If null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + } ); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + + // If we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } + + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; + + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + } ) ); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + return v == null ? ( i > 2 ? 1 : 0 ) : v; + } ); + + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; + } + + return prefix + rgba.join() + ")"; + }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } + + // Catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + } ); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; + } + return prefix + hsla.join() + ")"; + }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); + + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } + + return "#" + jQuery.map( rgba, function( v ) { + + // Default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + } ).join( "" ); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } +} ); +color.fn.parse.prototype = color.fn; + +// Hsla conversions adapted from: +// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 + +function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + ( q - p ) * h * 6; + } + if ( h * 2 < 1 ) { + return q; + } + if ( h * 3 < 2 ) { + return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; + } + return p; +} + +spaces.hsla.to = function( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } + + // Chroma (diff) == 0 means greyscale which, by definition, saturation = 0% + // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) + if ( diff === 0 ) { + s = 0; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; +}; + +spaces.hsla.from = function( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; +}; + +each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; + + // Makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { + + // Generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } + + var ret, + type = jQuery.type( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(); + + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + } ); + + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; + + // Makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + + // Alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var vtype = jQuery.type( value ), + fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), + local = this[ fn ](), + cur = local[ prop.idx ], + match; + + if ( vtype === "undefined" ) { + return cur; + } + + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = jQuery.type( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + } ); +} ); + +// Add cssHook and .fx.step function for each named hook. +// accept a space separated string of properties +color.hook = function( hook ) { + var hooks = hook.split( " " ); + each( hooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || + ( parsed = stringParse( value ) ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + ( backgroundColor === "" || backgroundColor === "transparent" ) && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } + } + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } + + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch ( e ) { + + // Wrapped to prevent IE from throwing errors on "invalid" values like + // 'auto' or 'inherit' + } + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; + } ); + +}; + +color.hook( stepHooks ); + +jQuery.cssHooks.borderColor = { + expand: function( value ) { + var expanded = {}; + + each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { + expanded[ "border" + part + "Color" ] = value; + } ); + return expanded; + } +}; + +// Basic color names only. +// Usage of any of the other color names requires adding yourself or including +// jquery.color.svg-names.js. +colors = jQuery.Color.names = { + + // 4.1. Basic color keywords + aqua: "#00ffff", + black: "#000000", + blue: "#0000ff", + fuchsia: "#ff00ff", + gray: "#808080", + green: "#008000", + lime: "#00ff00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + purple: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + teal: "#008080", + white: "#ffffff", + yellow: "#ffff00", + + // 4.2.3. "transparent" color keyword + transparent: [ null, null, null, 0 ], + + _default: "#ffffff" +}; + +} )( jQuery ); + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ +( function() { + +var classAnimationActions = [ "add", "remove", "toggle" ], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +$.each( + [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], + function( _, prop ) { + $.fx.step[ prop ] = function( fx ) { + if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { + jQuery.style( fx.elem, prop, fx.end ); + fx.setAttr = true; + } + }; + } +); + +function getElementStyles( elem ) { + var key, len, + style = elem.ownerDocument.defaultView ? + elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : + elem.currentStyle, + styles = {}; + + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + styles[ $.camelCase( key ) ] = style[ key ]; + } + } + + // Support: Opera, IE <9 + } else { + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + styles[ key ] = style[ key ]; + } + } + } + + return styles; +} + +function styleDifference( oldStyle, newStyle ) { + var diff = {}, + name, value; + + for ( name in newStyle ) { + value = newStyle[ name ]; + if ( oldStyle[ name ] !== value ) { + if ( !shorthandStyles[ name ] ) { + if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { + diff[ name ] = value; + } + } + } + } + + return diff; +} + +// Support: jQuery <1.8 +if ( !$.fn.addBack ) { + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +$.effects.animateClass = function( value, duration, easing, callback ) { + var o = $.speed( duration, easing, callback ); + + return this.queue( function() { + var animated = $( this ), + baseClass = animated.attr( "class" ) || "", + applyClassChange, + allAnimations = o.children ? animated.find( "*" ).addBack() : animated; + + // Map the animated objects to store the original styles. + allAnimations = allAnimations.map( function() { + var el = $( this ); + return { + el: el, + start: getElementStyles( this ) + }; + } ); + + // Apply class change + applyClassChange = function() { + $.each( classAnimationActions, function( i, action ) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); + } + } ); + }; + applyClassChange(); + + // Map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map( function() { + this.end = getElementStyles( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + } ); + + // Apply original class + animated.attr( "class", baseClass ); + + // Map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map( function() { + var styleInfo = this, + dfd = $.Deferred(), + opts = $.extend( {}, o, { + queue: false, + complete: function() { + dfd.resolve( styleInfo ); + } + } ); + + this.el.animate( this.diff, opts ); + return dfd.promise(); + } ); + + // Once all animations have completed: + $.when.apply( $, allAnimations.get() ).done( function() { + + // Set the final class + applyClassChange(); + + // For each animated element, + // clear all css properties that were animated + $.each( arguments, function() { + var el = this.el; + $.each( this.diff, function( key ) { + el.css( key, "" ); + } ); + } ); + + // This is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); + } ); + } ); +}; + +$.fn.extend( { + addClass: ( function( orig ) { + return function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { add: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + } )( $.fn.addClass ), + + removeClass: ( function( orig ) { + return function( classNames, speed, easing, callback ) { + return arguments.length > 1 ? + $.effects.animateClass.call( this, + { remove: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + } )( $.fn.removeClass ), + + toggleClass: ( function( orig ) { + return function( classNames, force, speed, easing, callback ) { + if ( typeof force === "boolean" || force === undefined ) { + if ( !speed ) { + + // Without speed parameter + return orig.apply( this, arguments ); + } else { + return $.effects.animateClass.call( this, + ( force ? { add: classNames } : { remove: classNames } ), + speed, easing, callback ); + } + } else { + + // Without force parameter + return $.effects.animateClass.call( this, + { toggle: classNames }, force, speed, easing ); + } + }; + } )( $.fn.toggleClass ), + + switchClass: function( remove, add, speed, easing, callback ) { + return $.effects.animateClass.call( this, { + add: add, + remove: remove + }, speed, easing, callback ); + } +} ); + +} )(); + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +( function() { + +if ( $.expr && $.expr.filters && $.expr.filters.animated ) { + $.expr.filters.animated = ( function( orig ) { + return function( elem ) { + return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); + }; + } )( $.expr.filters.animated ); +} + +if ( $.uiBackCompat !== false ) { + $.extend( $.effects, { + + // Saves a set of properties in a data storage + save: function( element, set ) { + var i = 0, length = set.length; + for ( ; i < length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function( element, set ) { + var val, i = 0, length = set.length; + for ( ; i < length; i++ ) { + if ( set[ i ] !== null ) { + val = element.data( dataSpace + set[ i ] ); + element.css( set[ i ], val ); + } + } + }, + + setMode: function( el, mode ) { + if ( mode === "toggle" ) { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } + return mode; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function( element ) { + + // If the element is already wrapped, return it + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + return element.parent(); + } + + // Wrap the element + var props = { + width: element.outerWidth( true ), + height: element.outerHeight( true ), + "float": element.css( "float" ) + }, + wrapper = $( "

" ) + .addClass( "ui-effects-wrapper" ) + .css( { + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0 + } ), + + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, + active = document.activeElement; + + // Support: Firefox + // Firefox incorrectly exposes anonymous content + // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 + try { + active.id; + } catch ( e ) { + active = document.body; + } + + element.wrap( wrapper ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).trigger( "focus" ); + } + + // Hotfix for jQuery 1.4 since some change in wrap() seems to actually + // lose the reference to the wrapped element + wrapper = element.parent(); + + // Transfer positioning properties to the wrapper + if ( element.css( "position" ) === "static" ) { + wrapper.css( { position: "relative" } ); + element.css( { position: "relative" } ); + } else { + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) + } ); + $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; + } + } ); + element.css( { + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + } ); + } + element.css( size ); + + return wrapper.css( props ).show(); + }, + + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).trigger( "focus" ); + } + } + + return element; + } + } ); +} + +$.extend( $.effects, { + version: "1.12.1", + + define: function( name, mode, effect ) { + if ( !effect ) { + effect = mode; + mode = "effect"; + } + + $.effects.effect[ name ] = effect; + $.effects.effect[ name ].mode = mode; + + return effect; + }, + + scaledDimensions: function( element, percent, direction ) { + if ( percent === 0 ) { + return { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + }; + } + + var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, + y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; + + return { + height: element.height() * y, + width: element.width() * x, + outerHeight: element.outerHeight() * y, + outerWidth: element.outerWidth() * x + }; + + }, + + clipToBox: function( animation ) { + return { + width: animation.clip.right - animation.clip.left, + height: animation.clip.bottom - animation.clip.top, + left: animation.clip.left, + top: animation.clip.top + }; + }, + + // Injects recently queued functions to be first in line (after "inprogress") + unshift: function( element, queueLength, count ) { + var queue = element.queue(); + + if ( queueLength > 1 ) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); + } + element.dequeue(); + }, + + saveStyle: function( element ) { + element.data( dataSpaceStyle, element[ 0 ].style.cssText ); + }, + + restoreStyle: function( element ) { + element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; + element.removeData( dataSpaceStyle ); + }, + + mode: function( element, mode ) { + var hidden = element.is( ":hidden" ); + + if ( mode === "toggle" ) { + mode = hidden ? "show" : "hide"; + } + if ( hidden ? mode === "hide" : mode === "show" ) { + mode = "none"; + } + return mode; + }, + + // Translates a [top,left] array into a baseline value + getBaseline: function( origin, original ) { + var y, x; + + switch ( origin[ 0 ] ) { + case "top": + y = 0; + break; + case "middle": + y = 0.5; + break; + case "bottom": + y = 1; + break; + default: + y = origin[ 0 ] / original.height; + } + + switch ( origin[ 1 ] ) { + case "left": + x = 0; + break; + case "center": + x = 0.5; + break; + case "right": + x = 1; + break; + default: + x = origin[ 1 ] / original.width; + } + + return { + x: x, + y: y + }; + }, + + // Creates a placeholder element so that the original element can be made absolute + createPlaceholder: function( element ) { + var placeholder, + cssPosition = element.css( "position" ), + position = element.position(); + + // Lock in margins first to account for form elements, which + // will change margin if you explicitly set height + // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 + // Support: Safari + element.css( { + marginTop: element.css( "marginTop" ), + marginBottom: element.css( "marginBottom" ), + marginLeft: element.css( "marginLeft" ), + marginRight: element.css( "marginRight" ) + } ) + .outerWidth( element.outerWidth() ) + .outerHeight( element.outerHeight() ); + + if ( /^(static|relative)/.test( cssPosition ) ) { + cssPosition = "absolute"; + + placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { + + // Convert inline to inline block to account for inline elements + // that turn to inline block based on content (like img) + display: /^(inline|ruby)/.test( element.css( "display" ) ) ? + "inline-block" : + "block", + visibility: "hidden", + + // Margins need to be set to account for margin collapse + marginTop: element.css( "marginTop" ), + marginBottom: element.css( "marginBottom" ), + marginLeft: element.css( "marginLeft" ), + marginRight: element.css( "marginRight" ), + "float": element.css( "float" ) + } ) + .outerWidth( element.outerWidth() ) + .outerHeight( element.outerHeight() ) + .addClass( "ui-effects-placeholder" ); + + element.data( dataSpace + "placeholder", placeholder ); + } + + element.css( { + position: cssPosition, + left: position.left, + top: position.top + } ); + + return placeholder; + }, + + removePlaceholder: function( element ) { + var dataKey = dataSpace + "placeholder", + placeholder = element.data( dataKey ); + + if ( placeholder ) { + placeholder.remove(); + element.removeData( dataKey ); + } + }, + + // Removes a placeholder if it exists and restores + // properties that were modified during placeholder creation + cleanUp: function( element ) { + $.effects.restoreStyle( element ); + $.effects.removePlaceholder( element ); + }, + + setTransition: function( element, list, factor, value ) { + value = value || {}; + $.each( list, function( i, x ) { + var unit = element.cssUnit( x ); + if ( unit[ 0 ] > 0 ) { + value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; + } + } ); + return value; + } +} ); + +// Return an effect options object for the given parameters: +function _normalizeArguments( effect, options, speed, callback ) { + + // Allow passing all options as the first parameter + if ( $.isPlainObject( effect ) ) { + options = effect; + effect = effect.effect; + } + + // Convert to an object + effect = { effect: effect }; + + // Catch (effect, null, ...) + if ( options == null ) { + options = {}; + } + + // Catch (effect, callback) + if ( $.isFunction( options ) ) { + callback = options; + speed = null; + options = {}; + } + + // Catch (effect, speed, ?) + if ( typeof options === "number" || $.fx.speeds[ options ] ) { + callback = speed; + speed = options; + options = {}; + } + + // Catch (effect, options, callback) + if ( $.isFunction( speed ) ) { + callback = speed; + speed = null; + } + + // Add options to effect + if ( options ) { + $.extend( effect, options ); + } + + speed = speed || options.duration; + effect.duration = $.fx.off ? 0 : + typeof speed === "number" ? speed : + speed in $.fx.speeds ? $.fx.speeds[ speed ] : + $.fx.speeds._default; + + effect.complete = callback || options.complete; + + return effect; +} + +function standardAnimationOption( option ) { + + // Valid standard speeds (nothing, number, named speed) + if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { + return true; + } + + // Invalid strings - treat as "normal" speed + if ( typeof option === "string" && !$.effects.effect[ option ] ) { + return true; + } + + // Complete callback + if ( $.isFunction( option ) ) { + return true; + } + + // Options hash (but not naming an effect) + if ( typeof option === "object" && !option.effect ) { + return true; + } + + // Didn't match any standard API + return false; +} + +$.fn.extend( { + effect: function( /* effect, options, speed, callback */ ) { + var args = _normalizeArguments.apply( this, arguments ), + effectMethod = $.effects.effect[ args.effect ], + defaultMode = effectMethod.mode, + queue = args.queue, + queueName = queue || "fx", + complete = args.complete, + mode = args.mode, + modes = [], + prefilter = function( next ) { + var el = $( this ), + normalizedMode = $.effects.mode( el, mode ) || defaultMode; + + // Sentinel for duck-punching the :animated psuedo-selector + el.data( dataSpaceAnimated, true ); + + // Save effect mode for later use, + // we can't just call $.effects.mode again later, + // as the .show() below destroys the initial state + modes.push( normalizedMode ); + + // See $.uiBackCompat inside of run() for removal of defaultMode in 1.13 + if ( defaultMode && ( normalizedMode === "show" || + ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { + el.show(); + } + + if ( !defaultMode || normalizedMode !== "none" ) { + $.effects.saveStyle( el ); + } + + if ( $.isFunction( next ) ) { + next(); + } + }; + + if ( $.fx.off || !effectMethod ) { + + // Delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args.duration, complete ); + } else { + return this.each( function() { + if ( complete ) { + complete.call( this ); + } + } ); + } + } + + function run( next ) { + var elem = $( this ); + + function cleanup() { + elem.removeData( dataSpaceAnimated ); + + $.effects.cleanUp( elem ); + + if ( args.mode === "hide" ) { + elem.hide(); + } + + done(); + } + + function done() { + if ( $.isFunction( complete ) ) { + complete.call( elem[ 0 ] ); + } + + if ( $.isFunction( next ) ) { + next(); + } + } + + // Override mode option on a per element basis, + // as toggle can be either show or hide depending on element state + args.mode = modes.shift(); + + if ( $.uiBackCompat !== false && !defaultMode ) { + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + + // Call the core method to track "olddisplay" properly + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[ 0 ], args, done ); + } + } else { + if ( args.mode === "none" ) { + + // Call the core method to track "olddisplay" properly + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[ 0 ], args, cleanup ); + } + } + } + + // Run prefilter on all elements first to ensure that + // any showing or hiding happens before placeholder creation, + // which ensures that any layout changes are correctly captured. + return queue === false ? + this.each( prefilter ).each( run ) : + this.queue( queueName, prefilter ).queue( queueName, run ); + }, + + show: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "show"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.show ), + + hide: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "hide"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.hide ), + + toggle: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) || typeof option === "boolean" ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "toggle"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.toggle ), + + cssUnit: function( key ) { + var style = this.css( key ), + val = []; + + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { + if ( style.indexOf( unit ) > 0 ) { + val = [ parseFloat( style ), unit ]; + } + } ); + return val; + }, + + cssClip: function( clipObj ) { + if ( clipObj ) { + return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + + clipObj.bottom + "px " + clipObj.left + "px)" ); + } + return parseClip( this.css( "clip" ), this ); + }, + + transfer: function( options, done ) { + var element = $( this ), + target = $( options.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $( "body" ), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, + endPosition = target.offset(), + animation = { + top: endPosition.top - fixTop, + left: endPosition.left - fixLeft, + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = element.offset(), + transfer = $( "
" ) + .appendTo( "body" ) + .addClass( options.className ) + .css( { + top: startPosition.top - fixTop, + left: startPosition.left - fixLeft, + height: element.innerHeight(), + width: element.innerWidth(), + position: targetFixed ? "fixed" : "absolute" + } ) + .animate( animation, options.duration, options.easing, function() { + transfer.remove(); + if ( $.isFunction( done ) ) { + done(); + } + } ); + } +} ); + +function parseClip( str, element ) { + var outerWidth = element.outerWidth(), + outerHeight = element.outerHeight(), + clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, + values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; + + return { + top: parseFloat( values[ 1 ] ) || 0, + right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), + bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), + left: parseFloat( values[ 4 ] ) || 0 + }; +} + +$.fx.step.clip = function( fx ) { + if ( !fx.clipInit ) { + fx.start = $( fx.elem ).cssClip(); + if ( typeof fx.end === "string" ) { + fx.end = parseClip( fx.end, fx.elem ); + } + fx.clipInit = true; + } + + $( fx.elem ).cssClip( { + top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, + right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, + bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, + left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left + } ); +}; + +} )(); + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +( function() { + +// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing) + +var baseEasings = {}; + +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +} ); + +$.extend( baseEasings, { + Sine: function( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); + }, + Circ: function( p ) { + return 1 - Math.sqrt( 1 - p * p ); + }, + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); + }, + Back: function( p ) { + return p * p * ( 3 * p - 2 ); + }, + Bounce: function( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); + } +} ); + +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < 0.5 ? + easeIn( p * 2 ) / 2 : + 1 - easeIn( p * -2 + 2 ) / 2; + }; +} ); + +} )(); + +var effect = $.effects; + + +/*! + * jQuery UI Effects Blind 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Blind Effect +//>>group: Effects +//>>description: Blinds the element. +//>>docs: http://api.jqueryui.com/blind-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { + var map = { + up: [ "bottom", "top" ], + vertical: [ "bottom", "top" ], + down: [ "top", "bottom" ], + left: [ "right", "left" ], + horizontal: [ "right", "left" ], + right: [ "left", "right" ] + }, + element = $( this ), + direction = options.direction || "up", + start = element.cssClip(), + animate = { clip: $.extend( {}, start ) }, + placeholder = $.effects.createPlaceholder( element ); + + animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; + + if ( options.mode === "show" ) { + element.cssClip( animate.clip ); + if ( placeholder ) { + placeholder.css( $.effects.clipToBox( animate ) ); + } + + animate.clip = start; + } + + if ( placeholder ) { + placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); + } + + element.animate( animate, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Bounce 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Bounce Effect +//>>group: Effects +//>>description: Bounces an element horizontally or vertically n times. +//>>docs: http://api.jqueryui.com/bounce-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { + var upAnim, downAnim, refValue, + element = $( this ), + + // Defaults: + mode = options.mode, + hide = mode === "hide", + show = mode === "show", + direction = options.direction || "up", + distance = options.distance, + times = options.times || 5, + + // Number of internal animations + anims = times * 2 + ( show || hide ? 1 : 0 ), + speed = options.duration / anims, + easing = options.easing, + + // Utility: + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ), + i = 0, + + queuelen = element.queue().length; + + $.effects.createPlaceholder( element ); + + refValue = element.css( ref ); + + // Default distance for the BIGGEST bounce is the outer Distance / 3 + if ( !distance ) { + distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; + } + + if ( show ) { + downAnim = { opacity: 1 }; + downAnim[ ref ] = refValue; + + // If we are showing, force opacity 0 and set the initial position + // then do the "first" animation + element + .css( "opacity", 0 ) + .css( ref, motion ? -distance * 2 : distance * 2 ) + .animate( downAnim, speed, easing ); + } + + // Start at the smallest distance if we are hiding + if ( hide ) { + distance = distance / Math.pow( 2, times - 1 ); + } + + downAnim = {}; + downAnim[ ref ] = refValue; + + // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here + for ( ; i < times; i++ ) { + upAnim = {}; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + element + .animate( upAnim, speed, easing ) + .animate( downAnim, speed, easing ); + + distance = hide ? distance * 2 : distance / 2; + } + + // Last Bounce when Hiding + if ( hide ) { + upAnim = { opacity: 0 }; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + element.animate( upAnim, speed, easing ); + } + + element.queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Clip 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Clip Effect +//>>group: Effects +//>>description: Clips the element on and off like an old TV. +//>>docs: http://api.jqueryui.com/clip-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { + var start, + animate = {}, + element = $( this ), + direction = options.direction || "vertical", + both = direction === "both", + horizontal = both || direction === "horizontal", + vertical = both || direction === "vertical"; + + start = element.cssClip(); + animate.clip = { + top: vertical ? ( start.bottom - start.top ) / 2 : start.top, + right: horizontal ? ( start.right - start.left ) / 2 : start.right, + bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, + left: horizontal ? ( start.right - start.left ) / 2 : start.left + }; + + $.effects.createPlaceholder( element ); + + if ( options.mode === "show" ) { + element.cssClip( animate.clip ); + animate.clip = start; + } + + element.animate( animate, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); + +} ); + + +/*! + * jQuery UI Effects Drop 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Drop Effect +//>>group: Effects +//>>description: Moves an element in one direction and hides it at the same time. +//>>docs: http://api.jqueryui.com/drop-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { + + var distance, + element = $( this ), + mode = options.mode, + show = mode === "show", + direction = options.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", + oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", + animation = { + opacity: 0 + }; + + $.effects.createPlaceholder( element ); + + distance = options.distance || + element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; + + animation[ ref ] = motion + distance; + + if ( show ) { + element.css( animation ); + + animation[ ref ] = oppositeMotion + distance; + animation.opacity = 1; + } + + // Animate + element.animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Explode 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Explode Effect +//>>group: Effects +// jscs:disable maximumLineLength +//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. +// jscs:enable maximumLineLength +//>>docs: http://api.jqueryui.com/explode-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { + + var i, j, left, top, mx, my, + rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, + cells = rows, + element = $( this ), + mode = options.mode, + show = mode === "show", + + // Show and then visibility:hidden the element before calculating offset + offset = element.show().css( "visibility", "hidden" ).offset(), + + // Width and height of a piece + width = Math.ceil( element.outerWidth() / cells ), + height = Math.ceil( element.outerHeight() / rows ), + pieces = []; + + // Children animate complete: + function childComplete() { + pieces.push( this ); + if ( pieces.length === rows * cells ) { + animComplete(); + } + } + + // Clone the element for each row and cell. + for ( i = 0; i < rows; i++ ) { // ===> + top = offset.top + i * height; + my = i - ( rows - 1 ) / 2; + + for ( j = 0; j < cells; j++ ) { // ||| + left = offset.left + j * width; + mx = j - ( cells - 1 ) / 2; + + // Create a clone of the now hidden main element that will be absolute positioned + // within a wrapper div off the -left and -top equal to size of our pieces + element + .clone() + .appendTo( "body" ) + .wrap( "
" ) + .css( { + position: "absolute", + visibility: "visible", + left: -j * width, + top: -i * height + } ) + + // Select the wrapper - make it overflow: hidden and absolute positioned based on + // where the original was located +left and +top equal to the size of pieces + .parent() + .addClass( "ui-effects-explode" ) + .css( { + position: "absolute", + overflow: "hidden", + width: width, + height: height, + left: left + ( show ? mx * width : 0 ), + top: top + ( show ? my * height : 0 ), + opacity: show ? 0 : 1 + } ) + .animate( { + left: left + ( show ? 0 : mx * width ), + top: top + ( show ? 0 : my * height ), + opacity: show ? 1 : 0 + }, options.duration || 500, options.easing, childComplete ); + } + } + + function animComplete() { + element.css( { + visibility: "visible" + } ); + $( pieces ).remove(); + done(); + } +} ); + + +/*! + * jQuery UI Effects Fade 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Fade Effect +//>>group: Effects +//>>description: Fades the element. +//>>docs: http://api.jqueryui.com/fade-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { + var show = options.mode === "show"; + + $( this ) + .css( "opacity", show ? 0 : 1 ) + .animate( { + opacity: show ? 1 : 0 + }, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Fold 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Fold Effect +//>>group: Effects +//>>description: Folds an element first horizontally and then vertically. +//>>docs: http://api.jqueryui.com/fold-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { + + // Create element + var element = $( this ), + mode = options.mode, + show = mode === "show", + hide = mode === "hide", + size = options.size || 15, + percent = /([0-9]+)%/.exec( size ), + horizFirst = !!options.horizFirst, + ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], + duration = options.duration / 2, + + placeholder = $.effects.createPlaceholder( element ), + + start = element.cssClip(), + animation1 = { clip: $.extend( {}, start ) }, + animation2 = { clip: $.extend( {}, start ) }, + + distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], + + queuelen = element.queue().length; + + if ( percent ) { + size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; + } + animation1.clip[ ref[ 0 ] ] = size; + animation2.clip[ ref[ 0 ] ] = size; + animation2.clip[ ref[ 1 ] ] = 0; + + if ( show ) { + element.cssClip( animation2.clip ); + if ( placeholder ) { + placeholder.css( $.effects.clipToBox( animation2 ) ); + } + + animation2.clip = start; + } + + // Animate + element + .queue( function( next ) { + if ( placeholder ) { + placeholder + .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) + .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); + } + + next(); + } ) + .animate( animation1, duration, options.easing ) + .animate( animation2, duration, options.easing ) + .queue( done ); + + $.effects.unshift( element, queuelen, 4 ); +} ); + + +/*! + * jQuery UI Effects Highlight 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Highlight Effect +//>>group: Effects +//>>description: Highlights the background of an element in a defined color for a custom duration. +//>>docs: http://api.jqueryui.com/highlight-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { + var element = $( this ), + animation = { + backgroundColor: element.css( "backgroundColor" ) + }; + + if ( options.mode === "hide" ) { + animation.opacity = 0; + } + + $.effects.saveStyle( element ); + + element + .css( { + backgroundImage: "none", + backgroundColor: options.color || "#ffff99" + } ) + .animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Size 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Size Effect +//>>group: Effects +//>>description: Resize an element to a specified width and height. +//>>docs: http://api.jqueryui.com/size-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectSize = $.effects.define( "size", function( options, done ) { + + // Create element + var baseline, factor, temp, + element = $( this ), + + // Copy for children + cProps = [ "fontSize" ], + vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], + hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], + + // Set options + mode = options.mode, + restore = mode !== "effect", + scale = options.scale || "both", + origin = options.origin || [ "middle", "center" ], + position = element.css( "position" ), + pos = element.position(), + original = $.effects.scaledDimensions( element ), + from = options.from || original, + to = options.to || $.effects.scaledDimensions( element, 0 ); + + $.effects.createPlaceholder( element ); + + if ( mode === "show" ) { + temp = from; + from = to; + to = temp; + } + + // Set scaling factor + factor = { + from: { + y: from.height / original.height, + x: from.width / original.width + }, + to: { + y: to.height / original.height, + x: to.width / original.width + } + }; + + // Scale the css box + if ( scale === "box" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + from = $.effects.setTransition( element, vProps, factor.from.y, from ); + to = $.effects.setTransition( element, vProps, factor.to.y, to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + from = $.effects.setTransition( element, hProps, factor.from.x, from ); + to = $.effects.setTransition( element, hProps, factor.to.x, to ); + } + } + + // Scale the content + if ( scale === "content" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + from = $.effects.setTransition( element, cProps, factor.from.y, from ); + to = $.effects.setTransition( element, cProps, factor.to.y, to ); + } + } + + // Adjust the position properties based on the provided origin points + if ( origin ) { + baseline = $.effects.getBaseline( origin, original ); + from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; + from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; + to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; + to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; + } + element.css( from ); + + // Animate the children if desired + if ( scale === "content" || scale === "both" ) { + + vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); + hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); + + // Only animate children with width attributes specified + // TODO: is this right? should we include anything with css width specified as well + element.find( "*[width]" ).each( function() { + var child = $( this ), + childOriginal = $.effects.scaledDimensions( child ), + childFrom = { + height: childOriginal.height * factor.from.y, + width: childOriginal.width * factor.from.x, + outerHeight: childOriginal.outerHeight * factor.from.y, + outerWidth: childOriginal.outerWidth * factor.from.x + }, + childTo = { + height: childOriginal.height * factor.to.y, + width: childOriginal.width * factor.to.x, + outerHeight: childOriginal.height * factor.to.y, + outerWidth: childOriginal.width * factor.to.x + }; + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); + childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); + childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); + } + + if ( restore ) { + $.effects.saveStyle( child ); + } + + // Animate children + child.css( childFrom ); + child.animate( childTo, options.duration, options.easing, function() { + + // Restore children + if ( restore ) { + $.effects.restoreStyle( child ); + } + } ); + } ); + } + + // Animate + element.animate( to, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: function() { + + var offset = element.offset(); + + if ( to.opacity === 0 ) { + element.css( "opacity", from.opacity ); + } + + if ( !restore ) { + element + .css( "position", position === "static" ? "relative" : position ) + .offset( offset ); + + // Need to save style here so that automatic style restoration + // doesn't restore to the original styles from before the animation. + $.effects.saveStyle( element ); + } + + done(); + } + } ); + +} ); + + +/*! + * jQuery UI Effects Scale 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Scale Effect +//>>group: Effects +//>>description: Grows or shrinks an element and its content. +//>>docs: http://api.jqueryui.com/scale-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectScale = $.effects.define( "scale", function( options, done ) { + + // Create element + var el = $( this ), + mode = options.mode, + percent = parseInt( options.percent, 10 ) || + ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), + + newOptions = $.extend( true, { + from: $.effects.scaledDimensions( el ), + to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), + origin: options.origin || [ "middle", "center" ] + }, options ); + + // Fade option to support puff + if ( options.fade ) { + newOptions.from.opacity = 1; + newOptions.to.opacity = 0; + } + + $.effects.effect.size.call( this, newOptions, done ); +} ); + + +/*! + * jQuery UI Effects Puff 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Puff Effect +//>>group: Effects +//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. +//>>docs: http://api.jqueryui.com/puff-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { + var newOptions = $.extend( true, {}, options, { + fade: true, + percent: parseInt( options.percent, 10 ) || 150 + } ); + + $.effects.effect.scale.call( this, newOptions, done ); +} ); + + +/*! + * jQuery UI Effects Pulsate 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Pulsate Effect +//>>group: Effects +//>>description: Pulsates an element n times by changing the opacity to zero and back. +//>>docs: http://api.jqueryui.com/pulsate-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { + var element = $( this ), + mode = options.mode, + show = mode === "show", + hide = mode === "hide", + showhide = show || hide, + + // Showing or hiding leaves off the "last" animation + anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), + duration = options.duration / anims, + animateTo = 0, + i = 1, + queuelen = element.queue().length; + + if ( show || !element.is( ":visible" ) ) { + element.css( "opacity", 0 ).show(); + animateTo = 1; + } + + // Anims - 1 opacity "toggles" + for ( ; i < anims; i++ ) { + element.animate( { opacity: animateTo }, duration, options.easing ); + animateTo = 1 - animateTo; + } + + element.animate( { opacity: animateTo }, duration, options.easing ); + + element.queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Shake 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Shake Effect +//>>group: Effects +//>>description: Shakes an element horizontally or vertically n times. +//>>docs: http://api.jqueryui.com/shake-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectShake = $.effects.define( "shake", function( options, done ) { + + var i = 1, + element = $( this ), + direction = options.direction || "left", + distance = options.distance || 20, + times = options.times || 3, + anims = times * 2 + 1, + speed = Math.round( options.duration / anims ), + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + positiveMotion = ( direction === "up" || direction === "left" ), + animation = {}, + animation1 = {}, + animation2 = {}, + + queuelen = element.queue().length; + + $.effects.createPlaceholder( element ); + + // Animation + animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; + animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; + animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; + + // Animate + element.animate( animation, speed, options.easing ); + + // Shakes + for ( ; i < times; i++ ) { + element + .animate( animation1, speed, options.easing ) + .animate( animation2, speed, options.easing ); + } + + element + .animate( animation1, speed, options.easing ) + .animate( animation, speed / 2, options.easing ) + .queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Slide 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Slide Effect +//>>group: Effects +//>>description: Slides an element in and out of the viewport. +//>>docs: http://api.jqueryui.com/slide-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { + var startClip, startRef, + element = $( this ), + map = { + up: [ "bottom", "top" ], + down: [ "top", "bottom" ], + left: [ "right", "left" ], + right: [ "left", "right" ] + }, + mode = options.mode, + direction = options.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + positiveMotion = ( direction === "up" || direction === "left" ), + distance = options.distance || + element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), + animation = {}; + + $.effects.createPlaceholder( element ); + + startClip = element.cssClip(); + startRef = element.position()[ ref ]; + + // Define hide animation + animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; + animation.clip = element.cssClip(); + animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; + + // Reverse the animation if we're showing + if ( mode === "show" ) { + element.cssClip( animation.clip ); + element.css( ref, animation[ ref ] ); + animation.clip = startClip; + animation[ ref ] = startRef; + } + + // Actually animate + element.animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Transfer 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Transfer Effect +//>>group: Effects +//>>description: Displays a transfer effect from one element to another. +//>>docs: http://api.jqueryui.com/transfer-effect/ +//>>demos: http://jqueryui.com/effect/ + + + +var effect; +if ( $.uiBackCompat !== false ) { + effect = $.effects.define( "transfer", function( options, done ) { + $( this ).transfer( options, done ); + } ); +} +var effectsEffectTransfer = effect; + + +/*! + * jQuery UI Focusable 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :focusable Selector +//>>group: Core +//>>description: Selects elements which can be focused. +//>>docs: http://api.jqueryui.com/focusable-selector/ + + + +// Selectors +$.ui.focusable = function( element, hasTabindex ) { + var map, mapName, img, focusableIfVisible, fieldset, + nodeName = element.nodeName.toLowerCase(); + + if ( "area" === nodeName ) { + map = element.parentNode; + mapName = map.name; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap='#" + mapName + "']" ); + return img.length > 0 && img.is( ":visible" ); + } + + if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { + focusableIfVisible = !element.disabled; + + if ( focusableIfVisible ) { + + // Form controls within a disabled fieldset are disabled. + // However, controls within the fieldset's legend do not get disabled. + // Since controls generally aren't placed inside legends, we skip + // this portion of the check. + fieldset = $( element ).closest( "fieldset" )[ 0 ]; + if ( fieldset ) { + focusableIfVisible = !fieldset.disabled; + } + } + } else if ( "a" === nodeName ) { + focusableIfVisible = element.href || hasTabindex; + } else { + focusableIfVisible = hasTabindex; + } + + return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) ); +}; + +// Support: IE 8 only +// IE 8 doesn't resolve inherit to visible/hidden for computed values +function visible( element ) { + var visibility = element.css( "visibility" ); + while ( visibility === "inherit" ) { + element = element.parent(); + visibility = element.css( "visibility" ); + } + return visibility !== "hidden"; +} + +$.extend( $.expr[ ":" ], { + focusable: function( element ) { + return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); + } +} ); + +var focusable = $.ui.focusable; + + + + +// Support: IE8 Only +// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop +// with a string, so we need to find the proper form. +var form = $.fn.form = function() { + return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); +}; + + +/*! + * jQuery UI Form Reset Mixin 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Form Reset Mixin +//>>group: Core +//>>description: Refresh input widgets when their form is reset +//>>docs: http://api.jqueryui.com/form-reset-mixin/ + + + +var formResetMixin = $.ui.formResetMixin = { + _formResetHandler: function() { + var form = $( this ); + + // Wait for the form reset to actually happen before refreshing + setTimeout( function() { + var instances = form.data( "ui-form-reset-instances" ); + $.each( instances, function() { + this.refresh(); + } ); + } ); + }, + + _bindFormResetHandler: function() { + this.form = this.element.form(); + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ) || []; + if ( !instances.length ) { + + // We don't use _on() here because we use a single event handler per form + this.form.on( "reset.ui-form-reset", this._formResetHandler ); + } + instances.push( this ); + this.form.data( "ui-form-reset-instances", instances ); + }, + + _unbindFormResetHandler: function() { + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ); + instances.splice( $.inArray( this, instances ), 1 ); + if ( instances.length ) { + this.form.data( "ui-form-reset-instances", instances ); + } else { + this.form + .removeData( "ui-form-reset-instances" ) + .off( "reset.ui-form-reset" ); + } + } +}; + + +/*! + * jQuery UI Support for jQuery core 1.7.x 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + */ + +//>>label: jQuery 1.7 Support +//>>group: Core +//>>description: Support version 1.7.x of jQuery core + + + +// Support: jQuery 1.7 only +// Not a great way to check versions, but since we only support 1.7+ and only +// need to detect <1.8, this is a simple check that should suffice. Checking +// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0 +// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting +// 1.7 anymore). See #11197 for why we're not using feature detection. +if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) { + + // Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight() + // Unlike jQuery Core 1.8+, these only support numeric values to set the + // dimensions in pixels + $.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; + if ( border ) { + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; + } + } ); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each( function() { + $( this ).css( type, reduce( this, size ) + "px" ); + } ); + }; + + $.fn[ "outer" + name ] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each( function() { + $( this ).css( type, reduce( this, size, true, margin ) + "px" ); + } ); + }; + } ); + + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +; +/*! + * jQuery UI Keycode 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Keycode +//>>group: Core +//>>description: Provide keycodes as keynames +//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/ + + +var keycode = $.ui.keyCode = { + BACKSPACE: 8, + COMMA: 188, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + LEFT: 37, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SPACE: 32, + TAB: 9, + UP: 38 +}; + + + + +// Internal use only +var escapeSelector = $.ui.escapeSelector = ( function() { + var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g; + return function( selector ) { + return selector.replace( selectorEscape, "\\$1" ); + }; +} )(); + + +/*! + * jQuery UI Labels 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: labels +//>>group: Core +//>>description: Find all the labels associated with a given input +//>>docs: http://api.jqueryui.com/labels/ + + + +var labels = $.fn.labels = function() { + var ancestor, selector, id, labels, ancestors; + + // Check control.labels first + if ( this[ 0 ].labels && this[ 0 ].labels.length ) { + return this.pushStack( this[ 0 ].labels ); + } + + // Support: IE <= 11, FF <= 37, Android <= 2.3 only + // Above browsers do not support control.labels. Everything below is to support them + // as well as document fragments. control.labels does not work on document fragments + labels = this.eq( 0 ).parents( "label" ); + + // Look for the label based on the id + id = this.attr( "id" ); + if ( id ) { + + // We don't search against the document in case the element + // is disconnected from the DOM + ancestor = this.eq( 0 ).parents().last(); + + // Get a full set of top level ancestors + ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); + + // Create a selector for the label based on the id + selector = "label[for='" + $.ui.escapeSelector( id ) + "']"; + + labels = labels.add( ancestors.find( selector ).addBack( selector ) ); + + } + + // Return whatever we have found for labels + return this.pushStack( labels ); +}; + + +/*! + * jQuery UI Scroll Parent 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: scrollParent +//>>group: Core +//>>description: Get the closest ancestor element that is scrollable. +//>>docs: http://api.jqueryui.com/scrollParent/ + + + +var scrollParent = $.fn.scrollParent = function( includeHidden ) { + var position = this.css( "position" ), + excludeStaticParent = position === "absolute", + overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, + scrollParent = this.parents().filter( function() { + var parent = $( this ); + if ( excludeStaticParent && parent.css( "position" ) === "static" ) { + return false; + } + return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + + parent.css( "overflow-x" ) ); + } ).eq( 0 ); + + return position === "fixed" || !scrollParent.length ? + $( this[ 0 ].ownerDocument || document ) : + scrollParent; +}; + + +/*! + * jQuery UI Tabbable 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :tabbable Selector +//>>group: Core +//>>description: Selects elements which can be tabbed to. +//>>docs: http://api.jqueryui.com/tabbable-selector/ + + + +var tabbable = $.extend( $.expr[ ":" ], { + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + hasTabindex = tabIndex != null; + return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); + } +} ); + + +/*! + * jQuery UI Unique ID 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: uniqueId +//>>group: Core +//>>description: Functions to generate and remove uniqueId's +//>>docs: http://api.jqueryui.com/uniqueId/ + + + +var uniqueId = $.fn.extend( { + uniqueId: ( function() { + var uuid = 0; + + return function() { + return this.each( function() { + if ( !this.id ) { + this.id = "ui-id-" + ( ++uuid ); + } + } ); + }; + } )(), + + removeUniqueId: function() { + return this.each( function() { + if ( /^ui-id-\d+$/.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } + } ); + } +} ); + + +/*! + * jQuery UI Accordion 1.12.1 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Accordion +//>>group: Widgets +// jscs:disable maximumLineLength +//>>description: Displays collapsible content panels for presenting information in a limited amount of space. +// jscs:enable maximumLineLength +//>>docs: http://api.jqueryui.com/accordion/ +//>>demos: http://jqueryui.com/accordion/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/accordion.css +//>>css.theme: ../../themes/base/theme.css + + + +var widgetsAccordion = $.widget( "ui.accordion", { + version: "1.12.1", + options: { + active: 0, + animate: {}, + classes: { + "ui-accordion-header": "ui-corner-top", + "ui-accordion-header-collapsed": "ui-corner-all", + "ui-accordion-content": "ui-corner-bottom" + }, + collapsible: false, + event: "click", + header: "> li > :first-child, > :not(li):even", + heightStyle: "auto", + icons: { + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" + }, + + // Callbacks + activate: null, + beforeActivate: null + }, + + hideProps: { + borderTopWidth: "hide", + borderBottomWidth: "hide", + paddingTop: "hide", + paddingBottom: "hide", + height: "hide" + }, + + showProps: { + borderTopWidth: "show", + borderBottomWidth: "show", + paddingTop: "show", + paddingBottom: "show", + height: "show" + }, + + _create: function() { + var options = this.options; + + this.prevShow = this.prevHide = $(); + this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); + this.element.attr( "role", "tablist" ); + + // Don't allow collapsible: false and active: false / null + if ( !options.collapsible && ( options.active === false || options.active == null ) ) { + options.active = 0; + } + + this._processPanels(); + + // handle negative values + if ( options.active < 0 ) { + options.active += this.headers.length; + } + this._refresh(); + }, + + _getCreateEventData: function() { + return { + header: this.active, + panel: !this.active.length ? $() : this.active.next() + }; + }, + + _createIcons: function() { + var icon, children, + icons = this.options.icons; + + if ( icons ) { + icon = $( "" ); + this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); + icon.prependTo( this.headers ); + children = this.active.children( ".ui-accordion-header-icon" ); + this._removeClass( children, icons.header ) + ._addClass( children, null, icons.activeHeader ) + ._addClass( this.headers, "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this._removeClass( this.headers, "ui-accordion-icons" ); + this.headers.children( ".ui-accordion-header-icon" ).remove(); + }, + + _destroy: function() { + var contents; + + // Clean up main element + this.element.removeAttr( "role" ); + + // Clean up headers + this.headers + .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) + .removeUniqueId(); + + this._destroyIcons(); + + // Clean up content panels + contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role aria-hidden aria-labelledby" ) + .removeUniqueId(); + + if ( this.options.heightStyle !== "content" ) { + contents.css( "height", "" ); + } + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "event" ) { + if ( this.options.event ) { + this._off( this.headers, this.options.event ); + } + this._setupEvents( value ); + } + + this._super( key, value ); + + // Setting collapsible: false while collapsed; open first panel + if ( key === "collapsible" && !value && this.options.active === false ) { + this._activate( 0 ); + } + + if ( key === "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + }, + + _setOptionDisabled: function( value ) { + this._super( value ); + + this.element.attr( "aria-disabled", value ); + + // Support: IE8 Only + // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + this._toggleClass( null, "ui-state-disabled", !!value ); + this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", + !!value ); + }, + + _keydown: function( event ) { + if ( event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._eventHandler( event ); + break; + case keyCode.HOME: + toFocus = this.headers[ 0 ]; + break; + case keyCode.END: + toFocus = this.headers[ length - 1 ]; + break; + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + $( toFocus ).trigger( "focus" ); + event.preventDefault(); + } + }, + + _panelKeyDown: function( event ) { + if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { + $( event.currentTarget ).prev().trigger( "focus" ); + } + }, + + refresh: function() { + var options = this.options; + this._processPanels(); + + // Was collapsed or no panel + if ( ( options.active === false && options.collapsible === true ) || + !this.headers.length ) { + options.active = false; + this.active = $(); + + // active false only when collapsible is true + } else if ( options.active === false ) { + this._activate( 0 ); + + // was active, but active panel is gone + } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + + // all remaining panel are disabled + if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { + options.active = false; + this.active = $(); + + // activate previous panel + } else { + this._activate( Math.max( 0, options.active - 1 ) ); + } + + // was active, active panel still exists + } else { + + // make sure active index is correct + options.active = this.headers.index( this.active ); + } + + this._destroyIcons(); + + this._refresh(); + }, + + _processPanels: function() { + var prevHeaders = this.headers, + prevPanels = this.panels; + + this.headers = this.element.find( this.options.header ); + this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", + "ui-state-default" ); + + this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); + this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); + + // Avoid memory leaks (#10056) + if ( prevPanels ) { + this._off( prevHeaders.not( this.headers ) ); + this._off( prevPanels.not( this.panels ) ); + } + }, + + _refresh: function() { + var maxHeight, + options = this.options, + heightStyle = options.heightStyle, + parent = this.element.parent(); + + this.active = this._findActive( options.active ); + this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) + ._removeClass( this.active, "ui-accordion-header-collapsed" ); + this._addClass( this.active.next(), "ui-accordion-content-active" ); + this.active.next().show(); + + this.headers + .attr( "role", "tab" ) + .each( function() { + var header = $( this ), + headerId = header.uniqueId().attr( "id" ), + panel = header.next(), + panelId = panel.uniqueId().attr( "id" ); + header.attr( "aria-controls", panelId ); + panel.attr( "aria-labelledby", headerId ); + } ) + .next() + .attr( "role", "tabpanel" ); + + this.headers + .not( this.active ) + .attr( { + "aria-selected": "false", + "aria-expanded": "false", + tabIndex: -1 + } ) + .next() + .attr( { + "aria-hidden": "true" + } ) + .hide(); + + // Make sure at least one header is in the tab order + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active.attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ) + .next() + .attr( { + "aria-hidden": "false" + } ); + } + + this._createIcons(); + + this._setupEvents( options.event ); + + if ( heightStyle === "fill" ) { + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each( function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + } ); + + this.headers.each( function() { + maxHeight -= $( this ).outerHeight( true ); + } ); + + this.headers.next() + .each( function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + } ) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.headers.next() + .each( function() { + var isVisible = $( this ).is( ":visible" ); + if ( !isVisible ) { + $( this ).show(); + } + maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); + if ( !isVisible ) { + $( this ).hide(); + } + } ) + .height( maxHeight ); + } + }, + + _activate: function( index ) { + var active = this._findActive( index )[ 0 ]; + + // Trying to activate the already active panel + if ( active === this.active[ 0 ] ) { + return; + } + + // Trying to collapse, simulate a click on the currently active header + active = active || this.active[ 0 ]; + + this._eventHandler( { + target: active, + currentTarget: active, + preventDefault: $.noop + } ); + }, + + _findActive: function( selector ) { + return typeof selector === "number" ? this.headers.eq( selector ) : $(); + }, + + _setupEvents: function( event ) { + var events = { + keydown: "_keydown" + }; + if ( event ) { + $.each( event.split( " " ), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + } ); + } + + this._off( this.headers.add( this.headers.next() ) ); + this._on( this.headers, events ); + this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + }, + + _eventHandler: function( event ) { + var activeChildren, clickedChildren, + options = this.options, + active = this.active, + clicked = $( event.currentTarget ), + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldPanel: toHide, + newHeader: collapsing ? $() : clicked, + newPanel: toShow + }; + + event.preventDefault(); + + if ( + + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); + + // When the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $() : clicked; + this._toggle( eventData ); + + // Switch classes + // corner classes on the previously active header stay after the animation + this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); + if ( options.icons ) { + activeChildren = active.children( ".ui-accordion-header-icon" ); + this._removeClass( activeChildren, null, options.icons.activeHeader ) + ._addClass( activeChildren, null, options.icons.header ); + } + + if ( !clickedIsActive ) { + this._removeClass( clicked, "ui-accordion-header-collapsed" ) + ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); + if ( options.icons ) { + clickedChildren = clicked.children( ".ui-accordion-header-icon" ); + this._removeClass( clickedChildren, null, options.icons.header ) + ._addClass( clickedChildren, null, options.icons.activeHeader ); + } + + this._addClass( clicked.next(), "ui-accordion-content-active" ); + } + }, + + _toggle: function( data ) { + var toShow = data.newPanel, + toHide = this.prevShow.length ? this.prevShow : data.oldPanel; + + // Handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; + + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); + } else { + toHide.hide(); + toShow.show(); + this._toggleComplete( data ); + } + + toHide.attr( { + "aria-hidden": "true" + } ); + toHide.prev().attr( { + "aria-selected": "false", + "aria-expanded": "false" + } ); + + // if we're switching panels, remove the old header from the tab order + // if we're opening from collapsed state, remove the previous header from the tab order + // if we're collapsing, then keep the collapsing header in the tab order + if ( toShow.length && toHide.length ) { + toHide.prev().attr( { + "tabIndex": -1, + "aria-expanded": "false" + } ); + } else if ( toShow.length ) { + this.headers.filter( function() { + return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; + } ) + .attr( "tabIndex", -1 ); + } + + toShow + .attr( "aria-hidden", "false" ) + .prev() + .attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ); + }, + + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + adjust = 0, + boxSizing = toShow.css( "box-sizing" ), + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + that._toggleComplete( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.length ) { + return toShow.animate( this.showProps, duration, easing, complete ); + } + if ( !toShow.length ) { + return toHide.animate( this.hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( this.hideProps, { + duration: duration, + easing: easing, + step: function( now, fx ) { + fx.now = Math.round( now ); + } + } ); + toShow + .hide() + .animate( this.showProps, { + duration: duration, + easing: easing, + complete: complete, + step: function( now, fx ) { + fx.now = Math.round( now ); + if ( fx.prop !== "height" ) { + if ( boxSizing === "content-box" ) { + adjust += fx.now; + } + } else if ( that.options.heightStyle !== "content" ) { + fx.now = Math.round( total - toHide.outerHeight() - adjust ); + adjust = 0; + } + } + } ); + }, + + _toggleComplete: function( data ) { + var toHide = data.oldPanel, + prev = toHide.prev(); + + this._removeClass( toHide, "ui-accordion-content-active" ); + this._removeClass( prev, "ui-accordion-header-active" ) + ._addClass( prev, "ui-accordion-header-collapsed" ); + + // Work around for rendering bug in IE (#5421) + if ( toHide.length ) { + toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; + } + this._trigger( "activate", null, data ); + } +} ); + + + +var safeActiveElement = $.ui.safeActiveElement = function( document ) { + var activeElement; + + // Support: IE 9 only + // IE9 throws an "Unspecified error" accessing document.activeElement from an