diff --git a/resources/Highway_cameras_style_2/Read Me.txt b/resources/Highway_cameras_style_2/Read Me.txt new file mode 100644 index 000000000..ad3f2095e --- /dev/null +++ b/resources/Highway_cameras_style_2/Read Me.txt @@ -0,0 +1,3 @@ +This is a simple ymap to add cameras to all the highways. This style is for a newer camera model. + +Map made by WolfoTheWolf for Phantom Productions. \ No newline at end of file diff --git a/resources/Highway_cameras_style_2/fxmanifest.lua b/resources/Highway_cameras_style_2/fxmanifest.lua new file mode 100644 index 000000000..bfbb7da8e --- /dev/null +++ b/resources/Highway_cameras_style_2/fxmanifest.lua @@ -0,0 +1,8 @@ +fx_version 'cerulean' +games { 'gta5' } + +author 'Phantom Productions | WolfoTheWolf' +description 'This is the second style of cameras for the ymap, includes more of a "newer/updated" style.' +version '1.0.0' + +this_is_a_map 'yes' \ No newline at end of file diff --git a/resources/Highway_cameras_style_2/stream/cctv_v2.ymap b/resources/Highway_cameras_style_2/stream/cctv_v2.ymap new file mode 100644 index 000000000..186656cf8 --- /dev/null +++ b/resources/Highway_cameras_style_2/stream/cctv_v2.ymap @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3a9a5cabb1baf29ed0ba712efdd7626b4e33ab72818bb2127aee907c29cc400 +size 3013 diff --git a/resources/K9_ped/__resource.lua b/resources/K9_ped/__resource.lua new file mode 100644 index 000000000..1ebb8b7d5 --- /dev/null +++ b/resources/K9_ped/__resource.lua @@ -0,0 +1,9 @@ +-- Manifest +resource_manifest_version '77731fab-63ca-442c-a67b-abc70f28dfa5' + +files { +'peds.meta', +} + + +-- data_file 'PED_METADATA_FILE' 'peds.meta' \ No newline at end of file diff --git a/resources/K9_ped/peds.meta b/resources/K9_ped/peds.meta new file mode 100644 index 000000000..2523d5bcd --- /dev/null +++ b/resources/K9_ped/peds.meta @@ -0,0 +1,43 @@ + + + + + a_c_shepherd + move_m@generic + expr_set_ambient_male + ANIMAL + move_m@business@c + move_ped_strafing + move_ped_to_strafe + move_strafe_injured + dam_ko + dam_ad + ANIM_GROUP_GESTURE_M_GENERIC + facial_clipset_group_gen_male + ANIM_GROUP_VISEMES_M_LO + Male + Male_prone + NMBS_SLOW_GETUPS + null + DEFAULT + STANDARD_PED + STANDARD_PED + STANDARD_MALE + ANIMAL + STANDARD_PED + DEFAULT_PERCEPTION + BS_AI + WEAPON_UNARMED + SERVICEMALES + DEFAULT + VFXPEDINFO_HUMAN_GENERIC + FLEE + SAT_NONE + TB_WARM + SLOD_HUMAN + SCENARIO_POP_STREAMING_NORMAL + DSP_NORMAL + + + + \ No newline at end of file diff --git a/resources/K9_ped/stream/a_c_shepherd.yft b/resources/K9_ped/stream/a_c_shepherd.yft new file mode 100644 index 000000000..f120334e0 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd.yft @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5a1dc24dfa0c6b0dc480c73ad7636face906482011077637f5940d9c350326a +size 17157 diff --git a/resources/K9_ped/stream/a_c_shepherd.ymt b/resources/K9_ped/stream/a_c_shepherd.ymt new file mode 100644 index 000000000..00f6b1cac Binary files /dev/null and b/resources/K9_ped/stream/a_c_shepherd.ymt differ diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_000_u.ydd b/resources/K9_ped/stream/a_c_shepherd^accs_000_u.ydd new file mode 100644 index 000000000..3adb7e2c6 Binary files /dev/null and b/resources/K9_ped/stream/a_c_shepherd^accs_000_u.ydd differ diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_a_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_a_uni.ytd new file mode 100644 index 000000000..3e2de141e --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_a_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c3da0123870c797dc4aafa84aa467dc657be925cb660a5182b9f35ca96bb4f4 +size 816597 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_b_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_b_uni.ytd new file mode 100644 index 000000000..bc82bb186 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_b_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46a8ff74e27a7b2bc79f8a870772885b5fc3882ce77efb60e1e8f3324d8576f1 +size 1081284 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_c_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_c_uni.ytd new file mode 100644 index 000000000..addc45d4e --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_c_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27a650e1fc505f020fd3e442dafa3894cf43d92bb88da4466dc09732f0dbeed5 +size 1092773 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_d_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_d_uni.ytd new file mode 100644 index 000000000..a33f8feb6 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_d_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9c97d382f554c9130fa64759f5cb2a4c76b005ff0910896d295c414d634557a +size 1124502 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_e_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_e_uni.ytd new file mode 100644 index 000000000..8f69e7150 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_e_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85a5493bf2606155c9cdde850a5510bfd890559294029c0518707ad7072fddfb +size 816599 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_f_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_f_uni.ytd new file mode 100644 index 000000000..569f824cb --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_f_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a9c370fcd66e113d8a0129e761b77a3b509c1c1c3627718eddf8ef713d48f91 +size 1081281 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_g_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_g_uni.ytd new file mode 100644 index 000000000..0df4e85a8 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_g_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eae286aef1d4fee6c04b387a95ce729661a745866c3de8d2904a5ce7460ef358 +size 1092773 diff --git a/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_h_uni.ytd b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_h_uni.ytd new file mode 100644 index 000000000..eb2c9e815 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^accs_diff_000_h_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd778bff1533bb2d8cfcfb5b0946eb2b75dd455e3338ea67b72d72037c74606b +size 1124501 diff --git a/resources/K9_ped/stream/a_c_shepherd^head_000_r.ydd b/resources/K9_ped/stream/a_c_shepherd^head_000_r.ydd new file mode 100644 index 000000000..60d99e1ad Binary files /dev/null and b/resources/K9_ped/stream/a_c_shepherd^head_000_r.ydd differ diff --git a/resources/K9_ped/stream/a_c_shepherd^head_diff_000_a_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_a_whi.ytd new file mode 100644 index 000000000..942843537 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_a_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8248a98def7b5a5674d7790168c5a8bdc5fb9b789b606cdbb6a25b97be0c6655 +size 8897696 diff --git a/resources/K9_ped/stream/a_c_shepherd^head_diff_000_b_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_b_whi.ytd new file mode 100644 index 000000000..8889d8920 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_b_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5862362b0e0127fd88c30646ec0b8869a5dab45301a6ac53f6d188f69f2b830 +size 8616083 diff --git a/resources/K9_ped/stream/a_c_shepherd^head_diff_000_c_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_c_whi.ytd new file mode 100644 index 000000000..d88555112 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_c_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f699ad159cfe8d2b0b0b0f42723e7648f19bef24c0cb130b67b8620172202634 +size 7426333 diff --git a/resources/K9_ped/stream/a_c_shepherd^head_diff_000_d_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_d_whi.ytd new file mode 100644 index 000000000..df5226bc8 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^head_diff_000_d_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73bde37f3068d7660dd4d05e25ea084d9c22db45f291d35a243f4865e774690d +size 6786818 diff --git a/resources/K9_ped/stream/a_c_shepherd^lowr_000_r.ydd b/resources/K9_ped/stream/a_c_shepherd^lowr_000_r.ydd new file mode 100644 index 000000000..f3c929c41 Binary files /dev/null and b/resources/K9_ped/stream/a_c_shepherd^lowr_000_r.ydd differ diff --git a/resources/K9_ped/stream/a_c_shepherd^lowr_diff_000_a_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^lowr_diff_000_a_whi.ytd new file mode 100644 index 000000000..9aa8b6a61 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^lowr_diff_000_a_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edf3eed7e212ea8469f9d3bc3daf474dd93c5677b6e8bda7273bb09791609f7f +size 185 diff --git a/resources/K9_ped/stream/a_c_shepherd^uppr_000_r.ydd b/resources/K9_ped/stream/a_c_shepherd^uppr_000_r.ydd new file mode 100644 index 000000000..173c4a602 Binary files /dev/null and b/resources/K9_ped/stream/a_c_shepherd^uppr_000_r.ydd differ diff --git a/resources/K9_ped/stream/a_c_shepherd^uppr_000_u.ydd b/resources/K9_ped/stream/a_c_shepherd^uppr_000_u.ydd new file mode 100644 index 000000000..c35a034cc Binary files /dev/null and b/resources/K9_ped/stream/a_c_shepherd^uppr_000_u.ydd differ diff --git a/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_a_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_a_whi.ytd new file mode 100644 index 000000000..7da9a4ff5 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_a_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adf024f477cda2a453fccca499b45125e45d522ba3f5e9c7287ddccedd5fd27e +size 5694988 diff --git a/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_b_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_b_whi.ytd new file mode 100644 index 000000000..6afc4bbff --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_b_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be6d9262ad3cc5f55eef8fe94281810e1dfe963af2c96a5bffb5bb5af56b9a81 +size 5689682 diff --git a/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_c_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_c_whi.ytd new file mode 100644 index 000000000..7303f959b --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_c_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3220d3ff6b346294c5954efb44dce66bc2b6178bd5e0b24714bcdbf6e8341e3c +size 5396171 diff --git a/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_d_whi.ytd b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_d_whi.ytd new file mode 100644 index 000000000..72ec946b1 --- /dev/null +++ b/resources/K9_ped/stream/a_c_shepherd^uppr_diff_000_d_whi.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:20c2d07feec35b03bd7a78254a8ce3455b81894e786547887f10f7c19394b834 +size 6264840 diff --git a/resources/KiloImmersiveTackle/KiloImmersiveTackle.net.dll b/resources/KiloImmersiveTackle/KiloImmersiveTackle.net.dll new file mode 100644 index 000000000..25321e085 Binary files /dev/null and b/resources/KiloImmersiveTackle/KiloImmersiveTackle.net.dll differ diff --git a/resources/KiloImmersiveTackle/LICENSE b/resources/KiloImmersiveTackle/LICENSE new file mode 100644 index 000000000..4cf560b89 --- /dev/null +++ b/resources/KiloImmersiveTackle/LICENSE @@ -0,0 +1,9 @@ +Copyright (C) 2025 DevKilo + +Permission is hereby granted, without charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software with restrictions to sell, distribute, or publish this Software, and freedoms include the rights to use, copy, modify, and sublicense this Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +THIS COPYRIGHT NOTICE IS A MODIFIED VERSION OF MIT LICENSE AND WAS MODIFIED BY THE COPYRIGHT HOLDER \ No newline at end of file diff --git a/resources/KiloImmersiveTackle/Newtonsoft.Json.dll b/resources/KiloImmersiveTackle/Newtonsoft.Json.dll new file mode 100644 index 000000000..6e233b9f7 Binary files /dev/null and b/resources/KiloImmersiveTackle/Newtonsoft.Json.dll differ diff --git a/resources/KiloImmersiveTackle/Tackle-server.net.dll b/resources/KiloImmersiveTackle/Tackle-server.net.dll new file mode 100644 index 000000000..e51ecfd58 Binary files /dev/null and b/resources/KiloImmersiveTackle/Tackle-server.net.dll differ diff --git a/resources/KiloImmersiveTackle/config.json b/resources/KiloImmersiveTackle/config.json new file mode 100644 index 000000000..ecce01079 --- /dev/null +++ b/resources/KiloImmersiveTackle/config.json @@ -0,0 +1,7 @@ +{ + "EnableOnPlayers": true, + "EnableOnAI": true, + "KnockWindOutOfPlayerWhenKnocked": true, + "DefaultTackleKey": "h", + "Note": "KnockWindOutOfPlayerWhenKnocked will remove the player's stamina. This is universal but will only affect the player with certain stamina scripts such as qb-hud." +} \ No newline at end of file diff --git a/resources/KiloImmersiveTackle/fxmanifest.lua b/resources/KiloImmersiveTackle/fxmanifest.lua new file mode 100644 index 000000000..2485f3fef --- /dev/null +++ b/resources/KiloImmersiveTackle/fxmanifest.lua @@ -0,0 +1,12 @@ +game 'gta5' +fx_version 'cerulean' + +author 'DevKilo' + +files { + 'Newtonsoft.Json.dll', + 'config.json' +} + +client_script 'KiloImmersiveTackle.net.dll' +server_script 'Tackle-server.net.dll' \ No newline at end of file diff --git a/resources/axonbody3-main/README.md b/resources/axonbody3-main/README.md new file mode 100644 index 000000000..66c3afc63 --- /dev/null +++ b/resources/axonbody3-main/README.md @@ -0,0 +1,13 @@ +

FiveM Axon Body 3 FORK

+ + +## Configuration +Change the framework name in config to match the folder name. + +## Credits +[Original Author](https://github.com/TFNRP/axonbody3) + + +## Screenshots + +![img](https://cdn.nat2k15.xyz/img/FiveM_GTAProcess_ybEvj9zdC7.png) diff --git a/resources/axonbody3-main/client/client.lua b/resources/axonbody3-main/client/client.lua new file mode 100644 index 000000000..864e00a78 --- /dev/null +++ b/resources/axonbody3-main/client/client.lua @@ -0,0 +1,160 @@ +-- globals +local hudForceHide = false +local hudPresence +local activated = false + +---------------------------------------------------------- +-------------------- Commands +---------------------------------------------------------- + + +-- HUD + +RegisterCommand('axonhide', function() + hudForceHide = true + ShowNotification("~y~Axon Body 3~s~ overlay now ~r~hidden~s~.") +end) + +RegisterCommand('axonshow', function() + hudForceHide = false + ShowNotification("~y~Axon Body 3~s~ overlay now ~g~visible~s~.") +end) + +-- Activation and deactivation + +if Config.CommandBinding then + RegisterKeyMapping('axon', 'Toggle Axon Body 3', 'keyboard', Config.CommandBinding) +end +RegisterCommand('axon', function () + if activated then + DeactivateAB3() + ShowNotification("~y~Axon Body 3~s~ has ~r~stopped recording~s~.") + else + local server_id = GetPlayerServerId(PlayerId()) + local player = exports[Config.framework_name]:getclientdept(server_id) + if(player ~= nil) then + if(player[server_id].dept ~= "Civilian") then + ActivateAB3(player[server_id].char_name .. " (" .. player[server_id].dept .. ")") + ShowNotification("~y~Axon Body 3~s~ has ~g~started recording~s~.") + else + -- ShowNotification("You have to be ~r~on duty~s~ to enable ~y~Axon Body 3~s~.") + end + end + end +end) + +RegisterCommand('axonon', function () + local server_id = GetPlayerServerId(PlayerId()) + local player = exports[Config.framework_name]:getclientdept(server_id) + if(player ~= nil) then + if(player[server_id].dept ~= "Civilian") then + if activated then + ShowNotification("~y~Axon Body 3~s~ is already ~g~recording~s~.") + else + + ActivateAB3(player[server_id].char_name .. " (" .. player[server_id].dept .. ")") + ShowNotification("~y~Axon Body 3~s~ has ~g~started recording~s~.") + end + else + -- ShowNotification("You have to be ~r~on duty~s~ to use ~y~Axon Body 3~s~.") + end + end +end) + +RegisterCommand('axonoff', function () + if not activated then + ShowNotification("~y~Axon Body 3~s~ has already ~r~stopped recording~s~.") + else + DeactivateAB3() + ShowNotification("~y~Axon Body 3~s~ has ~r~stopped recording~s~.") + end +end) + + +---------------------------------------------------------- +---------------------------------------------------------- +---------------------------------------------------------- + + +-- Events + +RegisterNetEvent("AB3:SetState", function(state) + if state == true then + ActivateAB3() + elseif state == false then + DeactivateAB3() + end +end) + +RegisterNetEvent("AB3:ServerBeep", function(netId) + local otherPed = GetPlayerPed(GetPlayerFromServerId(netId)) + local ped = PlayerPedId() + if (IsPedInAnyVehicle(ped) == IsPedInAnyVehicle(otherPed)) or not IsPedInAnyVehicle(ped) then + local volume = 0.05 + local radius = 10 + + local playerCoords = GetEntityCoords(ped); + local targetCoords = GetEntityCoords(otherPed); + + local distance = Vdist(playerCoords.x, playerCoords.y, playerCoords.z, targetCoords.x, targetCoords.y, targetCoords.z); + local distanceVolumeMultiplier = volume / radius; + local distanceVolume = volume - (distance * distanceVolumeMultiplier); + + if (distance <= radius) then + SendNUIMessage({ AxonBeep = { volume = distanceVolume } }) + end + end +end) + +-- Utils + +function ActivateAB3(name) + if activated then + return error("AB3 attempted to activate when already active.") + end + + activated = true + + -- beeper + -- Citizen.CreateThread(function() + -- Citizen.Wait(12e4) + -- while activated do + -- TriggerServerEvent("AB3:ClientBeep") + -- Citizen.Wait(12e4) + -- end + -- end) + + -- HUD + Citizen.CreateThread(function() + while activated do + Citizen.Wait(0) + if (GetFollowPedCamViewMode() == 4 or Config.ThirdPersonMode) and not hudForceHide then + if not hudPresence then + SetHudPresence(true, name) + end + elseif hudPresence then + SetHudPresence(false, name) + end + end + SetHudPresence(false, name) + end) +end + +function DeactivateAB3() + if not activated then + return error("AB3 attempted to deactivate when already deactivated.") + end + + activated = false +end + +function SetHudPresence(state, charname) + SendNUIMessage({AxonUIPresence = state, name = charname}) + hudPresence = state +end + +function ShowNotification(message) + BeginTextCommandThefeedPost("STRING") + AddTextComponentSubstringPlayerName(message) + EndTextCommandThefeedPostTicker(true, false) +end diff --git a/resources/axonbody3-main/config.lua b/resources/axonbody3-main/config.lua new file mode 100644 index 000000000..809d24ae7 --- /dev/null +++ b/resources/axonbody3-main/config.lua @@ -0,0 +1,6 @@ +Config = { + framework_name = "core_framework", + CommandBinding = 'SLASH', + --- whether the axon overlay is also visible in third person + --- @type boolean + ThirdPersonMode = true, diff --git a/resources/axonbody3-main/fxmanifest.lua b/resources/axonbody3-main/fxmanifest.lua new file mode 100644 index 000000000..f77dd5125 --- /dev/null +++ b/resources/axonbody3-main/fxmanifest.lua @@ -0,0 +1,25 @@ +fx_version 'cerulean' +game 'gta5' + +repository 'https://github.com/TFNRP/axonbody3' +version '0.0.1' +author 'Reece Stokes Edit: NAT2K15' + + +ui_page 'html/index.html' +file { + 'html/sound/beep.wav', + 'html/index.html', + 'html/img/logo.png', + 'html/css/style.css', + 'html/fonts/KlartextMonoBold.ttf', +} + +client_script { + 'config.lua', + 'client/client.lua', +} +server_scripts { + 'server/server.lua' +} + diff --git a/resources/axonbody3-main/html/css/style.css b/resources/axonbody3-main/html/css/style.css new file mode 100644 index 000000000..cbdefd4e1 --- /dev/null +++ b/resources/axonbody3-main/html/css/style.css @@ -0,0 +1,73 @@ +@font-face { + font-family: "Klartext Mono Bold"; + src: url("fonts/KlartextMonoBold.ttf") format("truetype"); +} + +p { + display: inline; + text-align: left; + font-family: "Klartext Mono Bold", monospace; + font-weight: 600; + font-style: normal; + text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black; + color: rgb(255, 255, 255); + font-size: 1.2vw; + margin: 1%; +} + +body { + user-select: none; + overflow: hidden; +} + +p, +button, +div, +svg, +img, +input, +select { + position: absolute; +} + +#ui { + display: none; +} + +#date { + top: 3vw; + left: 79.5vw; + width: 17vw; +} + +#text { + top: 4.2vw; + left: 79.5vw; + width: 17vw; +} + +#logo { + top: 2.6vw; + left: 95vw; + width: 3.5vw; + height: 3.5vw; +} + +svg { + display: none; + top: 2.5vw; + left: 81vw; + width: 18vw; + height: 3.8vw; + z-index: -1; +} + +rect { + fill: rgb(40, 40, 40); + width: 100%; + height: 100%; +} + +img { + opacity: .75; +} \ No newline at end of file diff --git a/resources/axonbody3-main/html/fonts/KlartextMonoBold.ttf b/resources/axonbody3-main/html/fonts/KlartextMonoBold.ttf new file mode 100644 index 000000000..b66526a5e Binary files /dev/null and b/resources/axonbody3-main/html/fonts/KlartextMonoBold.ttf differ diff --git a/resources/axonbody3-main/html/img/logo.png b/resources/axonbody3-main/html/img/logo.png new file mode 100644 index 000000000..bbb360db4 Binary files /dev/null and b/resources/axonbody3-main/html/img/logo.png differ diff --git a/resources/axonbody3-main/html/index.html b/resources/axonbody3-main/html/index.html new file mode 100644 index 000000000..bf8b44401 --- /dev/null +++ b/resources/axonbody3-main/html/index.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + +
+

1337-42-00 00:00:00

+

AXON BODY 3 X60390000

+ + + + + +
+ + + \ No newline at end of file diff --git a/resources/axonbody3-main/html/sound/beep.wav b/resources/axonbody3-main/html/sound/beep.wav new file mode 100644 index 000000000..a7a97f526 Binary files /dev/null and b/resources/axonbody3-main/html/sound/beep.wav differ diff --git a/resources/axonbody3-main/server/server.lua b/resources/axonbody3-main/server/server.lua new file mode 100644 index 000000000..48793d28e --- /dev/null +++ b/resources/axonbody3-main/server/server.lua @@ -0,0 +1,3 @@ +RegisterNetEvent('AB3:ClientBeep', function() + TriggerClientEvent('AB3:ServerBeep', -1, source) +end) \ No newline at end of file diff --git a/resources/ja_fireciv_eup/fxmanifest.lua b/resources/ja_fireciv_eup/fxmanifest.lua new file mode 100644 index 000000000..c5afb9ec6 --- /dev/null +++ b/resources/ja_fireciv_eup/fxmanifest.lua @@ -0,0 +1,12 @@ +-- Generated with AltTool + +fx_version 'bodacious' +game { 'gta5' } + +files { + 'mp_m_freemode_01_mp_m_fireciv.meta', + 'mp_f_freemode_01_mp_f_fireciv.meta' +} + +data_file 'SHOP_PED_APPAREL_META_FILE' 'mp_m_freemode_01_mp_m_fireciv.meta' +data_file 'SHOP_PED_APPAREL_META_FILE' 'mp_f_freemode_01_mp_f_fireciv.meta' \ No newline at end of file diff --git a/resources/ja_fireciv_eup/mp_f_freemode_01_mp_f_fireciv.meta b/resources/ja_fireciv_eup/mp_f_freemode_01_mp_f_fireciv.meta new file mode 100644 index 000000000..ca98ab9e2 --- /dev/null +++ b/resources/ja_fireciv_eup/mp_f_freemode_01_mp_f_fireciv.meta @@ -0,0 +1,14 @@ + + + mp_f_freemode_01 + mp_f_fireciv + mp_f_freemode_01_mp_f_fireciv + SCR_CHAR_MULTIPLAYER_F + MP_CreatureMetadata_fireciv + + + + + + + \ No newline at end of file diff --git a/resources/ja_fireciv_eup/mp_m_freemode_01_mp_m_fireciv.meta b/resources/ja_fireciv_eup/mp_m_freemode_01_mp_m_fireciv.meta new file mode 100644 index 000000000..ebe1cb18b --- /dev/null +++ b/resources/ja_fireciv_eup/mp_m_freemode_01_mp_m_fireciv.meta @@ -0,0 +1,14 @@ + + + mp_m_freemode_01 + mp_m_fireciv + mp_m_freemode_01_mp_m_fireciv + SCR_CHAR_MULTIPLAYER + MP_CreatureMetadata_fireciv + + + + + + + \ No newline at end of file diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv.ymt b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv.ymt new file mode 100644 index 000000000..f5bdcb636 Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv.ymt differ diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_000_u.ydd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_000_u.ydd new file mode 100644 index 000000000..4b4b110a1 Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_000_u.ydd differ diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_001_u.ydd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_001_u.ydd new file mode 100644 index 000000000..39c45b1c6 Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_001_u.ydd differ diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_a_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_a_uni.ytd new file mode 100644 index 000000000..0af9b6721 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_a_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae8abd567c694066b0a5e712799a3509a01b0cca743130a73ccbb00a72e1b651 +size 189166 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_b_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_b_uni.ytd new file mode 100644 index 000000000..fb3a97292 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_b_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45515278dfa1c0262dada5c2cf53c869009ba28bd6dad761d3e0bf269d2d4dd8 +size 201735 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_c_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_c_uni.ytd new file mode 100644 index 000000000..70be54e80 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_c_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df27dd6559ac759d5b5d1a0f8358f1d138beaf4498f2f668916925978ec60021 +size 176708 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_d_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_d_uni.ytd new file mode 100644 index 000000000..154041756 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_d_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f450b42aa12cef2fff29b018db388a854cba428c090b3c54724b533adb90c99 +size 187354 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_e_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_e_uni.ytd new file mode 100644 index 000000000..28489c3f6 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_e_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:053bc4330740fc7a887f133bc41cc440f25af140d487c9b5a4dc4be6e80fea7c +size 107228 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_f_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_f_uni.ytd new file mode 100644 index 000000000..8fccd4220 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_f_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:463c9bf5ef9968f23e9927e083ec918f0a631daca2c91f68aab0d522b29d6c66 +size 125557 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_g_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_g_uni.ytd new file mode 100644 index 000000000..ada4bcf50 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_g_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e55b7f001522a4e70c5ffc31a4a1e6989bc7392c863a3ab19f0a0e82f1ce77c +size 56170 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_h_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_h_uni.ytd new file mode 100644 index 000000000..fb9a38d22 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_h_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01c5a18e7383c3165b5e8960a39cdb25a2ec554d020b0e1b6060e9216e76aa3f +size 151503 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_i_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_i_uni.ytd new file mode 100644 index 000000000..81e4b2971 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_i_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80ce8b39133535ef6fdac0d01eb121bc31b62d81bdb1de24cfdc34a8c7070437 +size 153518 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_j_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_j_uni.ytd new file mode 100644 index 000000000..5adfdbac0 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_j_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5dbabfb4f96df63f4f929b8fa7a972830b15ae6211691258a3fd799e1fe8e22 +size 118133 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_k_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_k_uni.ytd new file mode 100644 index 000000000..729f5be70 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_k_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd4e96bc90fbed09cc3da5ce23fec85e4209e943e9710f23ca16c00d346ae837 +size 133372 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_l_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_l_uni.ytd new file mode 100644 index 000000000..ff3549538 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_l_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b6a92b4cf9c96dd07e7a2db4b859419ce45e3c40c1ee56a239c7a0e711331955 +size 178702 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_m_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_m_uni.ytd new file mode 100644 index 000000000..1207f38aa --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_m_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3fd7ae42ecc00129d0181be5eb955fa99a4a073746bc22488bc7b909221c6286 +size 62321 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_n_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_n_uni.ytd new file mode 100644 index 000000000..19dc82a82 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_000_n_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da6fc72eb193eb80d54b8eb5374ec3337adae6cc69fdedd63b6b09f230f43090 +size 63273 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_a_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_a_uni.ytd new file mode 100644 index 000000000..57dc2fd0f --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_a_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:625bf5bc72ced0536be5d5f84a30b54cf86193c7235d2cd5bd3689d79428a6c6 +size 300824 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_b_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_b_uni.ytd new file mode 100644 index 000000000..aa2ec33aa --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_b_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d833a4def04d631e8e52d7d62c0a5353eba98cd0c86ba746719a8d34b99d9fe +size 323246 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_c_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_c_uni.ytd new file mode 100644 index 000000000..e4d67e3ab --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_c_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6a9e803ba80827f6734a0320af7bdfa36cd2f1694f371e0a6eae0044246f16e +size 294598 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_d_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_d_uni.ytd new file mode 100644 index 000000000..0297e786b --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_d_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a30d4bf27bf11115bced1c45994b4de55e1d1ef853974a4125a10f8ecaca7989 +size 76640 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_e_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_e_uni.ytd new file mode 100644 index 000000000..7396f02f7 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_e_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c962b7bd4490061ddd17e2ecadbbafc5b99e0584957e248f309e7ed88a0367a1 +size 184897 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_f_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_f_uni.ytd new file mode 100644 index 000000000..9d55c9c96 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_f_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50625c6a655665d15004b92260e77eaeb2e112b04680610ac52794a64711d68b +size 177288 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_g_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_g_uni.ytd new file mode 100644 index 000000000..74880073d --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_g_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c70cd9288fac5525cb0d2ba84de01eb684ea73a503137832ee552d1946929c3a +size 282210 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_h_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_h_uni.ytd new file mode 100644 index 000000000..652754970 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_h_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:204a50b1d3e9a361830d112c4acbf081f8d0934c4cc49fc79c7506d358a0aa0d +size 258933 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_i_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_i_uni.ytd new file mode 100644 index 000000000..a20bb7aa2 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_i_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84490efd0fef3384596d1694fbef397236d736e684691ed2ed1f3ac38ffe861b +size 195908 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_j_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_j_uni.ytd new file mode 100644 index 000000000..8d7de82ef --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_j_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85b73866c714accea5ebe4abdf8b6eec42ce1893333f72cbf8e0fad9eca90c3e +size 331392 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_k_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_k_uni.ytd new file mode 100644 index 000000000..77d6b0c9d --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_k_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0098d3a0a37a0f5b8b99ac4886b14e4ff6b8b864d2acf223235ede9fa018383c +size 164267 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_l_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_l_uni.ytd new file mode 100644 index 000000000..e97e9ab4c --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_l_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3175632050cd0a4e3fc09eb294c01502bed61a222df972913bceaa57cce11b4b +size 128731 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_m_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_m_uni.ytd new file mode 100644 index 000000000..b2289b361 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_m_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9412e9e72a2dc089e1d5522578c098477356533149b3954a59f6eeaf707c228 +size 90966 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_n_uni.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_n_uni.ytd new file mode 100644 index 000000000..c772d549c --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_mp_f_fireciv/mp_f_freemode_01_mp_f_fireciv^jbib_diff_001_n_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5225bd717b33bd5a215458d4efdadca0aff884a3eff94f5756d9f533da3b91ee +size 301572 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_000.ydd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_000.ydd new file mode 100644 index 000000000..24f68dc66 Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_000.ydd differ diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_a.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_a.ytd new file mode 100644 index 000000000..f9e06f581 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_a.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b8fbca65faffe3d00a88ca3cd96f32e492c34a58d14480d968bc52546ee77fd +size 500966 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_b.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_b.ytd new file mode 100644 index 000000000..0b01ae2d5 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_b.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4fe9fbc12b7bcbbcaf2860194f19424a6a52703b3756d2a63d901f34de05f9f +size 643559 diff --git a/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_c.ytd b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_c.ytd new file mode 100644 index 000000000..63f659d34 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_f_freemode_01_p_mp_f_fireciv/mp_f_freemode_01_p_mp_f_fireciv^p_head_diff_000_c.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc12f47a4935100e327acb9fdc949766adc1e06bbfc8c149730e8913a22ba552 +size 710999 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv.ymt b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv.ymt new file mode 100644 index 000000000..efd9f9943 Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv.ymt differ diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_000_u.ydd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_000_u.ydd new file mode 100644 index 000000000..091d7bb5c Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_000_u.ydd differ diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_001_u.ydd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_001_u.ydd new file mode 100644 index 000000000..4edcf2bba Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_001_u.ydd differ diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_a_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_a_uni.ytd new file mode 100644 index 000000000..8d907c579 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_a_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbf1d80973344c1a26bf152ac4e488696a855086241852eb1a8cd31aafbb7192 +size 251628 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_b_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_b_uni.ytd new file mode 100644 index 000000000..cad5723ec --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_b_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d35e524148284f31b4e1239635173ab8ea1b2302dedc77d9d42e024d2ff9be85 +size 106598 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_c_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_c_uni.ytd new file mode 100644 index 000000000..b4657ec36 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_c_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a0639d20b446d9ea8c9170cdfccff05f26ce2ad01a0aa68b31cae5f8a5e64ff +size 216674 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_d_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_d_uni.ytd new file mode 100644 index 000000000..f32f1a4c9 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_d_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97ded299594cef9f83d952e5dd75fc10df85125268b22bd6e6579d2541eae60b +size 131684 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_e_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_e_uni.ytd new file mode 100644 index 000000000..d8ec415ac --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_e_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:177c6781b2652d51f28d7928c3b90552fd6b42086f2b692c1073522274f76b57 +size 160843 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_f_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_f_uni.ytd new file mode 100644 index 000000000..b47c56ea7 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_f_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef3b29a7608a10019f8928e8e75f5d8a663dd48327bb2268f16834eead30416b +size 237187 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_g_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_g_uni.ytd new file mode 100644 index 000000000..1f7e91684 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_g_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:98c158b160d7054f33d4b243c2caf4959be84f7148a9ca7af4928cfe9cd31456 +size 259746 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_h_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_h_uni.ytd new file mode 100644 index 000000000..0e2a57348 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_h_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4df8c68d90c780268b2af9a8a258c4b2695443cf0100a4a56cb3a365ec23316 +size 251085 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_i_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_i_uni.ytd new file mode 100644 index 000000000..1bc4226e5 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_i_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:940806434fbb281753fe2ea6542e54eb7cd96fdcd4babacd616233250c7a6efa +size 114129 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_j_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_j_uni.ytd new file mode 100644 index 000000000..f89ccc6e8 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_j_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8e101aea2e7a920450601e9752237aed6c1fb1125ae15f3b7586c251c6256b4 +size 151824 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_k_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_k_uni.ytd new file mode 100644 index 000000000..4ed673b48 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_k_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f295f3bf680211d98224542e9d8510f7dacd666c31d449b43ad0a7f6e718ec2 +size 238200 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_l_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_l_uni.ytd new file mode 100644 index 000000000..fcf186815 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_l_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7565b33bf99458ff9025a9cd0fdf95ba3e1e8218368e16e6832c699fea70d4e1 +size 198984 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_m_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_m_uni.ytd new file mode 100644 index 000000000..eeb92cd03 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_m_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24b8ad7ec5c1870c1a44dafc9be43bf682ca89e87f5d08cfe4a381c7a4f33378 +size 144893 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_n_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_n_uni.ytd new file mode 100644 index 000000000..4b19d4f70 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_000_n_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cde85942c2168fd01cf75ee6fe9daf5f2e204f4123cb0fa82ab279c58f97e610 +size 163156 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_a_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_a_uni.ytd new file mode 100644 index 000000000..d5df9a5ef --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_a_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f248e11be40958299caa765dffded1e8181e46a6d904f472fe3a51810bd8247c +size 683391 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_b_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_b_uni.ytd new file mode 100644 index 000000000..bc9f67954 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_b_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3f030b0e116f587ed083e5d2976a57d0409f266c11327f546134b06b1367483 +size 768782 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_c_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_c_uni.ytd new file mode 100644 index 000000000..c3971c2d2 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_c_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b303b963bbd5d28b28ea01c13e7a1179ebbbde228e84c8356fcc9fe82a1ea50 +size 540601 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_d_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_d_uni.ytd new file mode 100644 index 000000000..330eb9331 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_d_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c145552b8e7c6e33dee8f4bd985693a47593172e4c0757ca01f80293a6c433d8 +size 657745 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_e_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_e_uni.ytd new file mode 100644 index 000000000..7ec7513e6 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_e_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa3e81e00c6457a3c7bf047b5b6a8baeff7cda0a51dcfffae6e9bca3b85dac4f +size 204716 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_f_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_f_uni.ytd new file mode 100644 index 000000000..ad378d7db --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_f_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a8b993b51edc97b88abae2058b32f71bfc987f014101b004f9a076b88bc955b +size 692788 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_g_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_g_uni.ytd new file mode 100644 index 000000000..84431cddc --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_g_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b5541c620afb7eb5e74cb9f6b60906a45092fa4b0c1e6e06b4794efa0c904e9 +size 176981 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_h_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_h_uni.ytd new file mode 100644 index 000000000..d2dc0f883 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_h_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:541645fd262886e9798db98959c1b34759b006f0df0d80982afcf369204a6a84 +size 556438 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_i_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_i_uni.ytd new file mode 100644 index 000000000..dd4058262 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_i_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:027e802a6a383088152567a327aafa3c2ad62ed08ab197b17e11febf3ff2b4e7 +size 196831 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_j_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_j_uni.ytd new file mode 100644 index 000000000..7803c9ab4 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_j_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:481d4577a947419119619efe52a268890cc7990903080d0ba737c956f9a3acf3 +size 330333 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_k_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_k_uni.ytd new file mode 100644 index 000000000..cecf8f809 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_k_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14f1fe82f00a40ccee8eb150f319c99af4fd66a1daba498d5a5a545232022786 +size 421757 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_l_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_l_uni.ytd new file mode 100644 index 000000000..5922e7de1 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_l_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12c200d850dc2edf09009aab8f12ca4c3ca26cfa1682ed4db4c03c7dc0454ac0 +size 366483 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_m_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_m_uni.ytd new file mode 100644 index 000000000..a7b6527f6 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_m_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67e67d38ca91edbf4be013087e7ceae4c515129cd041c255fb2933dfcaa10306 +size 536441 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_n_uni.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_n_uni.ytd new file mode 100644 index 000000000..254dd9c7c --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_mp_m_fireciv/mp_m_freemode_01_mp_m_fireciv^jbib_diff_001_n_uni.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0c241984147db7302adc4b45719765bdb1874f647a58ac901b3f091901fd9c6 +size 390864 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_000.ydd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_000.ydd new file mode 100644 index 000000000..dac783638 Binary files /dev/null and b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_000.ydd differ diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_a.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_a.ytd new file mode 100644 index 000000000..49e3cc4ed --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_a.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48b7791e03a00732c252ca9e2c0182d5d32b8a7848ec01fc4f030f11c0a0abfb +size 25892 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_b.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_b.ytd new file mode 100644 index 000000000..30e0208d8 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_b.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a1f7841c0eaceb01c1e0cd96b9d64c7e17aa3d947790a9e02352feca3f1612f +size 32583 diff --git a/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_c.ytd b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_c.ytd new file mode 100644 index 000000000..6bbd61064 --- /dev/null +++ b/resources/ja_fireciv_eup/stream/mp_m_freemode_01_p_mp_m_fireciv/mp_m_freemode_01_p_mp_m_fireciv^p_head_diff_000_c.ytd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dde600a08275e92d655d741ae82079043c9c044d9f65585ee92b033aca09a21c +size 21971 diff --git a/resources/mrw_minigolf/Leaked by NulledLeaks.net.url b/resources/mrw_minigolf/Leaked by NulledLeaks.net.url new file mode 100644 index 000000000..bb1b5035d --- /dev/null +++ b/resources/mrw_minigolf/Leaked by NulledLeaks.net.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://nulledleaks.net/index.php diff --git a/resources/mrw_minigolf/client/Leaked by NulledLeaks.net.url b/resources/mrw_minigolf/client/Leaked by NulledLeaks.net.url new file mode 100644 index 000000000..bb1b5035d --- /dev/null +++ b/resources/mrw_minigolf/client/Leaked by NulledLeaks.net.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://nulledleaks.net/index.php diff --git a/resources/mrw_minigolf/client/game.lua b/resources/mrw_minigolf/client/game.lua new file mode 100644 index 000000000..8d3cec5f7 --- /dev/null +++ b/resources/mrw_minigolf/client/game.lua @@ -0,0 +1,306 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +Game = {} +Game.data = {} +Game.__index = Game + +local firstInit, total_stroke, inGame = true, 0, false +allGame = {} +c, s = nil, nil + +setmetatable(Game, { + __call = function(cls, index) + self = Game.new(index) + return self + end +}) + +function Game.new(hole) + local self = setmetatable({}, Game) + + self.hole = hole + self.stroke = 0 + self.ped = assert(PlayerPedId) + + self.ball = Object('prop_golf_ball', Config.golf_track[self.hole].start) + self.club = Object('prop_golf_putter_01', Utils:getEntityCoords(self.ped())) + + ApplyBallParams(self.ball.object) + AttachEntityToEntity(self.club.object, self.ped(), GetPedBoneIndex(self.ped(), 28422), 0, 0, 0, 0.0, 0.0, 0.0, false, false, false, true, 0, true) + + return self +end + +function Game:addStroke() + local hasMaxStroke = false + + if self.stroke + 1 >= Config.max_stroke + 1 then + self.stroke, hasMaxStroke = Config.max_stroke, true + else + self.stroke = self.stroke + 1 + end + + for key, value in pairs(allGame) do + if rawequal(value.hole, self.hole) then + value.stroke = self.stroke + break + end + end + + if hasMaxStroke then + DrawLineActive, self.ball, self.club = false, self.ball:delete(), self.club:delete() + + Ui:displayNotification(translation["max_stroke"]) + + Utils:freezeEntity(c.ped(), false) + ClearPedTasksImmediately(c.ped()) + + if self.hole + 1 < #Config.golf_track then + self.hole = self.hole + 1 + TriggerEvent("mrw_minigolf:st_game", self.hole) + else + total_stroke = total_stroke + self.stroke + + CreateThread(DisplayScaleform) + s:addContent(translation["congrats"], ("%s %s %s"):format(translation["finish_game"], total_stroke, translation["stroke"])) + + SetTimeout(2500, function() + TriggerEvent("mrw_minigolf:cut_game") + end) + end + + self, inGame = nil, false + end + + return hasMaxStroke +end + +function Game:shoot() + + Utils:setEntityHeading(self.ball.object, 0.0) + + local coords = Utils:getEntityCoords(self.ped()) + local power = getPower() + local cam = camPosition() + local offset = GetOffsetFromEntityGivenWorldCoords(self.ball.object, cam.x, cam.y, cam.z) + + Utils:playAnimation("mini@golfai", "iron_swing_action", {coords.x - 0.6, coords.y + 0.2, coords.z}, 5000, 0) + + SetTimeout(500, function() + Utils:playSoundFromEntity("GOLF_SWING_FAIRWAY_IRON_LIGHT_MASTER") + + FreezeEntityPosition(self.ball.object, false) + SetEntityVelocity(self.ball.object, offset.x * power, offset.y * power, -0.1) + ApplyForceToEntity(self.ball.object, 0, offset.x, offset.y, 0.0, 0.0, 0.0, 0.0, 0, false, false, false, false, true) + + Utils:createCamera() + + while true do Wait(100) + if power > 0.00 then + power = power - 0.01 + else + local speed = GetEntitySpeed(self.ball.object) + + if speed < 1.0 then + SetEntityVelocity(self.ball.object, 0.0, 0.0, 0.0) + FreezeEntityPosition(self.ball.object, true) + + local material = Utils:groundMaterial() + local objectAtCoords = DoesObjectOfTypeExistAtCoords(Config.golf_track[self.hole].hole, 0.1, `prop_golf_ball`, false) + + Utils:deleteCamera() + + if objectAtCoords then + self:finishGame() + return + elseif not material then + self:out() + return + else + self:reroll() + return + end + end + end + end + end) +end + +function Game:finishGame() + CreateThread(DisplayScaleform) + + total_stroke, DrawLineActive, self.ball, self.club = total_stroke + self.stroke, false, self.ball:delete(), self.club:delete() + + --print('Total stroke :', total_stroke) + + if self.hole == #Config.golf_track then + s:addContent(translation["congrats"], ("%s %s %s"):format(translation["finish_game"], total_stroke, translation["stroke"])) + + SetTimeout(2500, function() + TriggerEvent("mrw_minigolf:cut_game") + self = nil + end) + else + self.hole = self.hole + 1 + + s:addContent(translation["congrats"], ("%s %s %s"):format(translation["round_win"], self.stroke, translation["stroke"])) + + SetTimeout(2500, function() + Utils:freezeEntity(self.ped(), false) + TriggerEvent("mrw_minigolf:st_game", self.hole) + self = nil + end) + end +end + +function Game:out() + Ui:displayNotification(translation['off_side']) + DrawLineActive = false + + self:returnToStart() +end + +function Game:reroll() + local hole = Config.golf_track[self.hole].hole + local coords = self.ball:getPosition() + local nx, ny = coords.x - hole.x, coords.y - hole.y + local angle = Utils:deg(nx, ny) + + Ui:fadeOut(500) + + SetTimeout(1000, function() + setCurrentPosition(coords) + Utils:placePed(angle) + Utils:playAnimation("mini@golfai", "wedge_idle_a", {}, -1, 1) + Utils:freezeEntity(c.ped(), true) + Ui:fadeIn() + + CreateThread(DisplayDrawLine) + CreateThread(ProcessThread) + end) +end + +function Game:returnToStart() + local data = Config.golf_track[self.hole] + + Ui:fadeOut(500) + + Wait(500) + + Utils:freezeEntity(self.ped(), false) + Utils:freezeEntity(self.ball.object, false) + + setCurrentPosition(data.start) + + self.ball:setPosition(data.start) + self.ball:setHeading(0.0) + PlaceObjectOnGroundProperly(self.ball.object) + + Utils:placePed(data.heading) + + SetTimeout(2000, function() + + Utils:playAnimation("mini@golfai", "wedge_idle_a", {}, -1, 1) + Utils:freezeEntity(self.ped(), true) + Utils:freezeEntity(self.ball.object, true) + + Ui:fadeIn() + + CreateThread(DisplayDrawLine) + CreateThread(ProcessThread) + end) +end + +function Game:quit() + Ui:displayNotification(translation['quit']) + Utils:freezeEntity(c.ped(), false) + ClearPedTasksImmediately(c.ped()) + TriggerEvent("mrw_minigolf:cut_game") + self = nil +end + +RegisterNetEvent("mrw_minigolf:st_game") +AddEventHandler("mrw_minigolf:st_game", function(index) + local data = Config.golf_track[index] + + if firstInit then + RequestScriptAudioBank("GOLF_I", 0) + s = Scaleform() + + for i = 1, #Config.golf_track, 1 do + table.insert(allGame, {hole = i, stroke = 0}) + end + + firstInit = false + end + + setCurrentPosition(data.start) + + Ui:fadeOut(500) + + c = Game(index) + + Wait(500) + + Utils:placePed(data.heading) + + SetTimeout(2000, function() + Utils:playAnimation("mini@golfai", "wedge_idle_a", {}, -1, 1) + Utils:freezeEntity(c.ped(), true) + Ui:fadeIn() + + CreateThread(DisplayDrawLine) + CreateThread(ProcessThread) + end) + + inGame = true +end) + +RegisterNetEvent("mrw_minigolf:cut_game") +AddEventHandler("mrw_minigolf:cut_game", function() + ScaleformActive, DrawLineActive = false, false + + Wait(1) + + s:destruct() + + if c.ball and c.club then + c.ball, c.club = c.ball:delete(), c.club:delete() + end + + total_stroke, inGame, firstInit, allGame, c, s = 0, false, true, {}, nil, nil +end) + +AddEventHandler("onResourceStop", function(name) + if GetCurrentResourceName() == name then + if c then + c.ball = c.ball:delete() + c.club = c.club:delete() + c = nil + end + + if s then + s:destruct() + s = nil + end + + if inGame then + local ped = PlayerPedId() + + DetachEntity(ped, true, true) + FreezeEntityPosition(ped, false) + ClearPedTasksImmediately(ped) + + if IsScreenFadedOut() then + DoScreenFadeIn(100) + end + end + end +end) + +--[[ +RegisterCommand('st-golf', function(s,a) + TriggerEvent('mrw_minigolf:st_game', 1) +end) +]] \ No newline at end of file diff --git a/resources/mrw_minigolf/client/object.lua b/resources/mrw_minigolf/client/object.lua new file mode 100644 index 000000000..843e2af61 --- /dev/null +++ b/resources/mrw_minigolf/client/object.lua @@ -0,0 +1,57 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +Object = {} +Object.__index = Object + +setmetatable(Object, { + __call = function(cls, m, p) + self = Object.new(m, p) + return self + end +}) + +function ApplyBallParams(entity) + SetEntityLoadCollisionFlag(entity, true) + SetEntityCollision(entity, true, true) + SetEntityRecordsCollisions(entity, true) + SetEntityHasGravity(entity, true) + FreezeEntityPosition(entity, true) + SetEntityHeading(entity, 0.0) + SetEntityMaxSpeed(entity, 10.0) + PlaceObjectOnGroundProperly(entity) +end + +function Object.new(model, position) + local self = setmetatable({}, Object) + local model = model + local hash = GetHashKey(model) + + RequestModel(model) + + while not HasModelLoaded(model) do + Wait(1) + end + + self.object = CreateObject(hash, position, true, false, false) + + return self +end + +function Object:getPosition() + return GetEntityCoords(self.object) +end + +function Object:setPosition(position) + SetEntityCoords(self.object, position, false, false, false, false) +end + +function Object:setHeading(h) + SetEntityHeading(self.object, h) +end + +function Object:delete() + DeleteObject(self.object) + self = nil + return self +end \ No newline at end of file diff --git a/resources/mrw_minigolf/client/scaleform.lua b/resources/mrw_minigolf/client/scaleform.lua new file mode 100644 index 000000000..944ff4542 --- /dev/null +++ b/resources/mrw_minigolf/client/scaleform.lua @@ -0,0 +1,48 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +Scaleform = {} +Scaleform.__index = Scaleform + +setmetatable(Scaleform, { + __call = function(cls) + self = Scaleform.new() + return self + end +}) + +function Scaleform.new() + local self = setmetatable({}, Scaleform) + + if HasScaleformMovieLoaded("MP_BIG_MESSAGE_FREEMODE") then + return + end + + self.scaleform = RequestScaleformMovie("MP_BIG_MESSAGE_FREEMODE") + + while not HasScaleformMovieLoaded(self.scaleform) do + Wait(1) + end + + return self +end + +function Scaleform:display() + DrawScaleformMovieFullscreen(self.scaleform, 255, 255, 255, 255, 0) +end + +function Scaleform:destruct() + SetScaleformMovieAsNoLongerNeeded(self.scaleform) + self = nil +end + +function Scaleform:addContent(t, str) + BeginScaleformMovieMethod(self.scaleform, 'SHOW_SHARD_WASTED_MP_MESSAGE') + PushScaleformMovieMethodParameterString(t) + PushScaleformMovieMethodParameterString(str) + EndScaleformMovieMethod() + + SetTimeout(2500, function() + ScaleformActive = false + end) +end \ No newline at end of file diff --git a/resources/mrw_minigolf/client/thread.lua b/resources/mrw_minigolf/client/thread.lua new file mode 100644 index 000000000..bbcd2ac66 --- /dev/null +++ b/resources/mrw_minigolf/client/thread.lua @@ -0,0 +1,140 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +local currentPosition, ScoreboardIsOpen, power, gameCamPosition = nil, false, 0.0, nil +DrawLineActive, ScaleformActive = false, false + +function setCurrentPosition(p) + currentPosition = p +end + +function getPower() + return power +end + +function camPosition() + return gameCamPosition +end + +function ZoneThread() + while true do + local d = 500 + local pcoords = Utils:getEntityCoords(PlayerPedId()) + local distance = #(pcoords - Config.locate_club) + + if distance <= 1.5 then + d = 1 + + Ui:displayHelpNotification({ + translation['locate_club'] + }) + + if IsControlJustPressed(0, 38) then + TriggerServerEvent("mrw_minigolf:locateClub") + end + end + + Wait(d) + end +end + +function ProcessThread() + power, gameCamPosition = 0.0, nil + + local totalStroke = c:addStroke() + + if c.stroke > 0 then + Ui:displayNotification(('%s : %s'):format(translation["play_your"], c.stroke)) + end + + if totalStroke then return end + + while true do + local d = 500 + local pcoords = Utils:getEntityCoords(c.ped()) + local distance = #(pcoords - currentPosition) + + if distance <= 1.5 then + d = 1 + + Ui:displayHelpNotification({ + translation["other_params"], + translation["rotate_params"], + translation["games_params"] + }) + + if IsControlJustPressed(0, 121) and not ScoreboardIsOpen then + Ui:displayScoreboard(true) + ScoreboardIsOpen = not ScoreboardIsOpen + + elseif IsControlJustReleased(0, 121) and ScoreboardIsOpen then + Ui:displayScoreboard(false) + ScoreboardIsOpen = not ScoreboardIsOpen + + elseif IsControlPressed(0, 24) and power < 1.0 then + power = power + 0.01 + Ui:displayPowerBar(true, power) + + elseif IsControlPressed(0, 174) then + local baseHeading = Utils:getEntityHeading(c.ped()) + + if not IsEntityAttached(c.ped()) then + AttachEntityToEntity(c.ped(), c.ball.object, 20, 0.14, -0.62, 0.99, 0.0, 0.0, 0.0, false, false, false, false, 1, true) + end + + Utils:setEntityHeading(c.ball.object, baseHeading + 1.0) + DetachEntity(c.ped(), true, true) + + elseif IsControlPressed(0, 175) then + local baseHeading = Utils:getEntityHeading(c.ped()) + + if not IsEntityAttached(c.ped()) then + AttachEntityToEntity(c.ped(), c.ball.object, 20, 0.14, -0.62, 0.99, 0.0, 0.0, 0.0, false, false, false, false, 1, true) + end + + Utils:setEntityHeading(c.ball.object, baseHeading - 1.0) + DetachEntity(c.ped(), true, true) + + elseif IsControlJustPressed(0, 178) then + c:quit() + return + elseif IsControlJustPressed(0, 82) then + c:returnToStart() + return + elseif IsControlJustReleased(0, 24) then + Ui:displayPowerBar(false, 0) + gameCamPosition, DrawLineActive = Utils:rayCastGamePlayCamera(90.0), false + c:shoot() + return + end + end + + Wait(d) + end +end + +function DisplayDrawLine() + if not DrawLineActive then DrawLineActive = true end + + while DrawLineActive do Wait(1) + + if c.ball == nil then + return + end + + local bcoords = Utils:getEntityCoords(c.ball.object) + local direction = Utils:rayCastGamePlayCamera(50.0) + + Ui:drawLine(bcoords, direction) + end +end + +function DisplayScaleform() + if not ScaleformActive then ScaleformActive = true end + + while ScaleformActive do Wait(1) + s:display() + end +end + +CreateThread(ZoneThread) \ No newline at end of file diff --git a/resources/mrw_minigolf/client/ui.lua b/resources/mrw_minigolf/client/ui.lua new file mode 100644 index 000000000..83344268b --- /dev/null +++ b/resources/mrw_minigolf/client/ui.lua @@ -0,0 +1,75 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +-- Credit for research +-- https://github.com/Sainan/GTA-V-Decompiled-Scripts/blob/master/decompiled_scripts/golf_mp.c +-- https://www.vespura.com/fivem/scaleform/ + +Ui = {} +Ui.__index = Ui + +function Ui:displayNotification(str) + BeginTextCommandThefeedPost("STRING") + AddTextComponentString(str) + EndTextCommandThefeedPostTicker(false, true) +end + +function Ui:displayHelpNotification(request) + BeginTextCommandDisplayHelp("THREESTRINGS") + + for i = 1,#request,1 do + AddTextComponentSubstringPlayerName(request[i]) + end + + EndTextCommandDisplayHelp(0, false, true, request.duration or 5000) +end + +function Ui:fadeOut(time) + CreateThread(function() + if not IsScreenFadedOut() then + DoScreenFadeOut(time) + else + DoScreenFadeIn(100) + end + end) +end + +function Ui:fadeIn() + DoScreenFadeIn(150) +end + +function Ui:drawLine(coords, coords2) + DrawLine(coords.x, coords.y, coords.z, coords2.x, coords2.y, coords2.z, 255, 0, 0, 0.8) +end + +function Ui:displayScoreboard(display) + if display then + SendNuiMessage(json.encode({ + status = true, + data = allGame, + ui = 'Scoreboard' + })) + else + SendNuiMessage(json.encode({ + status = false, + ui = 'Scoreboard' + })) + end +end + +function Ui:displayPowerBar(display, power) + if display then + SendNuiMessage(json.encode({ + status = true, + ui = 'Power', + data = tonumber(power * 100) + })) + + else + SendNuiMessage(json.encode({ + status = false, + ui = 'Power', + data = 0 + })) + end +end diff --git a/resources/mrw_minigolf/client/utils.lua b/resources/mrw_minigolf/client/utils.lua new file mode 100644 index 000000000..cfefb1ff0 --- /dev/null +++ b/resources/mrw_minigolf/client/utils.lua @@ -0,0 +1,140 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +-- list of materials https://pastebin.com/PBE6wQSG + +Utils = {} +Utils.materials = {-840216541, -1693813558, -754997699, -1469616465, 1926285543, -1369136684} +Utils.__index = Utils + +local cam = nil + +function Utils:getEntityCoords(entity) + return GetEntityCoords(entity) +end + +function Utils:setEntityCoords(entity, new_coords) + SetEntityCoords(entity, new_coords, false, false, false, false) +end + +function Utils:getEntityHeading(entity) + return GetEntityHeading(entity) +end + +function Utils:setEntityHeading(entity, new_heading) + SetEntityHeading(entity, new_heading) +end + +function Utils:freezeEntity(entity, toggle) + FreezeEntityPosition(entity, toggle) +end + +function Utils:placePed(h) + SetEntityHeading(c.ball.object, h+360.0) + AttachEntityToEntity(c.ped(), c.ball.object, 20, 0.14, -0.62, 0.99, 0.0, 0.0, 0.0, false, false, false, false, 1, true) + DetachEntity(c.ped(), true, true) + SetEntityHeading(c.ball.object, 0.0) +end + +function Utils:createCamera() + cam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true) + RenderScriptCams(true, false, 0, true, true) + SetCamFov(cam, 90.0) + AttachCamToEntity(cam, c.ball.object, -0.2, 0.0, 1.0099, false) +end + +function Utils:deleteCamera() + if cam then + DestroyCam(cam, true) + RenderScriptCams(false, false, 0, true, true) + cam = nil + end +end + +function Utils:playAnimation(dict, anim, coords, duration, loop) + RequestAnimDict(dict) + + while not HasAnimDictLoaded(dict) do + Wait(1) + end + + if HasAnimDictLoaded(dict) then + local x, y, z = false, false, false + + if coords then + x = coords.x + y = coords.y + z = coords.z + end + + TaskPlayAnim(PlayerPedId(), dict, anim, 8.0, -8.0, duration or -1, loop or 0, 0, x, y, z) + end +end + +function Utils:playSoundFromEntity(sound) + PlaySoundFromEntity(-1, sound, PlayerPedId(), 0, 0, 0) +end + +function Utils:groundMaterial() + local ballCoords = self:getEntityCoords(c.ball.object) + local shape = StartShapeTestCapsule(ballCoords.x, ballCoords.y, ballCoords.z + 4, ballCoords.x, ballCoords.y, ballCoords.z - 0.03, 2, -1, c.ball.object, 7) + local result, hit, endCoords, surfaceNormal, materialHash, entityHit = GetShapeTestResultIncludingMaterial(shape) + + if materialHash == 0 then + materialHash = GetLastMaterialHitByEntity(c.ball.object) + end + + for i = 1, #self.materials, 1 do + local material = self.materials[i] + --print(material, materialHash) + if material == materialHash or materialHash == 0 then + return true + end + end + + return false +end + +function Utils:deg(x, y) + local heading = math.atan2(x, y) + + if heading < 0 then + heading = math.deg(math.abs(heading)) + else + heading = math.deg(2 * math.pi - heading) + end + + heading = heading + 90.0 + + return heading +end + +function Utils:rotationToDirection(rotation) + local adjustedRotation = + { + x = (math.pi / 180) * rotation.x, + y = (math.pi / 180) * rotation.y, + z = (math.pi / 180) * rotation.z + } + local direction = + { + x = -math.sin(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), + y = math.cos(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), + z = math.sin(adjustedRotation.x) + } + return direction +end + +function Utils:rayCastGamePlayCamera(distance) + local cameraRotation = GetGameplayCamRot() + local cameraCoord = GetGameplayCamCoord() + local direction = self:rotationToDirection(cameraRotation) + local destination = + { + x = cameraCoord.x + direction.x * distance, + y = cameraCoord.y + direction.y * distance, + z = cameraCoord.z + direction.z * distance + } + local a, b, c, d, e = GetShapeTestResult(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, -1, -1, 1)) + return c +end \ No newline at end of file diff --git a/resources/mrw_minigolf/fxmanifest.lua b/resources/mrw_minigolf/fxmanifest.lua new file mode 100644 index 000000000..c22f3dd9d --- /dev/null +++ b/resources/mrw_minigolf/fxmanifest.lua @@ -0,0 +1,27 @@ +fx_version 'cerulean' +game'gta5' +name 'mrw_minigolf' +description 'script for patoche golf mapping' +author 'Morow' + +client_scripts{ + 'client/*.lua' +} + +server_script{ + 'server/*.lua' +} + +shared_scripts{ + 'shared/*.lua', + 'shared/translation/*.lua' +} + +files{ + 'ui/ui.html', + 'ui/script/app.js', + 'ui/css/app.css', + 'ui/font/*.woff' +} + +ui_page 'ui/ui.html' \ No newline at end of file diff --git a/resources/mrw_minigolf/readme.md b/resources/mrw_minigolf/readme.md new file mode 100644 index 000000000..f536067aa --- /dev/null +++ b/resources/mrw_minigolf/readme.md @@ -0,0 +1,10 @@ +# MRW_MINIGOLF +## Script for Patoche minigolf mapping + +# [EN] +### the config file locate is /shared/shared.lua +### the translation file locate is /shared/translation/en.lua + +# [FR] +### Le fichier config se trouve ici /shared/shared.lua +### Le fichier de traduction se trouve ici /shared/translation/fr.lua \ No newline at end of file diff --git a/resources/mrw_minigolf/server/Leaked by NulledLeaks.net.url b/resources/mrw_minigolf/server/Leaked by NulledLeaks.net.url new file mode 100644 index 000000000..bb1b5035d --- /dev/null +++ b/resources/mrw_minigolf/server/Leaked by NulledLeaks.net.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://nulledleaks.net/index.php diff --git a/resources/mrw_minigolf/server/server.lua b/resources/mrw_minigolf/server/server.lua new file mode 100644 index 000000000..f4c48cd12 --- /dev/null +++ b/resources/mrw_minigolf/server/server.lua @@ -0,0 +1,27 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +if Config.USE_ESX then + ESX = nil + TriggerEvent('esx:getSharedObject', function( obj ) ESX = obj end) +end + +RegisterNetEvent("mrw_minigolf:locateClub") +AddEventHandler("mrw_minigolf:locateClub", function() + local x_source = source + + if Config.USE_ESX then + local xPlayer = ESX.GetPlayerFromId(x_source) + local getPlayerMoney = xPlayer.getMoney() + + if getPlayerMoney >= Config.club_price then + TriggerClientEvent("mrw_minigolf:st_game", x_source, 1) + else + TriggerClientEvent("mrw_golf:Notification", x_source, translation["no_money"]) + end + else + -- IF USE YOUR CUSTOM FRAMEWORK !! + -- ADD YOUR LINE FOR COMPARE PLAYER MONEY + TriggerClientEvent("mrw_minigolf:st_game", x_source, 1) + end +end) \ No newline at end of file diff --git a/resources/mrw_minigolf/shared/Leaked by NulledLeaks.net.url b/resources/mrw_minigolf/shared/Leaked by NulledLeaks.net.url new file mode 100644 index 000000000..bb1b5035d --- /dev/null +++ b/resources/mrw_minigolf/shared/Leaked by NulledLeaks.net.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://nulledleaks.net/index.php diff --git a/resources/mrw_minigolf/shared/shared.lua b/resources/mrw_minigolf/shared/shared.lua new file mode 100644 index 000000000..4c9343186 --- /dev/null +++ b/resources/mrw_minigolf/shared/shared.lua @@ -0,0 +1,81 @@ +-- Author : Morow +-- Github : https://github.com/Morow73 + +_G.language = "en" -- change translation, 'en' or 'fr' +_G.translation = {} + +if IsDuplicityVersion() then + Config = {} + Config.__index = Config + + Config.USE_ESX = true -- use ESX or not ? + Config.club_price = 200 -- minigolf price +else + Config = {} + Config.__index = Config + + Config.max_stroke = 10 -- max stroke + Config.locate_club = vector3(-1734.24, -1135.17, 12.79) -- locate club position + Config.golf_track = { + [1] = { + start = vector3(-1753.32, -1166.31, 12.79), -- fisrt position + hole = vector3(-1744.81, -1150.25, 11.96), -- hole position + heading = 240.0 -- heading for first position + }, + [2] = { + start = vector3(-1743.29, -1182.03, 12.79), + hole = vector3(-1738.33, -1164.27, 11.96), + heading = 244.0 + }, + [3] = { + start = vector3(-1730.49, -1179.09, 12.79), + hole = vector3(-1723.03, -1181.61, 11.96), + heading = 282.0 + }, + [4] = { + start = vector3(-1713.28, -1167.88, 12.79), + hole = vector3(-1716.87, -1172.23, 11.96), + heading = 290.0 + }, + [5] = { + start = vector3(-1760.85, -1190.26, 12.79), + hole = vector3(-1769.87, -1177.45, 11.96), + heading = 227.0 + }, + [6] = { + start = vector3(-1772.51, -1220.72, 12.79), + hole = vector3(-1769.00, -1224.46, 11.96), + heading = 263.0 + }, + [7] = { + start = vector3(-1746.66, -1192.76, 12.79), + hole = vector3(-1747.94, -1194.80, 11.96), + heading = 130.0 + }, + [8] = { + start = vector3(-1752.10, -1225.11, 12.79), + hole = vector3(-1748.39, -1217.06, 11.96), + heading = 245.0 + }, + [9] = { + start = vector3(-1741.43, -1238.41, 12.79), + hole = vector3(-1743.40, -1240.87, 11.78), + heading = 224.0 + }, + [10] = { + start = vector3(-1729.42, -1210.54, 12.79), + hole = vector3(-1730.75, -1206.63, 11.80), + heading = 281.0 + }, + [11] = { + start = vector3(-1719.01, -1209.35, 12.79), + hole = vector3(-1704.51, -1192.00, 11.78), + heading = 222.0 + }, + [12] = { + start = vector3(-1694.93, -1172.71, 12.79), + hole = vector3(-1690.35, -1184.38, 11.96), + heading = 250.0 + } + } +end diff --git a/resources/mrw_minigolf/shared/translation/en.lua b/resources/mrw_minigolf/shared/translation/en.lua new file mode 100644 index 000000000..015e32ac6 --- /dev/null +++ b/resources/mrw_minigolf/shared/translation/en.lua @@ -0,0 +1,17 @@ +if language == "en" then + translation = { + ["congrats"] = "Felicidades", + ["round_win"] = "Terminaste este hoyo con ", + ["finish_game"] = "Se acabo el juego, hiciste un total de : ", + ["stroke"] = "Tiro", + ["locate_club"] = "~INPUT_CONTEXT~ para rentar palos por $200 !", + ["other_params"] = "~INPUT_ATTACK~ para cargar el golpe !\n ~INPUT_VEH_FLY_ATTACK_CAMERA~ mostrar los puntos ! \n", + ["rotate_params"] = "~INPUT_CELLPHONE_LEFT~ ~INPUT_CELLPHONE_RIGHT~ rotar alrededor de la bola !\n", + ["games_params"] = "~INPUT_VEH_PREV_RADIO~ para reiniciar el nivel !\n ~INPUT_CELLPHONE_OPTION~ quitar el juego !", + ["no_money"] = "No tienes fondos !", + ["max_stroke"] = "Superaste el maximo de golpes en este round", + ["quit"] = "Saliste del juego", + ["off_side"] = "La bola salio del campo", + ["play_your"] = "Total de Tiros: " + } +end \ No newline at end of file diff --git a/resources/mrw_minigolf/shared/translation/fr.lua b/resources/mrw_minigolf/shared/translation/fr.lua new file mode 100644 index 000000000..8935e7b11 --- /dev/null +++ b/resources/mrw_minigolf/shared/translation/fr.lua @@ -0,0 +1,17 @@ +if language == "fr" then + translation = { + ["congrats"] = "Félicitation", + ["round_win"] = "Manche gagné en ", + ["finish_game"] = "La partie est terminé, vous avez fait un total de : ", + ["stroke"] = "coups", + ["locate_club"] = "~INPUT_CONTEXT~ pour accéder aux location de clubs !", + ["other_params"] = "~INPUT_ATTACK~ pour charger le tir !\n ~INPUT_VEH_FLY_ATTACK_CAMERA~ pour afficher les scores ! \n", + ["rotate_params"] = "~INPUT_CELLPHONE_LEFT~ ~INPUT_CELLPHONE_RIGHT~ pour tourner autour de la balle !\n", + ["games_params"] = "~INPUT_VEH_PREV_RADIO~ pour relancer le niveau !\n ~INPUT_CELLPHONE_OPTION~ pour quitter la partie !", + ["no_money"] = "Vous n'avez pas les fonds !", + ["max_stroke"] = "Vous avez atteind le nombre de coups maximum par tour", + ["quit"] = "Vous avez quitté la partie", + ["off_side"] = "La balle est sortit hors du terrain", + ["play_your"] = "Vous jouez votre coups n°" + } +end \ No newline at end of file diff --git a/resources/mrw_minigolf/ui/Leaked by NulledLeaks.net.url b/resources/mrw_minigolf/ui/Leaked by NulledLeaks.net.url new file mode 100644 index 000000000..bb1b5035d --- /dev/null +++ b/resources/mrw_minigolf/ui/Leaked by NulledLeaks.net.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://nulledleaks.net/index.php diff --git a/resources/mrw_minigolf/ui/css/app.css b/resources/mrw_minigolf/ui/css/app.css new file mode 100644 index 000000000..7c91bdafd --- /dev/null +++ b/resources/mrw_minigolf/ui/css/app.css @@ -0,0 +1,149 @@ + +@font-face { + font-family: 'Segoe UI Regular'; + font-style: normal; + font-weight: normal; + src: local('Segoe UI Regular'), url('Segoe UI.woff') format('woff'); +} + + +@font-face { + font-family: 'Segoe UI Italic'; + font-style: normal; + font-weight: normal; + src: local('Segoe UI Italic'), url('Segoe UI Italic.woff') format('woff'); +} + + +@font-face { + font-family: 'Segoe UI Bold'; + font-style: normal; + font-weight: normal; + src: local('Segoe UI Bold'), url('Segoe UI Bold.woff') format('woff'); +} + + +@font-face { + font-family: 'Segoe UI Bold Italic'; + font-style: normal; + font-weight: normal; + src: local('Segoe UI Bold Italic'), url('Segoe UI Bold Italic.woff') format('woff'); +} + +html, body{ + width: 60%; + height: 60%; + position: absolute; + left: 50%; + right: 50%; + transform: translate(-50%, 50%); +} + +#Scoreboard{ + display: none; + width: 100%; + height: 45%; + background-color: #14213d; + border-radius: 5px; + opacity: 0.9; + box-shadow: 10px 5px 5px black; + position: absolute; + bottom: 60%; +} + +.Scoreboard-header{ + color: #fca311; + font-size: 20px; + text-align: center; + width: 100%; + height: 20%; + font-family: 'Segoe UI Bold'; +} + +#Scoreboard-grid-hole{ + height: 30%; + width: 100%; + border-top: 1px solid white; + border-bottom: 1px solid white; + display: flex; + flex-direction: row; +} + +.Scoreboard-grid-hole-header{ + width: 50px; + height: 100%; + text-align: center; + border-right: 1px solid white; +} + +.Scoreboard-grid-hole-header-content{ + margin-top: 25%; + color: #fca311; + font-family: 'Segoe UI Bold'; +} + +.Scoreboard-grid-hole-hole{ + height: 100%; + width: 5%; + border-right: 1px solid white; + text-align: center; + color: white; + font-family: 'Segoe UI Regular'; +} + +.Scoreboard-grid-hole-hole p{ + margin-top: 40%; +} + +#Scoreboard-grid-score{ + height: 30%; + width: 100%; + border-bottom: 1px solid white; + display: flex; + flex-direction: row; +} + +.Scoreboard-grid-score-header{ + width: 50px; + height: 100%; + text-align: center; + border-right: 1px solid white; +} + +.Scoreboard-grid-score-header-content{ + margin-top: 25%; + color: #fca311; + font-family: 'Segoe UI Bold'; +} + +.Scoreboard-grid-score-score{ + height: 100%; + width: 5%; + border-right: 1px solid white; + text-align: center; + color: white; + font-family: 'Segoe UI Regular'; +} + +.Scoreboard-grid-score-score p{ + margin-top: 40%; +} + +#Bar{ + display: none; + width: 50%; + height: 5%; + border-radius: 5px; + background-color: white; + opacity: 0.9; + box-shadow: 10px 5px 5px black; + margin-top: 70%; + margin-left: 25%; +} + +#PowerBar{ + width: 10%; + height: 100%; + border-radius: 5px; + background-color: red; +} \ No newline at end of file diff --git a/resources/mrw_minigolf/ui/font/Segoe UI Bold Italic.woff b/resources/mrw_minigolf/ui/font/Segoe UI Bold Italic.woff new file mode 100644 index 000000000..fa45e22ab Binary files /dev/null and b/resources/mrw_minigolf/ui/font/Segoe UI Bold Italic.woff differ diff --git a/resources/mrw_minigolf/ui/font/Segoe UI Bold.woff b/resources/mrw_minigolf/ui/font/Segoe UI Bold.woff new file mode 100644 index 000000000..a6b0a974f Binary files /dev/null and b/resources/mrw_minigolf/ui/font/Segoe UI Bold.woff differ diff --git a/resources/mrw_minigolf/ui/font/Segoe UI Italic.woff b/resources/mrw_minigolf/ui/font/Segoe UI Italic.woff new file mode 100644 index 000000000..1649115ce Binary files /dev/null and b/resources/mrw_minigolf/ui/font/Segoe UI Italic.woff differ diff --git a/resources/mrw_minigolf/ui/font/Segoe UI.woff b/resources/mrw_minigolf/ui/font/Segoe UI.woff new file mode 100644 index 000000000..a45efa328 Binary files /dev/null and b/resources/mrw_minigolf/ui/font/Segoe UI.woff differ diff --git a/resources/mrw_minigolf/ui/script/app.js b/resources/mrw_minigolf/ui/script/app.js new file mode 100644 index 000000000..e4119a657 --- /dev/null +++ b/resources/mrw_minigolf/ui/script/app.js @@ -0,0 +1,51 @@ +const Scoreboard = document.getElementById("Scoreboard") +const ScoreboardGridHole = document.getElementById("Scoreboard-grid-hole") +const ScoreboardGridScore = document.getElementById("Scoreboard-grid-score") +const Bar = document.getElementById("Bar") +const BarContent = document.getElementById("PowerBar") + +let baseWidth = 0 + +window.addEventListener('message', function (event) { + const item = event.data; + const status = item.status; + const ui = item.ui + + if (ui === 'Scoreboard'){ + Scoreboard.style.display = (status ? "block" : "none"); + + if (item.data == undefined) return; + + const deleteIfDivExist = function(className){ + const divs = document.getElementsByClassName(className); + + if (divs == null) return; + + for (var i = divs.length-1; i >= 0; i--) { + divs[i].remove(); + } + } + + deleteIfDivExist("Scoreboard-grid-hole-hole") + deleteIfDivExist("Scoreboard-grid-score-score") + + for (let index = 0; index < item.data.length; index++) { + const element = item.data[index]; + + ScoreboardGridHole.innerHTML = ScoreboardGridHole.innerHTML + `
+

${element.hole}

+
`; + + ScoreboardGridScore.innerHTML = ScoreboardGridScore.innerHTML + `
+

${element.stroke}

+
`; + }; + }else{ + Bar.style.display = (status ? "block" : "none"); + + if (item.data == undefined) return; + if (item.data > 100) return; + + BarContent.setAttribute('style', `width:${item.data}%`) + } +}) diff --git a/resources/mrw_minigolf/ui/ui.html b/resources/mrw_minigolf/ui/ui.html new file mode 100644 index 000000000..9977a6542 --- /dev/null +++ b/resources/mrw_minigolf/ui/ui.html @@ -0,0 +1,34 @@ + + + + Scoreboard + + + +
+
Portside Minigolf
+ +
+ +
+
Hoyo
+
+ +
+ +
+ +
+
Puntuacion
+
+ +
+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/resources/nearestpostal/LICENSE b/resources/nearestpostal/LICENSE new file mode 100644 index 000000000..5c70ddb63 --- /dev/null +++ b/resources/nearestpostal/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2019 BlockBa5her + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/resources/nearestpostal/README.md b/resources/nearestpostal/README.md new file mode 100644 index 000000000..a434a466d --- /dev/null +++ b/resources/nearestpostal/README.md @@ -0,0 +1,76 @@ +# Nearest Postals + +This script displays a nearest postal next to where PLD would go and also has a command to draw a route to a specific postal + +## Installation + +1. There are 2 ways to install it, and I recommend the first + 1. Run the following command in a terminal + - `git clone https://github.com/blockba5her/nearest-postal.git` + 2. Download the code from the GitHub [releases](https://github.com/blockba5her/nearest-postal/releases) +2. As of now, this script supports 3 postal maps. From what I have seen, these are the most popular + - `new-postals.json` -> [New and Improved Postals](https://forum.fivem.net/t/release-postal-code-map-new-improved-v1-1/147458) + - `old-postals.json` -> [Original Postals](https://forum.fivem.net/t/release-modified-street-names-w-postal-numbers/8717) + - `ocrp-postals.json` -> [OCRP Postals](https://forum.fivem.net/t/release-ocrp-community-releases/166277) +3. To setup the postal map, open the `__resource.lua` file and change the variable `postalFile` to one of the files above + - **NOTE**: This defaults as the `new-postals.json` file + +## Command + +To draw a route to a certain postal, type `/postal [postalName]` and to remove just type `/postal` + +It will automatically remove the route when within 100m of the destination + +## Updates + +### 1.4 + +- Performance Improvements +- New config options added +- Fix some tiny bugs (and leftover code) + +### 1.3 + +- Improvements in selection of postal map +- Fix dev mode being on + +### 1.2.1 + +- Fixes to missing postals on improved postal map + +### 1.2 + +- Updates to README.md +- Version check +- Fixes for Improved Postal map +- Updates to dev API + +### 1.1.1 + +- Fixed issue with blip name being set to nil, clearing the screen of all other text + +### 1.1 + +- Added OCRP postals +- Added `config.lua` file + +## Development + +This script provides a simple way of working on a new postal map + +1. In the script, enabled the local variable `dev` near the bottom +2. Restart the script into game +3. Teleport to the first postal code in numerical order +4. Type `/setnext [postalCode]` where postalCode is the postal that you are at +5. Type `/next` to insert it +6. Teleport to the next postal code in numerical order +7. Type `/next` to insert it +8. Repeat from step 6 on + +If you make a mistake, you can either remove a specific postal using `/remove [postalCode]` or remove the last postal inserted with `/rl` (this will decrease the next value also) + +When done with that, you can print all of the postals you just inserted into console with the `/json` command and then copy it from your `CitizenFX.log` file + +## Discord + +Join my [discord](https://discord.gg/ZcTayce) for support and more scripts diff --git a/resources/nearestpostal/__resource.lua b/resources/nearestpostal/__resource.lua new file mode 100644 index 000000000..558563b26 --- /dev/null +++ b/resources/nearestpostal/__resource.lua @@ -0,0 +1,23 @@ +-- the postal map to read from +-- change it to whatever model you want that is in this directory +local postalFile = 'ocrp-postals.json' + +--[[ +WHAT EVER YOU DO, DON'T TOUCH ANYTHING BELOW UNLESS YOU **KNOW** WHAT YOU ARE DOING +If you just want to change the postal file, **ONLY** change the above variable +--]] +resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' + +client_scripts { + 'config.lua', + 'cl.lua' +} +server_script { + 'config.lua', + 'sv.lua' +} + +file(postalFile) +postal_file(postalFile) + +file 'version.json' diff --git a/resources/nearestpostal/cl.lua b/resources/nearestpostal/cl.lua new file mode 100644 index 000000000..69960cd86 --- /dev/null +++ b/resources/nearestpostal/cl.lua @@ -0,0 +1,195 @@ +local raw = LoadResourceFile(GetCurrentResourceName(), GetResourceMetadata(GetCurrentResourceName(), 'postal_file')) +local postals = json.decode(raw) + +local nearest = nil +local pBlip = nil + +-- thread for nearest and blip +Citizen.CreateThread( + function() + while true do + local x, y = table.unpack(GetEntityCoords(GetPlayerPed(-1))) + + local ndm = -1 -- nearest distance magnitude + local ni = -1 -- nearest index + for i, p in ipairs(postals) do + local dm = (x - p.x) ^ 2 + (y - p.y) ^ 2 -- distance magnitude + if ndm == -1 or dm < ndm then + ni = i + ndm = dm + end + end + + --setting the nearest + if ni ~= -1 then + local nd = math.sqrt(ndm) -- nearest distance + nearest = {i = ni, d = nd} + end + + -- if blip exists + if pBlip then + local b = {x = pBlip.p.x, y = pBlip.p.y} -- blip coords + local dm = (b.x - x) ^ 2 + (b.y - y) ^ 2 -- distance magnitude + if dm < config.blip.distToDelete ^ 2 then + -- delete blip if close + RemoveBlip(pBlip.hndl) + pBlip = nil + end + end + + Wait(100) + end + end +) +-- text display thread +Citizen.CreateThread( + function() + while true do + if nearest and not IsHudHidden() then + local text = config.text.format:format(postals[nearest.i].code, nearest.d) + SetTextScale(0.44, 0.44) + SetTextFont(4) + SetTextOutline() + BeginTextCommandDisplayText('STRING') + AddTextComponentSubstringPlayerName(text) + EndTextCommandDisplayText(config.text.posX, config.text.posY) + end + Wait(0) + end + end +) + +RegisterCommand( + 'postal', + function(source, args, raw) + if #args < 1 then + if pBlip then + RemoveBlip(pBlip.hndl) + pBlip = nil + TriggerEvent( + 'chat:addMessage', + { + color = {255, 0, 0}, + args = { + config.blip.deleteText + } + } + ) + end + return + end + local n = string.upper(args[1]) + + local fp = nil + for _, p in ipairs(postals) do + if string.upper(p.code) == n then + fp = p + end + end + + if fp then + if pBlip then + RemoveBlip(pBlip.hndl) + end + pBlip = {hndl = AddBlipForCoord(fp.x, fp.y, 0.0), p = fp} + SetBlipRoute(pBlip.hndl, true) + SetBlipSprite(pBlip.hndl, config.blip.sprite) + SetBlipColour(pBlip.hndl, config.blip.color) + SetBlipRouteColour(pBlip.hndl, config.blip.color) + BeginTextCommandSetBlipName('STRING') + AddTextComponentSubstringPlayerName(config.blip.blipText:format(pBlip.p.code)) + EndTextCommandSetBlipName(pBlip.hndl) + + TriggerEvent( + 'chat:addMessage', + { + color = {255, 0, 0}, + args = { + config.blip.drawRouteText:format(fp.code) + } + } + ) + else + TriggerEvent( + 'chat:addMessage', + { + color = {255, 0, 0}, + args = { + config.blip.notExistText + } + } + ) + end + end +) + +--[[Development shit]] +local dev = false +if dev then + local devLocal = json.decode(raw) + local next = 0 + + RegisterCommand( + 'setnext', + function(src, args, raw) + local n = tonumber(args[1]) + if n ~= nil then + next = n + print('next ' .. next) + return + end + print('invalid ' .. n) + end + ) + RegisterCommand( + 'next', + function(src, args, raw) + for i, d in ipairs(devLocal) do + if d.code == tostring(next) then + print('duplicate ' .. next) + return + end + end + local coords = GetEntityCoords(GetPlayerPed(-1)) + table.insert(devLocal, {code = tostring(next), x = coords.x, y = coords.y}) + print('insert ' .. next) + next = next + 1 + end + ) + RegisterCommand( + 'rl', + function(src, args, raw) + if #devLocal > 0 then + local data = table.remove(devLocal, #devLocal) + print('remove ' .. data.code) + print('next ' .. next) + next = next - 1 + else + print('invalid') + end + end + ) + RegisterCommand( + 'remove', + function(src, args, raw) + if #args < 1 then + print('invalid') + else + for i, d in ipairs(devLocal) do + if d.code == args[1] then + table.remove(devLocal, i) + print('remove ' .. d.code) + return + end + end + print('invalid') + end + end + ) + RegisterCommand( + 'json', + function(src, args, raw) + print(json.encode(devLocal)) + end + ) +end diff --git a/resources/nearestpostal/config.lua b/resources/nearestpostal/config.lua new file mode 100644 index 000000000..de93c8d79 --- /dev/null +++ b/resources/nearestpostal/config.lua @@ -0,0 +1,21 @@ +config = { + versionCheck = true, -- enables version checking (if this is enabled and there is no new version it won't display a message anyways) + text = { + format = '~w~Nearest Postal :~c~ %s ', + -- ScriptHook PLD Position + --posX = 0.225, + --posY = 0.963, + -- vMenu PLD Position + posX = 0.160, + posY = 0.836 + }, + blip = { + blipText = 'Postal Route %s', + sprite = 8, + color = 5, -- default 3 (light blue) + distToDelete = 100.0, -- in meters + deleteText = '^7Route Removed', + drawRouteText = '^7Drawing Route To %s', + notExistText = "^7Incorrect Postal" + } +} diff --git a/resources/nearestpostal/new-postals.json b/resources/nearestpostal/new-postals.json new file mode 100644 index 000000000..458840627 --- /dev/null +++ b/resources/nearestpostal/new-postals.json @@ -0,0 +1 @@ +[{"x":2325.4345703125,"y":5147.21484375,"code":"2000"},{"x":2151.2138671875,"y":5166.0888671875,"code":"2001"},{"x":2059.6528320313,"y":5105.8408203125,"code":"2002"},{"x":1932.6868896484,"y":5103.4384765625,"code":"2003"},{"x":1874.1627197266,"y":5058.5385742188,"code":"2004"},{"x":1790.8677978516,"y":4980.5830078125,"code":"2005"},{"x":1722.9151611328,"y":4922.7026367188,"code":"2006"},{"x":1618.3675537109,"y":4869.5747070313,"code":"2007"},{"x":1720.4150390625,"y":4869.5498046875,"code":"2008"},{"x":1626.4921875,"y":4812.8330078125,"code":"2009"},{"x":1724.9730224609,"y":4815.1616210938,"code":"2010"},{"x":1640.4869384766,"y":4758.4838867188,"code":"2011"},{"x":1740.1538085938,"y":4759.6303710938,"code":"2012"},{"x":1647.4232177734,"y":4705.2939453125,"code":"2013"},{"x":1749.4649658203,"y":4707.6118164063,"code":"2014"},{"x":1652.0007324219,"y":4648.5717773438,"code":"2015"},{"x":1751.7038574219,"y":4654.4521484375,"code":"2016"},{"x":1798.2783203125,"y":4607.2275390625,"code":"2017"},{"x":1880.2452392578,"y":4613.1025390625,"code":"2018"},{"x":1956.2924804688,"y":4631.9892578125,"code":"2019"},{"x":2006.3699951172,"y":4681.5327148438,"code":"2020"},{"x":1945.4973144531,"y":4801.9169921875,"code":"2021"},{"x":1905.84765625,"y":4860.9282226563,"code":"2022"},{"x":1850.8508300781,"y":4918.7465820313,"code":"2023"},{"x":1964.7199707031,"y":4997.796875,"code":"2024"},{"x":2037.2509765625,"y":4908.0278320313,"code":"2025"},{"x":2195.98046875,"y":5039.0419921875,"code":"2026"},{"x":2399.5415039063,"y":4988.2368164063,"code":"2027"},{"x":2263.0915527344,"y":4912.6440429688,"code":"2028"},{"x":2141.9887695313,"y":4841.7666015625,"code":"2029"},{"x":2071.6528320313,"y":4763.8330078125,"code":"2030"},{"x":2242.1860351563,"y":4777.966796875,"code":"2031"},{"x":2328.8666992188,"y":4865.3110351563,"code":"2032"},{"x":2337.6499023438,"y":4748.4252929688,"code":"2033"},{"x":2417.2333984375,"y":4790.8999023438,"code":"2034"},{"x":2421.2778320313,"y":4689.322265625,"code":"2035"},{"x":2484.35546875,"y":4735.341796875,"code":"2036"},{"x":2510.8581542969,"y":4840.3696289063,"code":"2037"},{"x":2609.3720703125,"y":4881.6694335938,"code":"2038"},{"x":2635.8583984375,"y":4718.7333984375,"code":"2039"},{"x":2571.4553222656,"y":4651.408203125,"code":"2040"},{"x":2509.4165039063,"y":4591.1923828125,"code":"2041"},{"x":2552.4360351563,"y":4526.2192382813,"code":"2042"},{"x":2643.8388671875,"y":4604.1171875,"code":"2043"},{"x":2662.0444335938,"y":4487.2250976563,"code":"2044"},{"x":2596.4248046875,"y":4426.9912109375,"code":"2045"},{"x":2526.1025390625,"y":4358.4770507813,"code":"2046"},{"x":2516.0109863281,"y":4252.19921875,"code":"2047"},{"x":2432.7163085938,"y":4130.552734375,"code":"2048"},{"x":2688.2358398438,"y":4275.7583007813,"code":"2049"},{"x":2879.9858398438,"y":4385.541015625,"code":"2050"},{"x":2928.888671875,"y":4517.7216796875,"code":"2051"},{"x":2876.2612304688,"y":4626.3110351563,"code":"2052"},{"x":2811.85546875,"y":4745.5366210938,"code":"2053"},{"x":2774.6083984375,"y":4863.5556640625,"code":"2054"},{"x":2731.4553222656,"y":5025.2856445313,"code":"2055"},{"x":3051.9165039063,"y":5011.0834960938,"code":"2056"},{"x":3318.0610351563,"y":5191.6752929688,"code":"2057"},{"x":3392.9614257813,"y":5463.1772460938,"code":"2058"},{"x":3751.1640625,"y":4490.3896484375,"code":"2059"},{"x":3523.6528320313,"y":3685.2565917969,"code":"2060"},{"x":1698.5841064453,"y":3599.630859375,"code":"3000"},{"x":1664.0155029297,"y":3657.4467773438,"code":"3001"},{"x":1763.7017822266,"y":3637.3305664063,"code":"3002"},{"x":1732.3602294922,"y":3697.5083007813,"code":"3003"},{"x":1845.0377197266,"y":3686.875,"code":"3004"},{"x":1804.2158203125,"y":3741.1557617188,"code":"3005"},{"x":1909.8052978516,"y":3723.4416503906,"code":"3006"},{"x":1874.7437744141,"y":3775.328125,"code":"3007"},{"x":1980.3048095703,"y":3761.1333007813,"code":"3008"},{"x":1947.779296875,"y":3821.3081054688,"code":"3009"},{"x":2068.7026367188,"y":3803.5920410156,"code":"3010"},{"x":2032.6301269531,"y":3863.7858886719,"code":"3011"},{"x":1915.0797119141,"y":3900.3471679688,"code":"3012"},{"x":1811.0383300781,"y":3910.880859375,"code":"3013"},{"x":1837.5073242188,"y":3849.4609375,"code":"3014"},{"x":1729.4243164063,"y":3867.1586914063,"code":"3015"},{"x":1764.1710205078,"y":3803.3999023438,"code":"3016"},{"x":1632.4604492188,"y":3877.7250976563,"code":"3017"},{"x":1695.5550537109,"y":3753.7414550781,"code":"3018"},{"x":1659.4842529297,"y":3815.0869140625,"code":"3019"},{"x":1635.1939697266,"y":3720.60546875,"code":"3020"},{"x":1586.1025390625,"y":3754.8356933594,"code":"3021"},{"x":1550.0340576172,"y":3805.5637207031,"code":"3022"},{"x":1532.8271484375,"y":3702.8420410156,"code":"3023"},{"x":1500.2799072266,"y":3660.2998046875,"code":"3024"},{"x":1406.3410644531,"y":3649.625,"code":"3025"},{"x":1370.5953369141,"y":3610.6567382813,"code":"3026"},{"x":1155.3911132813,"y":3585.2182617188,"code":"3027"},{"x":1002.1698608398,"y":3586.970703125,"code":"3028"},{"x":890.87438964844,"y":3664.8664550781,"code":"3029"},{"x":868.12127685547,"y":3584.5717773438,"code":"3030"},{"x":464.05184936523,"y":3546.1821289063,"code":"3031"},{"x":354.55065917969,"y":3571.5322265625,"code":"3032"},{"x":12.16725730896,"y":3624.5874023438,"code":"3033"},{"x":106.29637908936,"y":3715.4526367188,"code":"3034"},{"x":1512.6649169922,"y":3571.7692871094,"code":"3035"},{"x":1619.1922607422,"y":3549.9096679688,"code":"3036"},{"x":1772.3302001953,"y":3271.2485351563,"code":"3037"},{"x":1898.9097900391,"y":3274.7416992188,"code":"3038"},{"x":1971.7969970703,"y":3237.5124511719,"code":"3039"},{"x":1982.0775146484,"y":3340.2080078125,"code":"3040"},{"x":2054.947265625,"y":3439.3666992188,"code":"3041"},{"x":2165.5749511719,"y":3509.5932617188,"code":"3042"},{"x":2194.1762695313,"y":3343.0915527344,"code":"3043"},{"x":2117.1166992188,"y":3171.2788085938,"code":"3044"},{"x":1994.0245361328,"y":3027.2221679688,"code":"3045"},{"x":2019.6750488281,"y":2948.1025390625,"code":"3046"},{"x":2127.9638671875,"y":2936.8850097656,"code":"3047"},{"x":2385.0139160156,"y":3089.1416015625,"code":"3048"},{"x":2466.7514648438,"y":3296.2875976563,"code":"3049"},{"x":2578.60546875,"y":3170.5209960938,"code":"3050"},{"x":2649.7263183594,"y":3283.2431640625,"code":"3051"},{"x":2715.1831054688,"y":3490.3386230469,"code":"3052"},{"x":2620.7888183594,"y":2748.8625488281,"code":"3053"},{"x":2892.5708007813,"y":2871.037109375,"code":"3054"},{"x":3092.947265625,"y":2850.3403320313,"code":"3055"},{"x":2529.4777832031,"y":2624.2233886719,"code":"3056"},{"x":2347.9375,"y":2562.8107910156,"code":"3057"},{"x":2090.8237304688,"y":2307.1806640625,"code":"3058"},{"x":2435.2250976563,"y":2136.5595703125,"code":"3059"},{"x":2129.7290039063,"y":1824.2932128906,"code":"3060"},{"x":2498.9165039063,"y":1638.3122558594,"code":"3061"},{"x":2748.8806152344,"y":1728.0220947266,"code":"3062"},{"x":2743.240234375,"y":1360.8472900391,"code":"3063"},{"x":2411.7565917969,"y":1215.591796875,"code":"3064"},{"x":1698.2772216797,"y":2577.6418457031,"code":"4000"},{"x":1558.7576904297,"y":2204.5749511719,"code":"4001"},{"x":1572.5209960938,"y":1671.529296875,"code":"4002"},{"x":1232.7921142578,"y":1878.6875,"code":"4003"},{"x":1115.5771484375,"y":2102.9555664063,"code":"4004"},{"x":1126.4464111328,"y":2505.4987792969,"code":"4005"},{"x":738.87951660156,"y":2552.6716308594,"code":"4006"},{"x":851.88513183594,"y":2287.615234375,"code":"4007"},{"x":979.0517578125,"y":2060.93359375,"code":"4008"},{"x":850.06805419922,"y":2171.275390625,"code":"4009"},{"x":248.26159667969,"y":2579.158203125,"code":"4010"},{"x":72.049034118652,"y":2791.0595703125,"code":"4011"},{"x":-24.513399124146,"y":2883.7233886719,"code":"4012"},{"x":171.71435546875,"y":3051.9291992188,"code":"4013"},{"x":199.73529052734,"y":2784.50390625,"code":"4014"},{"x":359.95733642578,"y":2622.1733398438,"code":"4015"},{"x":393.29782104492,"y":2578.4697265625,"code":"4016"},{"x":481.49340820313,"y":2645.1513671875,"code":"4017"},{"x":481.83526611328,"y":2596.1435546875,"code":"4018"},{"x":567.63238525391,"y":2659.2497558594,"code":"4019"},{"x":596.22540283203,"y":2766.0400390625,"code":"4020"},{"x":932.36022949219,"y":2656.7985839844,"code":"4021"},{"x":976.32257080078,"y":2712.8264160156,"code":"4022"},{"x":1035.6104736328,"y":2652.38671875,"code":"4023"},{"x":1202.3509521484,"y":2708.0361328125,"code":"4024"},{"x":1135.3509521484,"y":2647.7917480469,"code":"4025"},{"x":-432.455078125,"y":2847.0344238281,"code":"5000"},{"x":-111.16876983643,"y":1904.4890136719,"code":"5001"},{"x":-827.80084228516,"y":1729.7996826172,"code":"5002"},{"x":-1298.4808349609,"y":2482.5209960938,"code":"5004"},{"x":-1612.5933837891,"y":2825.9462890625,"code":"5005"},{"x":-2401.2626953125,"y":3522.0424804688,"code":"5006"},{"x":-1695.5712890625,"y":2431.4914550781,"code":"5007"},{"x":-1763.189453125,"y":2228.3947753906,"code":"5008"},{"x":-1912.8382568359,"y":1929.0791015625,"code":"5009"},{"x":-2059.5356445313,"y":2296.7932128906,"code":"5010"},{"x":-2556.2705078125,"y":2323.9028320313,"code":"5011"},{"x":-2583.1748046875,"y":1905.3527832031,"code":"5012"},{"x":-2798.3693847656,"y":1436.0512695313,"code":"5013"},{"x":-2614.8747558594,"y":1119.2763671875,"code":"5014"},{"x":-2127.6206054688,"y":965.19665527344,"code":"5015"},{"x":-1789.1284179688,"y":830.56616210938,"code":"5016"},{"x":-1497.2863769531,"y":1452.0844726563,"code":"5017"},{"x":-1544.8598632813,"y":973.00732421875,"code":"5018"},{"x":-794.03955078125,"y":1043.3806152344,"code":"5019"},{"x":-423.65374755859,"y":1130.7108154297,"code":"5020"},{"x":-190.8380279541,"y":1450.0402832031,"code":"5021"},{"x":139.99778747559,"y":1421.6665039063,"code":"5022"},{"x":808.36334228516,"y":1729.169921875,"code":"5023"},{"x":1420.1495361328,"y":1236.8513183594,"code":"5024"},{"x":767.54479980469,"y":1282.3012695313,"code":"5025"},{"x":145.04937744141,"y":1134.1402587891,"code":"5026"},{"x":-3209.5334472656,"y":1289.7377929688,"code":"5027"},{"x":-3219.8818359375,"y":1252.5125732422,"code":"5028"},{"x":-3219.6066894531,"y":1214.1319580078,"code":"5029"},{"x":-3225.259765625,"y":1180.4542236328,"code":"5030"},{"x":-3231.5,"y":1150.9360351563,"code":"5031"},{"x":-3258.41015625,"y":1107.2193603516,"code":"5032"},{"x":-3159.5808105469,"y":1115.4633789063,"code":"5033"},{"x":-3181.7373046875,"y":1054.6513671875,"code":"5034"},{"x":-3265.2766113281,"y":1080.0319824219,"code":"5035"},{"x":-3268.5485839844,"y":1050.4859619141,"code":"5036"},{"x":-3267.6665039063,"y":1017.9842529297,"code":"5037"},{"x":-3271.5385742188,"y":986.66461181641,"code":"5038"},{"x":-3427.08984375,"y":965.98327636719,"code":"5039"},{"x":-3252.6755371094,"y":912.82080078125,"code":"5040"},{"x":-3049.3513183594,"y":800.64678955078,"code":"5041"},{"x":-3139.1105957031,"y":751.76202392578,"code":"5042"},{"x":-3140.0373535156,"y":714.55914306641,"code":"5043"},{"x":-3124.9997558594,"y":679.12921142578,"code":"5044"},{"x":-3104.8137207031,"y":648.91979980469,"code":"5045"},{"x":-3082.5166015625,"y":621.79669189453,"code":"5046"},{"x":-3072.2216796875,"y":595.18688964844,"code":"5047"},{"x":-3063.6931152344,"y":564.455078125,"code":"5048"},{"x":-3062.8161621094,"y":537.88696289063,"code":"5049"},{"x":-3059.60546875,"y":510.1064453125,"code":"5050"},{"x":-3068.2106933594,"y":481.17578125,"code":"5051"},{"x":-3082.7136230469,"y":451.04525756836,"code":"5052"},{"x":-3100.7553710938,"y":401.41351318359,"code":"5053"},{"x":-3115.8542480469,"y":368.93173217773,"code":"5054"},{"x":-3122.6906738281,"y":340.56274414063,"code":"5055"},{"x":-3133.6220703125,"y":310.44152832031,"code":"5056"},{"x":-3140.4401855469,"y":279.70132446289,"code":"5057"},{"x":-3137.7958984375,"y":247.23010253906,"code":"5058"},{"x":-3117.4375,"y":215.91195678711,"code":"5059"},{"x":-3084.1052246094,"y":157.45587158203,"code":"5060"},{"x":-3067.9194335938,"y":109.04676818848,"code":"5061"},{"x":-3029.8791503906,"y":68.267807006836,"code":"5062"},{"x":-2972.9401855469,"y":34.603740692139,"code":"5063"},{"x":-2881.1638183594,"y":12.759202003479,"code":"5064"},{"x":-2947.6696777344,"y":371.97171020508,"code":"5065"},{"x":-3033.5871582031,"y":384.34530639648,"code":"5066"},{"x":-2946.5361328125,"y":401.41748046875,"code":"5067"},{"x":-2941.5354003906,"y":428.54724121094,"code":"5068"},{"x":-2938.8955078125,"y":459.24383544922,"code":"5069"},{"x":-2940.3774414063,"y":486.94250488281,"code":"5070"},{"x":-2199.2092285156,"y":-389.80383300781,"code":"7000"},{"x":-2116.3181152344,"y":-332.00323486328,"code":"7001"},{"x":-2116.6474609375,"y":-431.80743408203,"code":"7002"},{"x":-2082.7109375,"y":-254.1768951416,"code":"7003"},{"x":-2048.8107910156,"y":-473.78384399414,"code":"7004"},{"x":-2019.6340332031,"y":-223.5227355957,"code":"7005"},{"x":-2018.7672119141,"y":-498.02963256836,"code":"7006"},{"x":-1963.6116943359,"y":-266.07138061523,"code":"7007"},{"x":-1984.607421875,"y":-523.46142578125,"code":"7008"},{"x":-2009.7395019531,"y":-342.28518676758,"code":"7009"},{"x":-1958.1031494141,"y":-548.30725097656,"code":"7010"},{"x":-1884.072265625,"y":-328.76721191406,"code":"7011"},{"x":-1932.2103271484,"y":-571.99481201172,"code":"7012"},{"x":-1950.8552246094,"y":-386.65811157227,"code":"7013"},{"x":-1903.9252929688,"y":-598.01983642578,"code":"7014"},{"x":-1825.1501464844,"y":-371.97402954102,"code":"7015"},{"x":-1871.4891357422,"y":-619.91717529297,"code":"7016"},{"x":-1888.3256835938,"y":-430.47146606445,"code":"7017"},{"x":-1852.6398925781,"y":-650.08361816406,"code":"7018"},{"x":-1792.1490478516,"y":-422.84359741211,"code":"7019"},{"x":-1821.3714599609,"y":-674.30865478516,"code":"7020"},{"x":-1824.0679931641,"y":-477.79266357422,"code":"7021"},{"x":-1781.3073730469,"y":-705.05755615234,"code":"7022"},{"x":-1713.1843261719,"y":-476.66754150391,"code":"7023"},{"x":-1648.576171875,"y":-516.84448242188,"code":"7024"},{"x":-1686.0948486328,"y":-437.1676940918,"code":"7025"},{"x":-1597.8563232422,"y":-444.87408447266,"code":"7026"},{"x":-1648.9616699219,"y":-395.31716918945,"code":"7027"},{"x":-1566.0848388672,"y":-403.62777709961,"code":"7028"},{"x":-1611.2490234375,"y":-351.30529785156,"code":"7029"},{"x":-1507.6091308594,"y":-331.92144775391,"code":"7030"},{"x":-1563.4343261719,"y":-273.51312255859,"code":"7031"},{"x":-1489.373046875,"y":-190.91166687012,"code":"7032"},{"x":-1549.9063720703,"y":-102.99909973145,"code":"7033"},{"x":-1484.7360839844,"y":-53.421825408936,"code":"7034"},{"x":-1593.6586914063,"y":-46.95739364624,"code":"7035"},{"x":-1485.3869628906,"y":23.832782745361,"code":"7036"},{"x":-1562.4373779297,"y":13.172778129578,"code":"7037"},{"x":-1654.2404785156,"y":26.725975036621,"code":"7038"},{"x":-1699.4086914063,"y":65.067581176758,"code":"7039"},{"x":-1622.4224853516,"y":103.41746520996,"code":"7040"},{"x":-1564.8999023438,"y":80.378746032715,"code":"7041"},{"x":-1493.7747802734,"y":74.446685791016,"code":"7042"},{"x":-1554.8959960938,"y":137.55923461914,"code":"7043"},{"x":-1487.9063720703,"y":120.43137359619,"code":"7044"},{"x":-1481.1636962891,"y":165.26069641113,"code":"7045"},{"x":-1447.2622070313,"y":207.74937438965,"code":"7046"},{"x":-1396.8343505859,"y":272.08969116211,"code":"7047"},{"x":-1311.5577392578,"y":252.57038879395,"code":"7048"},{"x":-1362.6612548828,"y":327.51477050781,"code":"7049"},{"x":-1314.5948486328,"y":360.55511474609,"code":"7050"},{"x":-1288.3446044922,"y":314.5029296875,"code":"7051"},{"x":-1243.1960449219,"y":368.21478271484,"code":"7052"},{"x":-1217.525390625,"y":267.8522644043,"code":"7053"},{"x":-1211.3543701172,"y":321.56488037109,"code":"7054"},{"x":-1133.1903076172,"y":359.32727050781,"code":"7055"},{"x":-1117.5603027344,"y":299.68145751953,"code":"7056"},{"x":-1037.6297607422,"y":225.86000061035,"code":"7057"},{"x":-1029.6843261719,"y":157.37721252441,"code":"7058"},{"x":-996.35229492188,"y":110.71755218506,"code":"7059"},{"x":-916.42034912109,"y":103.61616516113,"code":"7060"},{"x":-920.28967285156,"y":154.36337280273,"code":"7061"},{"x":-927.09112548828,"y":199.21054077148,"code":"7062"},{"x":-807.57794189453,"y":164.95886230469,"code":"7063"},{"x":-823.84216308594,"y":107.6879196167,"code":"7064"},{"x":-701.96051025391,"y":190.87864685059,"code":"7065"},{"x":-701.70788574219,"y":145.39820861816,"code":"7066"},{"x":-599.33984375,"y":212.64114379883,"code":"7067"},{"x":-600.82861328125,"y":156.52317810059,"code":"7068"},{"x":-493.72451782227,"y":211.39082336426,"code":"7069"},{"x":-498.17999267578,"y":158.81488037109,"code":"7070"},{"x":-418.12149047852,"y":206.01795959473,"code":"7071"},{"x":-419.13818359375,"y":154.64540100098,"code":"7072"},{"x":-339.17007446289,"y":208.31494140625,"code":"7073"},{"x":-342.44937133789,"y":150.45230102539,"code":"7074"},{"x":-267.19244384766,"y":216.56059265137,"code":"7075"},{"x":-269.85913085938,"y":156.34120178223,"code":"7076"},{"x":-164.54524230957,"y":220.63507080078,"code":"7077"},{"x":-170.33535766602,"y":156.90377807617,"code":"7078"},{"x":-51.261993408203,"y":224.14115905762,"code":"7079"},{"x":-59.861751556396,"y":156.80795288086,"code":"7080"},{"x":-71.413513183594,"y":97.181373596191,"code":"7081"},{"x":3.8074636459351,"y":47.566139221191,"code":"7082"},{"x":24.751974105835,"y":99.49405670166,"code":"7083"},{"x":41.28279876709,"y":148.3278503418,"code":"7084"},{"x":57.770198822021,"y":197.98307800293,"code":"7085"},{"x":86.936210632324,"y":272.8330078125,"code":"7086"},{"x":185.22845458984,"y":388.5940246582,"code":"7087"},{"x":151.84634399414,"y":320.07727050781,"code":"7088"},{"x":166.25904846191,"y":251.57748413086,"code":"7089"},{"x":265.88671875,"y":213.06823730469,"code":"7090"},{"x":293.73529052734,"y":289.29541015625,"code":"7091"},{"x":310.46026611328,"y":358.32046508789,"code":"7092"},{"x":379.85479736328,"y":336.45932006836,"code":"7093"},{"x":363.01657104492,"y":267.38198852539,"code":"7094"},{"x":339.67346191406,"y":191.19873046875,"code":"7095"},{"x":422.00445556641,"y":153.41694641113,"code":"7096"},{"x":449.39508056641,"y":237.2190246582,"code":"7097"},{"x":517.52410888672,"y":218.90100097656,"code":"7098"},{"x":487.09075927734,"y":133.30479431152,"code":"7099"},{"x":579.41821289063,"y":96.697784423828,"code":"7100"},{"x":607.43518066406,"y":184.6509552002,"code":"7101"},{"x":709.21997070313,"y":156.31629943848,"code":"7102"},{"x":678.79772949219,"y":76.612144470215,"code":"7103"},{"x":587.54901123047,"y":-7.8100380897522,"code":"7104"},{"x":502.20208740234,"y":-47.399017333984,"code":"7105"},{"x":470.02700805664,"y":-118.2336807251,"code":"7106"},{"x":441.36865234375,"y":-190.85466003418,"code":"7107"},{"x":426.8782043457,"y":-250.52320861816,"code":"7108"},{"x":331.12322998047,"y":-223.47969055176,"code":"7109"},{"x":356.57424926758,"y":-160.24067687988,"code":"7110"},{"x":386.94644165039,"y":-76.430992126465,"code":"7111"},{"x":422.60900878906,"y":-16.83233833313,"code":"7112"},{"x":451.68350219727,"y":54.277870178223,"code":"7113"},{"x":391.29364013672,"y":71.067588806152,"code":"7114"},{"x":361.43807983398,"y":5.528687953949,"code":"7115"},{"x":337.4909362793,"y":-54.708728790283,"code":"7116"},{"x":304.0458984375,"y":-145.77757263184,"code":"7117"},{"x":283.68252563477,"y":-198.23512268066,"code":"7118"},{"x":202.48402404785,"y":-174.63926696777,"code":"7119"},{"x":223.40191650391,"y":-113.85186767578,"code":"7120"},{"x":250.84468078613,"y":-39.525653839111,"code":"7121"},{"x":275.28668212891,"y":33.049011230469,"code":"7122"},{"x":297.97344970703,"y":101.52397155762,"code":"7123"},{"x":228.58941650391,"y":126.29117584229,"code":"7124"},{"x":201.09918212891,"y":50.693996429443,"code":"7125"},{"x":182.45341491699,"y":-9.5587949752808,"code":"7126"},{"x":147.91889953613,"y":-91.046058654785,"code":"7127"},{"x":126.35182189941,"y":-145.99638366699,"code":"7128"},{"x":46.364261627197,"y":-112.9450302124,"code":"7129"},{"x":67.301887512207,"y":-61.006088256836,"code":"7130"},{"x":95.328193664551,"y":20.40322303772,"code":"7131"},{"x":108.54914855957,"y":64.059242248535,"code":"7132"},{"x":127.78938293457,"y":116.97310638428,"code":"7133"},{"x":141.61860656738,"y":167.12309265137,"code":"7134"},{"x":-8.0422210693359,"y":-24.743330001831,"code":"7135"},{"x":-21.934183120728,"y":-90.271217346191,"code":"7136"},{"x":-124.36614227295,"y":-49.571273803711,"code":"7137"},{"x":-106.42967224121,"y":18.787809371948,"code":"7138"},{"x":-182.25309753418,"y":59.578884124756,"code":"7139"},{"x":-197.94508361816,"y":-24.859977722168,"code":"7140"},{"x":-290.69509887695,"y":8.1253080368042,"code":"7141"},{"x":-282.97415161133,"y":90.788482666016,"code":"7142"},{"x":-354.13092041016,"y":91.340026855469,"code":"7143"},{"x":-353.85736083984,"y":35.223419189453,"code":"7144"},{"x":-435.06552124023,"y":38.151237487793,"code":"7145"},{"x":-434.21737670898,"y":94.225944519043,"code":"7146"},{"x":-505.97164916992,"y":95.970291137695,"code":"7147"},{"x":-506.88833618164,"y":33.970352172852,"code":"7148"},{"x":-605.18395996094,"y":31.588443756104,"code":"7149"},{"x":-604.90783691406,"y":93.528701782227,"code":"7150"},{"x":-698.51153564453,"y":68.708045959473,"code":"7151"},{"x":-691.76470947266,"y":9.6718225479126,"code":"7152"},{"x":-774.73699951172,"y":-9.2394599914551,"code":"7153"},{"x":-796.29791259766,"y":52.13858795166,"code":"7154"},{"x":-914.65380859375,"y":39.113334655762,"code":"7155"},{"x":-865.41485595703,"y":-48.261569976807,"code":"7156"},{"x":-1132.5535888672,"y":-204.72421264648,"code":"7157"},{"x":-1226.751953125,"y":-143.95236206055,"code":"7158"},{"x":-1293.2147216797,"y":-117.44091796875,"code":"7159"},{"x":-1364.3817138672,"y":51.36882019043,"code":"7160"},{"x":-1361.15625,"y":-105.07413482666,"code":"7161"},{"x":-1357.9561767578,"y":-183.01718139648,"code":"7162"},{"x":-1240.8408203125,"y":-194.26989746094,"code":"7163"},{"x":-1204.5501708984,"y":-248.015625,"code":"7164"},{"x":-1278.6323242188,"y":-284.64767456055,"code":"7165"},{"x":-1429.4681396484,"y":-253.36561584473,"code":"7166"},{"x":-1307.0205078125,"y":-241.00469970703,"code":"7167"},{"x":-1375.2297363281,"y":-329.00192260742,"code":"7168"},{"x":-1459.9578857422,"y":-376.86303710938,"code":"7169"},{"x":-1532.3116455078,"y":-437.10891723633,"code":"7170"},{"x":-1588.7243652344,"y":-587.67156982422,"code":"7171"},{"x":-1508.1793212891,"y":-526.90173339844,"code":"7172"},{"x":-1406.3796386719,"y":-456.11715698242,"code":"7173"},{"x":-1324.1636962891,"y":-406.97958374023,"code":"7174"},{"x":-1237.5474853516,"y":-361.89862060547,"code":"7175"},{"x":-1162.9831542969,"y":-321.61190795898,"code":"7176"},{"x":-1085.3809814453,"y":-308.07412719727,"code":"7177"},{"x":-1074.4820556641,"y":-249.66285705566,"code":"7178"},{"x":-934.90258789063,"y":-178.86724853516,"code":"7179"},{"x":-831.94970703125,"y":-125.18535614014,"code":"7180"},{"x":-743.11566162109,"y":-75.616943359375,"code":"7181"},{"x":-627.16333007813,"y":-31.379716873169,"code":"7182"},{"x":-516.63244628906,"y":-29.634790420532,"code":"7183"},{"x":-438.34127807617,"y":-28.469976425171,"code":"7184"},{"x":-341.84225463867,"y":-60.965557098389,"code":"7185"},{"x":-210.51528930664,"y":-109.40273284912,"code":"7186"},{"x":-140.60443115234,"y":-129.51954650879,"code":"7187"},{"x":-45.913478851318,"y":-164.96725463867,"code":"7188"},{"x":21.043941497803,"y":-190.9725189209,"code":"7189"},{"x":108.06352233887,"y":-221.10440063477,"code":"7190"},{"x":172.09213256836,"y":-242.99082946777,"code":"7191"},{"x":257.93273925781,"y":-279.00726318359,"code":"7192"},{"x":304.82440185547,"y":-295.57809448242,"code":"7193"},{"x":390.09271240234,"y":-323.34320068359,"code":"7194"},{"x":377.35684204102,"y":-358.76672363281,"code":"7195"},{"x":294.26147460938,"y":-339.58251953125,"code":"7196"},{"x":239.05592346191,"y":-321.30206298828,"code":"7197"},{"x":156.11320495605,"y":-286.52401733398,"code":"7198"},{"x":89.100494384766,"y":-264.71020507813,"code":"7199"},{"x":4.9829225540161,"y":-230.5140838623,"code":"7200"},{"x":-51.424247741699,"y":-212.25173950195,"code":"7201"},{"x":-147.44256591797,"y":-180.49078369141,"code":"7202"},{"x":-225.07437133789,"y":-158.06991577148,"code":"7203"},{"x":-347.58557128906,"y":-115.0101776123,"code":"7204"},{"x":-473.03695678711,"y":-66.647735595703,"code":"7205"},{"x":-616.19506835938,"y":-90.261505126953,"code":"7206"},{"x":-711.53289794922,"y":-125.12683105469,"code":"7207"},{"x":-801.57043457031,"y":-168.83096313477,"code":"7208"},{"x":-871.07830810547,"y":-233.84226989746,"code":"7209"},{"x":-985.2216796875,"y":-281.61315917969,"code":"7210"},{"x":-1075.2819824219,"y":-346.12161254883,"code":"7211"},{"x":-1133.4451904297,"y":-373.1533203125,"code":"7212"},{"x":-1221.6993408203,"y":-396.22146606445,"code":"7213"},{"x":-1291.6506347656,"y":-448.19494628906,"code":"7214"},{"x":-1372.2003173828,"y":-499.12393188477,"code":"7215"},{"x":-1442.7905273438,"y":-547.9931640625,"code":"7216"},{"x":-1529.2775878906,"y":-612.9306640625,"code":"7217"},{"x":-1468.208984375,"y":-668.4365234375,"code":"7218"},{"x":-1397.7141113281,"y":-616.50567626953,"code":"7219"},{"x":-1319.4672851563,"y":-570.59692382813,"code":"7220"},{"x":-1236.9929199219,"y":-500.71939086914,"code":"7221"},{"x":-1192.6867675781,"y":-456.6296081543,"code":"7222"},{"x":-1116.26171875,"y":-437.17132568359,"code":"7223"},{"x":-1038.6811523438,"y":-405.91580200195,"code":"7224"},{"x":-950.45629882813,"y":-358.13793945313,"code":"7225"},{"x":-863.43701171875,"y":-337.49066162109,"code":"7226"},{"x":-773.43572998047,"y":-220.03509521484,"code":"7227"},{"x":-683.05572509766,"y":-174.72058105469,"code":"7228"},{"x":-593.42590332031,"y":-132.69073486328,"code":"7229"},{"x":-434.96331787109,"y":-129.74906921387,"code":"7230"},{"x":-333.77029418945,"y":-148.63935852051,"code":"7231"},{"x":-229.61874389648,"y":-210.62959289551,"code":"7232"},{"x":-158.52439880371,"y":-230.71984863281,"code":"7233"},{"x":-85.653625488281,"y":-286.23663330078,"code":"7234"},{"x":-24.609064102173,"y":-305.72967529297,"code":"7235"},{"x":65.954689025879,"y":-339.39633178711,"code":"7236"},{"x":128.22149658203,"y":-363.60174560547,"code":"7237"},{"x":214.67274475098,"y":-389.03237915039,"code":"7238"},{"x":271.01861572266,"y":-432.14071655273,"code":"7239"},{"x":200.45906066895,"y":-447.49761962891,"code":"7240"},{"x":112.20059967041,"y":-415.62548828125,"code":"7241"},{"x":39.297740936279,"y":-399.71298217773,"code":"7242"},{"x":-50.179836273193,"y":-367.28509521484,"code":"7243"},{"x":-102.442527771,"y":-343.09912109375,"code":"7244"},{"x":-205.45635986328,"y":-308.86437988281,"code":"7245"},{"x":-335.06890869141,"y":-247.51156616211,"code":"7246"},{"x":-407.41165161133,"y":-173.76556396484,"code":"7247"},{"x":-552.95635986328,"y":-198.59223937988,"code":"7248"},{"x":-527.32592773438,"y":-246.41288757324,"code":"7249"},{"x":-609.56915283203,"y":-290.55505371094,"code":"7250"},{"x":-637.74108886719,"y":-238.21565246582,"code":"7251"},{"x":-708.29119873047,"y":-317.93792724609,"code":"7252"},{"x":-772.34887695313,"y":-376.9787902832,"code":"7253"},{"x":-907.90661621094,"y":-380.63442993164,"code":"7254"},{"x":-1033.8917236328,"y":-440.162109375,"code":"7255"},{"x":-1117.4270019531,"y":-482.70053100586,"code":"7256"},{"x":-1196.8448486328,"y":-540.54779052734,"code":"7257"},{"x":-1296.7912597656,"y":-608.94848632813,"code":"7258"},{"x":-1380.4765625,"y":-661.00457763672,"code":"7259"},{"x":-1435.6938476563,"y":-699.41857910156,"code":"7260"},{"x":-1330.3391113281,"y":-708.89611816406,"code":"7261"},{"x":-1252.6789550781,"y":-665.22430419922,"code":"7262"},{"x":-1178.6728515625,"y":-595.59741210938,"code":"7263"},{"x":-1124.1014404297,"y":-556.05163574219,"code":"7264"},{"x":-1063.0361328125,"y":-525.39495849609,"code":"7265"},{"x":-994.33551025391,"y":-492.98516845703,"code":"7266"},{"x":-894.89099121094,"y":-439.87539672852,"code":"7267"},{"x":-790.12915039063,"y":-438.1298828125,"code":"7268"},{"x":-696.00360107422,"y":-413.35885620117,"code":"7269"},{"x":-576.52172851563,"y":-348.46997070313,"code":"7270"},{"x":-575.54638671875,"y":-422.2868347168,"code":"7271"},{"x":-467.97714233398,"y":-427.6130065918,"code":"7272"},{"x":-504.89535522461,"y":-330.84494018555,"code":"7273"},{"x":-447.94088745117,"y":-303.10745239258,"code":"7274"},{"x":-380.36608886719,"y":-360.9977722168,"code":"7275"},{"x":-374.79534912109,"y":-429.47268676758,"code":"7276"},{"x":-291.27841186523,"y":-443.0768737793,"code":"7277"},{"x":-121.00784301758,"y":-415.94769287109,"code":"7278"},{"x":-72.945343017578,"y":-445.46435546875,"code":"7279"},{"x":51.300407409668,"y":-445.50051879883,"code":"7280"},{"x":379.78671264648,"y":-442.5491027832,"code":"7281"},{"x":571.29211425781,"y":-230.64088439941,"code":"7282"},{"x":573.90319824219,"y":-141.51860046387,"code":"7283"},{"x":684.57373046875,"y":-62.453575134277,"code":"7284"},{"x":775.15447998047,"y":68.541107177734,"code":"7285"},{"x":751.83099365234,"y":225.51345825195,"code":"7286"},{"x":1265.6342773438,"y":318.17315673828,"code":"7287"},{"x":1091.7604980469,"y":237.2815246582,"code":"7288"},{"x":1031.2438964844,"y":153.43008422852,"code":"7289"},{"x":1132.4299316406,"y":102.0453338623,"code":"7290"},{"x":990.43524169922,"y":78.978652954102,"code":"7291"},{"x":951.14349365234,"y":15.789879798889,"code":"7292"},{"x":897.08648681641,"y":-47.410163879395,"code":"7293"},{"x":802.30731201172,"y":-129.49909973145,"code":"7294"},{"x":883.87591552734,"y":-179.1529083252,"code":"7295"},{"x":737.31951904297,"y":-303.07089233398,"code":"7296"},{"x":858.00885009766,"y":-284.80178833008,"code":"7297"},{"x":956.86846923828,"y":-228.18383789063,"code":"7298"},{"x":1004.9545288086,"y":-132.57548522949,"code":"7299"},{"x":1112.0799560547,"y":-198.71315002441,"code":"7300"},{"x":1056.8569335938,"y":-283.15243530273,"code":"7301"},{"x":1159.2609863281,"y":-309.76162719727,"code":"7302"},{"x":1106.41796875,"y":-339.31286621094,"code":"7303"},{"x":998.08197021484,"y":-368.86080932617,"code":"7304"},{"x":1025.4958496094,"y":-396.64190673828,"code":"7305"},{"x":1032.5069580078,"y":-482.85696411133,"code":"7306"},{"x":984.22222900391,"y":-421.69152832031,"code":"7307"},{"x":1004.5624389648,"y":-507.33633422852,"code":"7308"},{"x":952.30828857422,"y":-451.27035522461,"code":"7309"},{"x":961.44720458984,"y":-530.39605712891,"code":"7310"},{"x":919.19305419922,"y":-474.91271972656,"code":"7311"},{"x":920.62359619141,"y":-553.45599365234,"code":"7312"},{"x":861.27502441406,"y":-498.60314941406,"code":"7313"},{"x":837.93188476563,"y":-534.06561279297,"code":"7314"},{"x":834.6513671875,"y":-571.2861328125,"code":"7315"},{"x":868.69256591797,"y":-606.81170654297,"code":"7316"},{"x":910.16247558594,"y":-639.21429443359,"code":"7317"},{"x":984.22778320313,"y":-609.14489746094,"code":"7318"},{"x":940.15533447266,"y":-673.52618408203,"code":"7319"},{"x":962.33331298828,"y":-711.86682128906,"code":"7320"},{"x":1029.8846435547,"y":-682.97528076172,"code":"7321"},{"x":988.23333740234,"y":-743.79754638672,"code":"7322"},{"x":1059.9173583984,"y":-716.05279541016,"code":"7323"},{"x":1048.3874511719,"y":-790.47393798828,"code":"7324"},{"x":1112.9832763672,"y":-743.86700439453,"code":"7325"},{"x":1146.2985839844,"y":-792.89196777344,"code":"7326"},{"x":1151.85546875,"y":-710.85028076172,"code":"7327"},{"x":1241.865234375,"y":-712.66967773438,"code":"7328"},{"x":1302.3513183594,"y":-757.56036376953,"code":"7329"},{"x":1375.2471923828,"y":-778.2587890625,"code":"7330"},{"x":1418.5832519531,"y":-719.27124023438,"code":"7331"},{"x":1348.0096435547,"y":-695.68811035156,"code":"7332"},{"x":1243.8138427734,"y":-663.23425292969,"code":"7333"},{"x":1141.3553466797,"y":-664.12512207031,"code":"7334"},{"x":1133.3791503906,"y":-611.91491699219,"code":"7335"},{"x":1233.3999023438,"y":-624.34521484375,"code":"7336"},{"x":1130.3444824219,"y":-556.46697998047,"code":"7337"},{"x":1226.7858886719,"y":-581.15197753906,"code":"7338"},{"x":1316.2248535156,"y":-592.51257324219,"code":"7339"},{"x":1383.7846679688,"y":-620.29193115234,"code":"7340"},{"x":1404.7026367188,"y":-562.45245361328,"code":"7341"},{"x":1347.1457519531,"y":-532.98547363281,"code":"7342"},{"x":1235.8304443359,"y":-493.45098876953,"code":"7343"},{"x":1131.0235595703,"y":-484.64471435547,"code":"7344"},{"x":1248.1322021484,"y":-443.09335327148,"code":"7345"},{"x":1138.6513671875,"y":-445.71017456055,"code":"7346"},{"x":1264.6722412109,"y":-363.70111083984,"code":"7347"},{"x":1146.2971191406,"y":-399.16549682617,"code":"7348"},{"x":1374.98046875,"y":-149.51196289063,"code":"7349"},{"x":1635.5555419922,"y":-30.312574386597,"code":"7350"},{"x":2178.0,"y":73.750213623047,"code":"7351"},{"x":1859.2497558594,"y":335.0166015625,"code":"7352"},{"x":2424.0,"y":570.25042724609,"code":"7353"},{"x":2565.1499023438,"y":291.29028320313,"code":"7354"},{"x":2579.5817871094,"y":465.62487792969,"code":"7355"},{"x":2407.4816894531,"y":631.80883789063,"code":"7356"},{"x":1532.5715332031,"y":815.74157714844,"code":"7357"},{"x":1975.5415039063,"y":846.99938964844,"code":"7358"},{"x":2291.591796875,"y":939.62420654297,"code":"7359"},{"x":2013.2316894531,"y":1271.3271484375,"code":"7360"},{"x":-1830.291015625,"y":-1214.4635009766,"code":"8000"},{"x":-1678.4899902344,"y":-1117.2708740234,"code":"8001"},{"x":-1620.734375,"y":-1045.5661621094,"code":"8002"},{"x":-1559.7967529297,"y":-974.66320800781,"code":"8003"},{"x":-1613.6203613281,"y":-830.43530273438,"code":"8004"},{"x":-1484.1507568359,"y":-918.12463378906,"code":"8005"},{"x":-1415.4753417969,"y":-876.10388183594,"code":"8006"},{"x":-1343.1877441406,"y":-793.85461425781,"code":"8007"},{"x":-1273.4790039063,"y":-786.72662353516,"code":"8008"},{"x":-1232.4600830078,"y":-836.15246582031,"code":"8009"},{"x":-1168.3585205078,"y":-793.15966796875,"code":"8010"},{"x":-1199.9035644531,"y":-756.53601074219,"code":"8011"},{"x":-1165.298828125,"y":-727.05938720703,"code":"8012"},{"x":-1131.4459228516,"y":-761.37280273438,"code":"8013"},{"x":-1075.2786865234,"y":-708.79516601563,"code":"8014"},{"x":-1031.8812255859,"y":-672.93310546875,"code":"8015"},{"x":-977.32299804688,"y":-642.66235351563,"code":"8016"},{"x":-920.38171386719,"y":-621.97686767578,"code":"8017"},{"x":-806.84155273438,"y":-609.24731445313,"code":"8018"},{"x":-690.900390625,"y":-616.42333984375,"code":"8019"},{"x":-551.08923339844,"y":-611.66772460938,"code":"8020"},{"x":-314.0,"y":-598.94732666016,"code":"8021"},{"x":-179.7685546875,"y":-579.82098388672,"code":"8022"},{"x":-200.94201660156,"y":-643.61340332031,"code":"8023"},{"x":-134.41723632813,"y":-615.75347900391,"code":"8024"},{"x":-63.135009765625,"y":-698.6923828125,"code":"8025"},{"x":-40.45458984375,"y":-641.31292724609,"code":"8026"},{"x":-17.804565429688,"y":-581.57183837891,"code":"8027"},{"x":47.885620117188,"y":-593.5556640625,"code":"8028"},{"x":25.114074707031,"y":-653.37811279297,"code":"8029"},{"x":6.3492431640625,"y":-716.36633300781,"code":"8030"},{"x":87.976623535156,"y":-750.6728515625,"code":"8031"},{"x":112.23950195313,"y":-680.56030273438,"code":"8032"},{"x":133.30133056641,"y":-620.82183837891,"code":"8033"},{"x":188.67425537109,"y":-647.15240478516,"code":"8034"},{"x":173.08740234375,"y":-702.19592285156,"code":"8035"},{"x":143.93762207031,"y":-769.15155029297,"code":"8036"},{"x":246.29974365234,"y":-812.24029541016,"code":"8037"},{"x":270.53942871094,"y":-742.11029052734,"code":"8038"},{"x":290.00720214844,"y":-677.58953857422,"code":"8039"},{"x":326.24517822266,"y":-609.85137939453,"code":"8040"},{"x":462.87261962891,"y":-636.20239257813,"code":"8041"},{"x":374.75653076172,"y":-729.50396728516,"code":"8042"},{"x":358.39038085938,"y":-824.39807128906,"code":"8043"},{"x":457.5615234375,"y":-716.79925537109,"code":"8044"},{"x":456.33410644531,"y":-805.27172851563,"code":"8045"},{"x":456.67822265625,"y":-907.32147216797,"code":"8046"},{"x":464.20166015625,"y":-993.43060302734,"code":"8047"},{"x":359.36865234375,"y":-1011.7819824219,"code":"8048"},{"x":362.11944580078,"y":-927.90307617188,"code":"8049"},{"x":325.01721191406,"y":-887.50073242188,"code":"8050"},{"x":292.69952392578,"y":-983.19506835938,"code":"8051"},{"x":273.89923095703,"y":-1028.6313476563,"code":"8052"},{"x":171.40972900391,"y":-991.18896484375,"code":"8053"},{"x":221.99188232422,"y":-881.20806884766,"code":"8054"},{"x":77.266540527344,"y":-821.47180175781,"code":"8055"},{"x":68.063781738281,"y":-884.46630859375,"code":"8056"},{"x":48.502136230469,"y":-940.29296875,"code":"8057"},{"x":-61.113586425781,"y":-900.44781494141,"code":"8058"},{"x":-43.23681640625,"y":-842.26586914063,"code":"8059"},{"x":-26.1337890625,"y":-788.89819335938,"code":"8060"},{"x":-81.564697265625,"y":-764.98870849609,"code":"8061"},{"x":-106.72705078125,"y":-816.0107421875,"code":"8062"},{"x":-129.48596191406,"y":-875.82818603516,"code":"8063"},{"x":-223.96990966797,"y":-843.17120361328,"code":"8064"},{"x":-207.68090820313,"y":-786.60998535156,"code":"8065"},{"x":-187.39575195313,"y":-731.65405273438,"code":"8066"},{"x":-301.76251220703,"y":-694.13153076172,"code":"8067"},{"x":-301.71411132813,"y":-693.98406982422,"code":"8068"},{"x":-324.98895263672,"y":-816.22521972656,"code":"8069"},{"x":-460.11907958984,"y":-819.43811035156,"code":"8070"},{"x":-468.53918457031,"y":-758.87475585938,"code":"8071"},{"x":-494.47418212891,"y":-701.51293945313,"code":"8072"},{"x":-588.96990966797,"y":-696.76776123047,"code":"8073"},{"x":-579.85424804688,"y":-758.00122070313,"code":"8074"},{"x":-549.23425292969,"y":-808.41369628906,"code":"8075"},{"x":-697.12164306641,"y":-813.23229980469,"code":"8076"},{"x":-695.17755126953,"y":-755.06591796875,"code":"8077"},{"x":-693.22772216797,"y":-692.9306640625,"code":"8078"},{"x":-777.00115966797,"y":-688.97875976563,"code":"8079"},{"x":-780.63635253906,"y":-755.92938232422,"code":"8080"},{"x":-778.72772216797,"y":-811.79296875,"code":"8081"},{"x":-820.61395263672,"y":-784.72058105469,"code":"8082"},{"x":-825.85101318359,"y":-725.76879882813,"code":"8083"},{"x":-901.24066162109,"y":-693.91833496094,"code":"8084"},{"x":-901.66876220703,"y":-759.30755615234,"code":"8085"},{"x":-904.50994873047,"y":-811.95483398438,"code":"8086"},{"x":-963.15289306641,"y":-804.82659912109,"code":"8087"},{"x":-966.00994873047,"y":-723.55163574219,"code":"8088"},{"x":-1023.8558959961,"y":-769.82843017578,"code":"8089"},{"x":-1084.8941650391,"y":-830.42523193359,"code":"8090"},{"x":-1111.6213378906,"y":-879.06958007813,"code":"8091"},{"x":-1175.83203125,"y":-916.56103515625,"code":"8092"},{"x":-1234.453125,"y":-950.07574462891,"code":"8093"},{"x":-1329.7668457031,"y":-965.24383544922,"code":"8094"},{"x":-1354.1298828125,"y":-919.81860351563,"code":"8095"},{"x":-1410.3618164063,"y":-987.5986328125,"code":"8096"},{"x":-1504.8696289063,"y":-1076.0716552734,"code":"8097"},{"x":-1435.9759521484,"y":-1114.3579101563,"code":"8098"},{"x":-1421.2749023438,"y":-1197.2924804688,"code":"8099"},{"x":-1339.2521972656,"y":-1182.1665039063,"code":"8100"},{"x":-1338.125,"y":-1134.3774414063,"code":"8101"},{"x":-1359.2917480469,"y":-1065.0572509766,"code":"8102"},{"x":-1313.4952392578,"y":-1006.940246582,"code":"8103"},{"x":-1293.9929199219,"y":-1054.7724609375,"code":"8104"},{"x":-1276.4588623047,"y":-1109.0532226563,"code":"8105"},{"x":-1266.6072998047,"y":-1152.8873291016,"code":"8106"},{"x":-1224.0283203125,"y":-1014.2146606445,"code":"8107"},{"x":-1195.8745117188,"y":-1078.5490722656,"code":"8108"},{"x":-1179.4812011719,"y":-1129.8607177734,"code":"8109"},{"x":-1156.8045654297,"y":-1180.1136474609,"code":"8110"},{"x":-1153.2834472656,"y":-1244.7104492188,"code":"8111"},{"x":-1103.5051269531,"y":-1283.8050537109,"code":"8112"},{"x":-1010.8887939453,"y":-1222.5776367188,"code":"8113"},{"x":-1038.3781738281,"y":-1174.7432861328,"code":"8114"},{"x":-1063.4271240234,"y":-1130.8625488281,"code":"8115"},{"x":-1090.2277832031,"y":-1077.0704345703,"code":"8116"},{"x":-1117.7211914063,"y":-1037.6478271484,"code":"8117"},{"x":-1150.8475341797,"y":-980.26293945313,"code":"8118"},{"x":-1062.0001220703,"y":-934.07153320313,"code":"8119"},{"x":-1028.1959228516,"y":-990.69000244141,"code":"8120"},{"x":-1007.8956298828,"y":-1029.7551269531,"code":"8121"},{"x":-974.84289550781,"y":-1076.8254394531,"code":"8122"},{"x":-954.54565429688,"y":-1117.4990234375,"code":"8123"},{"x":-940.62219238281,"y":-1179.6693115234,"code":"8124"},{"x":-890.05810546875,"y":-1156.5856933594,"code":"8125"},{"x":-829.146484375,"y":-1114.3566894531,"code":"8126"},{"x":-851.08880615234,"y":-1068.1715087891,"code":"8127"},{"x":-884.19775390625,"y":-1023.565612793,"code":"8128"},{"x":-912.38952636719,"y":-975.99487304688,"code":"8129"},{"x":-940.86529541016,"y":-925.58642578125,"code":"8130"},{"x":-977.18560791016,"y":-880.96557617188,"code":"8131"},{"x":-886.755859375,"y":-861.07391357422,"code":"8132"},{"x":-804.32641601563,"y":-868.27331542969,"code":"8133"},{"x":-803.1748046875,"y":-917.71661376953,"code":"8134"},{"x":-806.00982666016,"y":-967.96362304688,"code":"8135"},{"x":-770.52813720703,"y":-1026.1676025391,"code":"8136"},{"x":-750.345703125,"y":-1071.6313476563,"code":"8137"},{"x":-700.55529785156,"y":-1031.0007324219,"code":"8138"},{"x":-718.55364990234,"y":-984.82147216797,"code":"8139"},{"x":-693.51342773438,"y":-933.83929443359,"code":"8140"},{"x":-696.35992431641,"y":-871.6806640625,"code":"8141"},{"x":-586.82690429688,"y":-870.10583496094,"code":"8142"},{"x":-545.82250976563,"y":-894.85827636719,"code":"8143"},{"x":-563.00665283203,"y":-940.42175292969,"code":"8144"},{"x":-472.60583496094,"y":-1056.7182617188,"code":"8145"},{"x":-492.99487304688,"y":-1006.5607299805,"code":"8146"},{"x":-485.44836425781,"y":-946.77185058594,"code":"8147"},{"x":-470.01870727539,"y":-886.9052734375,"code":"8148"},{"x":-327.6982421875,"y":-884.65887451172,"code":"8149"},{"x":-336.88616943359,"y":-946.072265625,"code":"8150"},{"x":-338.91271972656,"y":-1003.4870605469,"code":"8151"},{"x":-334.58642578125,"y":-1068.0604248047,"code":"8152"},{"x":-317.48376464844,"y":-1119.9077148438,"code":"8153"},{"x":-287.63110351563,"y":-1033.0723876953,"code":"8154"},{"x":-272.1279296875,"y":-969.33654785156,"code":"8155"},{"x":-254.23693847656,"y":-907.1806640625,"code":"8156"},{"x":-159.82067871094,"y":-943.06695556641,"code":"8157"},{"x":-180.19482421875,"y":-1006.8634033203,"code":"8158"},{"x":-201.34191894531,"y":-1066.6782226563,"code":"8159"},{"x":-228.0712890625,"y":-1123.2899169922,"code":"8160"},{"x":-138.45300292969,"y":-1123.2999267578,"code":"8161"},{"x":-118.19567871094,"y":-1063.5217285156,"code":"8162"},{"x":-100.28674316406,"y":-1007.7569580078,"code":"8163"},{"x":-89.623161315918,"y":-964.93267822266,"code":"8164"},{"x":-3.1412353515625,"y":-999.86987304688,"code":"8165"},{"x":-20.306701660156,"y":-1061.2722167969,"code":"8166"},{"x":-43.883117675781,"y":-1123.4693603516,"code":"8167"},{"x":24.226928710938,"y":-1091.6182861328,"code":"8168"},{"x":50.932918548584,"y":-1026.1612548828,"code":"8169"},{"x":131.72967529297,"y":-1048.6171875,"code":"8170"},{"x":109.76110839844,"y":-1108.4281005859,"code":"8171"},{"x":173.09448242188,"y":-1106.0588378906,"code":"8172"},{"x":175.8193359375,"y":-1071.8271484375,"code":"8173"},{"x":268.63513183594,"y":-1071.8500976563,"code":"8174"},{"x":265.79010009766,"y":-1110.1579589844,"code":"8175"},{"x":357.78820800781,"y":-1110.9970703125,"code":"8176"},{"x":356.53411865234,"y":-1071.1478271484,"code":"8177"},{"x":453.3203125,"y":-1070.3530273438,"code":"8178"},{"x":453.67822265625,"y":-1111.8461914063,"code":"8179"},{"x":746.54296875,"y":-1136.5583496094,"code":"8180"},{"x":749.26934814453,"y":-1074.4306640625,"code":"8181"},{"x":744.84594726563,"y":-985.97827148438,"code":"8182"},{"x":739.59899902344,"y":-935.78637695313,"code":"8183"},{"x":735.94299316406,"y":-887.18041992188,"code":"8184"},{"x":729.90185546875,"y":-820.24847412109,"code":"8185"},{"x":731.87231445313,"y":-760.47180175781,"code":"8186"},{"x":739.40161132813,"y":-709.4892578125,"code":"8187"},{"x":817.798828125,"y":-746.24493408203,"code":"8188"},{"x":813.44592285156,"y":-788.44323730469,"code":"8189"},{"x":813.77825927734,"y":-821.92578125,"code":"8190"},{"x":816.51934814453,"y":-884.91625976563,"code":"8191"},{"x":829.63092041016,"y":-937.55480957031,"code":"8192"},{"x":831.572265625,"y":-986.21954345703,"code":"8193"},{"x":841.68493652344,"y":-1033.2755126953,"code":"8194"},{"x":834.65478515625,"y":-1109.8161621094,"code":"8195"},{"x":904.37091064453,"y":-1130.5729980469,"code":"8196"},{"x":911.10461425781,"y":-1051.8024902344,"code":"8197"},{"x":926.62200927734,"y":-969.60461425781,"code":"8198"},{"x":918.21075439453,"y":-897.119140625,"code":"8199"},{"x":-1406.5347900391,"y":-1268.6197509766,"code":"8200"},{"x":-1362.576171875,"y":-1344.2043457031,"code":"8201"},{"x":-1387.0986328125,"y":-1421.5750732422,"code":"8202"},{"x":-1367.3278808594,"y":-1516.0430908203,"code":"8203"},{"x":-1320.4248046875,"y":-1607.5413818359,"code":"8204"},{"x":-1255.2265625,"y":-1700.8128662109,"code":"8205"},{"x":-1198.8803710938,"y":-1793.5231933594,"code":"8206"},{"x":-1084.0930175781,"y":-1662.5076904297,"code":"8207"},{"x":-1110.9595947266,"y":-1617.0979003906,"code":"8208"},{"x":-1156.7485351563,"y":-1553.349609375,"code":"8209"},{"x":-1192.4637451172,"y":-1499.6339111328,"code":"8210"},{"x":-1238.2485351563,"y":-1430.5867919922,"code":"8211"},{"x":-1275.7347412109,"y":-1366.8492431641,"code":"8212"},{"x":-1289.033203125,"y":-1317.2657470703,"code":"8213"},{"x":-1312.3676757813,"y":-1265.9447021484,"code":"8214"},{"x":-1322.7319335938,"y":-1232.3039550781,"code":"8215"},{"x":-1253.39453125,"y":-1208.1477050781,"code":"8216"},{"x":-1244.6705322266,"y":-1239.3704833984,"code":"8217"},{"x":-1218.5848388672,"y":-1304.3797607422,"code":"8218"},{"x":-1205.9111328125,"y":-1337.4548339844,"code":"8219"},{"x":-1176.1430664063,"y":-1392.3951416016,"code":"8220"},{"x":-1135.0238037109,"y":-1453.1245117188,"code":"8221"},{"x":-1105.3430175781,"y":-1501.0115966797,"code":"8222"},{"x":-1058.4248046875,"y":-1572.4730224609,"code":"8223"},{"x":-1038.6776123047,"y":-1604.9644775391,"code":"8224"},{"x":-964.03210449219,"y":-1584.3395996094,"code":"8225"},{"x":-914.76403808594,"y":-1520.599609375,"code":"8226"},{"x":-1004.2291870117,"y":-1528.86328125,"code":"8227"},{"x":-1028.7485351563,"y":-1495.8439941406,"code":"8228"},{"x":-944.04754638672,"y":-1430.3278808594,"code":"8229"},{"x":-1042.3331298828,"y":-1393.162109375,"code":"8230"},{"x":-1112.3000488281,"y":-1360.1431884766,"code":"8231"},{"x":-983.37646484375,"y":-1289.3161621094,"code":"8232"},{"x":-954.77386474609,"y":-1328.3073730469,"code":"8233"},{"x":-885.44458007813,"y":-1302.3771972656,"code":"8234"},{"x":-891.65002441406,"y":-1248.0938720703,"code":"8235"},{"x":-811.63067626953,"y":-1199.6518554688,"code":"8236"},{"x":-791.92803955078,"y":-1242.7899169922,"code":"8237"},{"x":-802.2822265625,"y":-1308.3205566406,"code":"8238"},{"x":-698.70843505859,"y":-1307.7591552734,"code":"8239"},{"x":-714.98480224609,"y":-1416.4106445313,"code":"8240"},{"x":-754.84582519531,"y":-1469.5748291016,"code":"8241"},{"x":-742.16125488281,"y":-1519.7728271484,"code":"8242"},{"x":-692.91424560547,"y":-1492.0563964844,"code":"8243"},{"x":-686.75427246094,"y":-1440.7452392578,"code":"8244"},{"x":-638.69464111328,"y":-1235.3330078125,"code":"8245"},{"x":-676.18487548828,"y":-1187.5369873047,"code":"8246"},{"x":-697.74755859375,"y":-1155.0841064453,"code":"8247"},{"x":-717.52648925781,"y":-1124.4047851563,"code":"8248"},{"x":-586.21545410156,"y":-986.32403564453,"code":"8249"},{"x":-588.90850830078,"y":-1026.4881591797,"code":"8250"},{"x":-606.36547851563,"y":-1065.4576416016,"code":"8251"},{"x":-623.22509765625,"y":-1110.3604736328,"code":"8252"},{"x":-612.92242431641,"y":-1160.5725097656,"code":"8253"},{"x":-529.42797851563,"y":-1234.3839111328,"code":"8254"},{"x":-554.15460205078,"y":-1292.1862792969,"code":"8255"},{"x":-2262.1477050781,"y":297.61862182617,"code":"6000"},{"x":-1994.5190429688,"y":648.20050048828,"code":"6001"},{"x":-1887.9575195313,"y":641.11657714844,"code":"6002"},{"x":-2014.0268554688,"y":599.19030761719,"code":"6003"},{"x":-1912.8198242188,"y":590.29577636719,"code":"6004"},{"x":-2021.7159423828,"y":547.93298339844,"code":"6005"},{"x":-1927.6529541016,"y":532.35278320313,"code":"6006"},{"x":-2030.7054443359,"y":493.98202514648,"code":"6007"},{"x":-1943.0958251953,"y":472.10983276367,"code":"6008"},{"x":-2031.3487548828,"y":436.68328857422,"code":"6009"},{"x":-1928.3488769531,"y":418.35144042969,"code":"6010"},{"x":-2014.828125,"y":388.83602905273,"code":"6011"},{"x":-1919.5220947266,"y":366.36947631836,"code":"6012"},{"x":-2003.0770263672,"y":323.84991455078,"code":"6013"},{"x":-1908.953125,"y":298.46801757813,"code":"6014"},{"x":-1997.8389892578,"y":268.93615722656,"code":"6015"},{"x":-1893.6683349609,"y":249.42088317871,"code":"6016"},{"x":-1978.9973144531,"y":213.98333740234,"code":"6017"},{"x":-1952.7348632813,"y":159.64445495605,"code":"6018"},{"x":-1897.5489501953,"y":112.38739013672,"code":"6019"},{"x":-1869.5643310547,"y":207.38467407227,"code":"6020"},{"x":-1737.0852050781,"y":214.4333190918,"code":"6021"},{"x":-1700.2106933594,"y":159.50413513184,"code":"6022"},{"x":-1660.9986572266,"y":246.86109924316,"code":"6023"},{"x":-1625.8809814453,"y":186.05140686035,"code":"6024"},{"x":-1563.6281738281,"y":213.79307556152,"code":"6025"},{"x":-1849.6419677734,"y":304.65264892578,"code":"6026"},{"x":-1795.0516357422,"y":427.42770385742,"code":"6027"},{"x":-1794.806640625,"y":322.92083740234,"code":"6028"},{"x":-1737.2999267578,"y":355.95559692383,"code":"6029"},{"x":-1669.1251220703,"y":365.39450073242,"code":"6030"},{"x":-1569.6906738281,"y":403.12774658203,"code":"6031"},{"x":-1492.6707763672,"y":541.81518554688,"code":"6032"},{"x":-1481.1917724609,"y":427.87646484375,"code":"6033"},{"x":-1470.8723144531,"y":485.10702514648,"code":"6034"},{"x":-1389.7387695313,"y":578.95404052734,"code":"6035"},{"x":-1319.8041992188,"y":649.19311523438,"code":"6036"},{"x":-1313.0637207031,"y":597.20562744141,"code":"6037"},{"x":-1262.6334228516,"y":679.24865722656,"code":"6038"},{"x":-1251.7319335938,"y":618.4013671875,"code":"6039"},{"x":-1191.8388671875,"y":650.865234375,"code":"6040"},{"x":-1146.6955566406,"y":714.00988769531,"code":"6041"},{"x":-1123.3859863281,"y":807.26391601563,"code":"6042"},{"x":-1096.5444335938,"y":745.27099609375,"code":"6043"},{"x":-1007.7152099609,"y":762.95837402344,"code":"6044"},{"x":-910.65142822266,"y":761.17913818359,"code":"6045"},{"x":-846.13549804688,"y":771.1787109375,"code":"6046"},{"x":-786.77917480469,"y":790.03894042969,"code":"6047"},{"x":-663.72924804688,"y":783.50695800781,"code":"6048"},{"x":-613.87359619141,"y":829.54168701172,"code":"6049"},{"x":-556.94104003906,"y":807.65979003906,"code":"6050"},{"x":-604.46942138672,"y":765.74035644531,"code":"6051"},{"x":-657.92224121094,"y":717.29736328125,"code":"6052"},{"x":-577.37915039063,"y":705.44445800781,"code":"6053"},{"x":-535.78741455078,"y":740.81671142578,"code":"6054"},{"x":-514.25689697266,"y":780.93884277344,"code":"6055"},{"x":-485.08337402344,"y":686.45562744141,"code":"6056"},{"x":-464.73760986328,"y":633.91528320313,"code":"6057"},{"x":-350.533203125,"y":687.02502441406,"code":"6058"},{"x":-401.02182006836,"y":642.13891601563,"code":"6059"},{"x":-291.67199707031,"y":648.49810791016,"code":"6060"},{"x":-341.48052978516,"y":601.91802978516,"code":"6061"},{"x":-239.08898925781,"y":624.33056640625,"code":"6062"},{"x":-277.17504882813,"y":579.43884277344,"code":"6063"},{"x":-168.29577636719,"y":625.44171142578,"code":"6064"},{"x":-204.01466369629,"y":572.865234375,"code":"6065"},{"x":-123.47906494141,"y":574.03063964844,"code":"6066"},{"x":-96.05509185791,"y":814.24304199219,"code":"6067"},{"x":-166.05004882813,"y":880.9013671875,"code":"6068"},{"x":-203.5856628418,"y":980.06671142578,"code":"6069"},{"x":-80.529174804688,"y":1000.1196289063,"code":"6070"},{"x":-44.25,"y":922.18334960938,"code":"6071"},{"x":153.15551757813,"y":735.05572509766,"code":"6072"},{"x":243.75549316406,"y":761.61242675781,"code":"6073"},{"x":375.67501831055,"y":793.47485351563,"code":"6074"},{"x":677.57409667969,"y":638.79724121094,"code":"6075"},{"x":808.29443359375,"y":554.34033203125,"code":"6076"},{"x":656.84167480469,"y":492.91119384766,"code":"6077"},{"x":360.77349853516,"y":414.39306640625,"code":"6078"},{"x":308.50833129883,"y":453.89862060547,"code":"6079"},{"x":295.21667480469,"y":504.61383056641,"code":"6080"},{"x":249.45138549805,"y":658.66259765625,"code":"6081"},{"x":239.11804199219,"y":589.58752441406,"code":"6082"},{"x":175.05268859863,"y":555.31396484375,"code":"6083"},{"x":95.065246582031,"y":548.21667480469,"code":"6084"},{"x":31.002807617188,"y":528.72082519531,"code":"6085"},{"x":39.556945800781,"y":488.56109619141,"code":"6086"},{"x":101.82203674316,"y":501.5361328125,"code":"6087"},{"x":170.56524658203,"y":513.30560302734,"code":"6088"},{"x":198.58605957031,"y":465.48751831055,"code":"6089"},{"x":130.96112060547,"y":448.33193969727,"code":"6090"},{"x":62.770755767822,"y":434.7236328125,"code":"6091"},{"x":-1.2972412109375,"y":447.09588623047,"code":"6092"},{"x":-66.628433227539,"y":468.28079223633,"code":"6093"},{"x":-119.97309112549,"y":482.46658325195,"code":"6094"},{"x":-175.78332519531,"y":485.40130615234,"code":"6095"},{"x":-232.74758911133,"y":470.56115722656,"code":"6096"},{"x":-291.53466796875,"y":474.73196411133,"code":"6097"},{"x":-369.76379394531,"y":455.81115722656,"code":"6098"},{"x":-331.13897705078,"y":511.28619384766,"code":"6099"},{"x":-402.87100219727,"y":492.36114501953,"code":"6100"},{"x":-360.69793701172,"y":541.34301757813,"code":"6101"},{"x":-439.50415039063,"y":518.86938476563,"code":"6102"},{"x":-410.33340454102,"y":567.25268554688,"code":"6103"},{"x":-492.69583129883,"y":531.83337402344,"code":"6104"},{"x":-459.35787963867,"y":578.43200683594,"code":"6105"},{"x":-528.75988769531,"y":594.927734375,"code":"6106"},{"x":-558.10064697266,"y":628.72186279297,"code":"6107"},{"x":-601.43756103516,"y":648.56945800781,"code":"6108"},{"x":-648.38018798828,"y":667.43884277344,"code":"6109"},{"x":-718.94104003906,"y":695.73327636719,"code":"6110"},{"x":-654.31750488281,"y":630.17919921875,"code":"6111"},{"x":-664.091796875,"y":580.56677246094,"code":"6112"},{"x":-713.98077392578,"y":631.90423583984,"code":"6113"},{"x":-717.83959960938,"y":572.28198242188,"code":"6114"},{"x":-766.55902099609,"y":589.95812988281,"code":"6115"},{"x":-775.70361328125,"y":620.64440917969,"code":"6116"},{"x":-789.62451171875,"y":648.34301757813,"code":"6117"},{"x":-806.47595214844,"y":677.22369384766,"code":"6118"},{"x":-862.28363037109,"y":677.79028320313,"code":"6119"},{"x":-918.67370605469,"y":673.61810302734,"code":"6120"},{"x":-974.53161621094,"y":672.35675048828,"code":"6121"},{"x":-1026.2021484375,"y":675.30151367188,"code":"6122"},{"x":-1065.5067138672,"y":708.35546875,"code":"6123"},{"x":-1338.2426757813,"y":541.27087402344,"code":"6124"},{"x":-1388.7254638672,"y":508.19418334961,"code":"6125"},{"x":-1410.8890380859,"y":438.9221496582,"code":"6126"},{"x":-1343.9058837891,"y":476.67770385742,"code":"6127"},{"x":-1351.9217529297,"y":434.14993286133,"code":"6128"},{"x":-1230.0601806641,"y":443.54446411133,"code":"6129"},{"x":-1284.1134033203,"y":488.95129394531,"code":"6130"},{"x":-1212.4343261719,"y":494.26245117188,"code":"6131"},{"x":-1212.158203125,"y":563.90283203125,"code":"6132"},{"x":-1140.2407226563,"y":527.28747558594,"code":"6133"},{"x":-1158.8768310547,"y":573.85028076172,"code":"6134"},{"x":-1115.4670410156,"y":595.69030761719,"code":"6135"},{"x":-1085.6940917969,"y":547.24731445313,"code":"6136"},{"x":-1037.5952148438,"y":565.49865722656,"code":"6137"},{"x":-954.66888427734,"y":609.72082519531,"code":"6138"},{"x":-972.70709228516,"y":558.93609619141,"code":"6139"},{"x":-895.13220214844,"y":582.51110839844,"code":"6140"},{"x":-922.60095214844,"y":537.04864501953,"code":"6141"},{"x":-854.97277832031,"y":554.59283447266,"code":"6142"},{"x":-892.58575439453,"y":498.03335571289,"code":"6143"},{"x":-831.50915527344,"y":513.93762207031,"code":"6144"},{"x":-884.38293457031,"y":452.51110839844,"code":"6145"},{"x":-823.89910888672,"y":466.66662597656,"code":"6146"},{"x":-814.16357421875,"y":409.9831237793,"code":"6147"},{"x":-773.17822265625,"y":481.37347412109,"code":"6148"},{"x":-756.38006591797,"y":412.8776550293,"code":"6149"},{"x":-724.23278808594,"y":499.6208190918,"code":"6150"},{"x":-712.74206542969,"y":441.16241455078,"code":"6151"},{"x":-671.13714599609,"y":517.88616943359,"code":"6152"},{"x":-659.64196777344,"y":466.4958190918,"code":"6153"},{"x":-607.41296386719,"y":531.97094726563,"code":"6154"},{"x":-598.89373779297,"y":476.46380615234,"code":"6155"},{"x":-558.46899414063,"y":553.77642822266,"code":"6156"},{"x":-521.02032470703,"y":494.13180541992,"code":"6157"},{"x":-510.1328125,"y":452.78060913086,"code":"6158"},{"x":-590.72540283203,"y":387.22906494141,"code":"6159"},{"x":-498.37484741211,"y":374.80413818359,"code":"6160"},{"x":-477.44799804688,"y":418.48046875,"code":"6161"},{"x":-422.26184082031,"y":419.63055419922,"code":"6162"},{"x":-437.25512695313,"y":367.65478515625,"code":"6163"},{"x":-462.48934936523,"y":328.10137939453,"code":"6164"},{"x":-393.73489379883,"y":328.10000610352,"code":"6165"},{"x":-369.84939575195,"y":390.66912841797,"code":"6166"},{"x":-323.51623535156,"y":347.55966186523,"code":"6167"},{"x":-316.17437744141,"y":405.98754882813,"code":"6168"},{"x":-266.91488647461,"y":369.94305419922,"code":"6169"},{"x":-207.63012695313,"y":388.1985168457,"code":"6170"},{"x":-157.18350219727,"y":410.58056640625,"code":"6171"},{"x":-84.303298950195,"y":439.47348022461,"code":"6172"},{"x":-86.418128967285,"y":357.40148925781,"code":"6173"},{"x":-6.4694213867188,"y":404.0319519043,"code":"6174"},{"x":-42.2138671875,"y":334.93740844727,"code":"6175"},{"x":49.536071777344,"y":376.21939086914,"code":"6176"},{"x":12.605529785156,"y":310.67916870117,"code":"6177"},{"x":-149.43428039551,"y":291.76098632813,"code":"6178"},{"x":-217.6293182373,"y":297.13497924805,"code":"6179"},{"x":-269.89212036133,"y":289.37637329102,"code":"6180"},{"x":-359.32946777344,"y":272.82220458984,"code":"6181"},{"x":-425.75863647461,"y":271.02914428711,"code":"6182"},{"x":-494.56964111328,"y":286.93753051758,"code":"6183"},{"x":-568.09265136719,"y":335.89297485352,"code":"6184"},{"x":-571.34918212891,"y":290.98889160156,"code":"6185"},{"x":-634.80773925781,"y":294.49157714844,"code":"6186"},{"x":-698.30737304688,"y":314.51943969727,"code":"6187"},{"x":-781.28607177734,"y":319.22219848633,"code":"6188"},{"x":-756.80535888672,"y":260.7624206543,"code":"6189"},{"x":-830.34216308594,"y":254.25691223145,"code":"6190"},{"x":-882.001953125,"y":285.53472900391,"code":"6191"},{"x":-873.49456787109,"y":340.39581298828,"code":"6192"},{"x":-945.36529541016,"y":389.28802490234,"code":"6193"},{"x":-933.15216064453,"y":473.7096862793,"code":"6194"},{"x":-980.72039794922,"y":433.56103515625,"code":"6195"},{"x":-951.53369140625,"y":509.10546875,"code":"6196"},{"x":-997.88922119141,"y":468.37091064453,"code":"6197"},{"x":-1015.9061889648,"y":521.47497558594,"code":"6198"},{"x":-1069.9627685547,"y":478.95004272461,"code":"6199"},{"x":-1041.3735351563,"y":419.33206176758,"code":"6200"},{"x":-1041.6975097656,"y":368.53604125977,"code":"6201"},{"x":-962.31048583984,"y":326.0,"code":"6202"},{"x":-1037.6130371094,"y":308.8818359375,"code":"6203"},{"x":-1112.3223876953,"y":419.82232666016,"code":"6204"},{"x":-1133.8972167969,"y":487.09161376953,"code":"6205"},{"x":-1164.3012695313,"y":446.32086181641,"code":"6206"},{"x":-617.99291992188,"y":-1779.3375244141,"code":"9000"},{"x":-557.49957275391,"y":-1797.0583496094,"code":"9001"},{"x":-512.93701171875,"y":-1739.8428955078,"code":"9002"},{"x":-455.40063476563,"y":-1752.8360595703,"code":"9003"},{"x":-442.17102050781,"y":-1722.7446289063,"code":"9004"},{"x":-425.97006225586,"y":-1691.4652099609,"code":"9005"},{"x":-325.95092773438,"y":-1964.2082519531,"code":"9006"},{"x":-82.513252258301,"y":-2016.1943359375,"code":"9007"},{"x":-111.77169799805,"y":-2131.8942871094,"code":"9008"},{"x":-401.33639526367,"y":-2141.3444824219,"code":"9009"},{"x":-581.68414306641,"y":-2153.1555175781,"code":"9010"},{"x":-508.21328735352,"y":-2211.6374511719,"code":"9011"},{"x":-432.40249633789,"y":-2189.2194824219,"code":"9012"},{"x":-354.24099731445,"y":-2189.8400878906,"code":"9013"},{"x":-284.30514526367,"y":-2220.5444335938,"code":"9014"},{"x":-223.84916687012,"y":-2240.029296875,"code":"9015"},{"x":-110.22423553467,"y":-2227.6540527344,"code":"9016"},{"x":-13.152498245239,"y":-2228.2902832031,"code":"9017"},{"x":-79.018424987793,"y":-2191.7026367188,"code":"9018"},{"x":-10.2855052948,"y":-2171.6804199219,"code":"9019"},{"x":125.16636657715,"y":-2105.5888671875,"code":"9020"},{"x":125.44242095947,"y":-2155.1833496094,"code":"9021"},{"x":189.44230651855,"y":-2152.2485351563,"code":"9022"},{"x":134.2064666748,"y":-2217.1804199219,"code":"9023"},{"x":135.67269897461,"y":-2261.470703125,"code":"9024"},{"x":219.17179870605,"y":-2221.9514160156,"code":"9025"},{"x":299.72015380859,"y":-2211.375,"code":"9026"},{"x":267.52749633789,"y":-2170.0803222656,"code":"9027"},{"x":-366.77319335938,"y":-1601.0847167969,"code":"9028"},{"x":-351.75268554688,"y":-1568.6346435547,"code":"9029"},{"x":-329.61773681641,"y":-1542.0874023438,"code":"9030"},{"x":-317.55230712891,"y":-1515.5374755859,"code":"9031"},{"x":-314.94671630859,"y":-1491.3485107422,"code":"9032"},{"x":-314.65774536133,"y":-1465.9680175781,"code":"9033"},{"x":-314.99819946289,"y":-1401.6596679688,"code":"9034"},{"x":-318.24963378906,"y":-1349.7554931641,"code":"9035"},{"x":-315.59759521484,"y":-1301.3970947266,"code":"9036"},{"x":-222.04414367676,"y":-1279.5596923828,"code":"9037"},{"x":-221.16809082031,"y":-1332.1346435547,"code":"9038"},{"x":-225.03984069824,"y":-1369.3374023438,"code":"9039"},{"x":-223.5772857666,"y":-1394.7319335938,"code":"9040"},{"x":-143.6206817627,"y":-1279.6457519531,"code":"9041"},{"x":-144.53955078125,"y":-1332.1846923828,"code":"9042"},{"x":-58.668151855469,"y":-1296.7834472656,"code":"9043"},{"x":-54.275856018066,"y":-1341.6610107422,"code":"9044"},{"x":2.6582078933716,"y":-1293.2971191406,"code":"9045"},{"x":25.372587203979,"y":-1341.7027587891,"code":"9046"},{"x":118.90602874756,"y":-1300.4305419922,"code":"9047"},{"x":139.26152038574,"y":-1345.3110351563,"code":"9048"},{"x":169.05590820313,"y":-1313.4749755859,"code":"9049"},{"x":182.32823181152,"y":-1281.0345458984,"code":"9050"},{"x":269.36267089844,"y":-1264.5220947266,"code":"9051"},{"x":328.66967773438,"y":-1277.5358886719,"code":"9052"},{"x":400.36538696289,"y":-1320.0499267578,"code":"9053"},{"x":467.93350219727,"y":-1294.66796875,"code":"9054"},{"x":461.69897460938,"y":-1327.1652832031,"code":"9055"},{"x":437.15036010742,"y":-1358.4846191406,"code":"9056"},{"x":456.33099365234,"y":-1382.1110839844,"code":"9057"},{"x":497.3212890625,"y":-1406.9416503906,"code":"9058"},{"x":497.59185791016,"y":-1353.8249511719,"code":"9059"},{"x":486.0364074707,"y":-1468.3637695313,"code":"9060"},{"x":561.10925292969,"y":-1605.8107910156,"code":"9061"},{"x":532.02807617188,"y":-1641.95703125,"code":"9062"},{"x":454.37530517578,"y":-1575.2985839844,"code":"9063"},{"x":475.89196777344,"y":-1511.5500488281,"code":"9064"},{"x":401.17672729492,"y":-1529.8985595703,"code":"9065"},{"x":363.94625854492,"y":-1456.7110595703,"code":"9066"},{"x":397.12634277344,"y":-1431.9426269531,"code":"9067"},{"x":330.79077148438,"y":-1417.8332519531,"code":"9068"},{"x":352.29205322266,"y":-1384.2041015625,"code":"9069"},{"x":264.00042724609,"y":-1344.7014160156,"code":"9070"},{"x":237.13723754883,"y":-1387.8402099609,"code":"9071"},{"x":93.363952636719,"y":-1409.0999755859,"code":"9072"},{"x":57.044925689697,"y":-1454.5513916016,"code":"9073"},{"x":20.694875717163,"y":-1403.2456054688,"code":"9074"},{"x":10.90746307373,"y":-1437.4860839844,"code":"9075"},{"x":-40.752319335938,"y":-1401.4930419922,"code":"9076"},{"x":-52.313407897949,"y":-1441.0485839844,"code":"9077"},{"x":-113.44661712646,"y":-1419.9624023438,"code":"9078"},{"x":-116.69929504395,"y":-1468.9930419922,"code":"9079"},{"x":-155.96124267578,"y":-1441.2569580078,"code":"9080"},{"x":-231.85336303711,"y":-1510.3624267578,"code":"9081"},{"x":-170.21907043457,"y":-1542.2749023438,"code":"9082"},{"x":-200.65257263184,"y":-1574.7651367188,"code":"9083"},{"x":-214.57510375977,"y":-1620.2512207031,"code":"9084"},{"x":-215.48867797852,"y":-1674.0151367188,"code":"9085"},{"x":-187.46504211426,"y":-1731.8972167969,"code":"9086"},{"x":-118.73623657227,"y":-1580.1986083984,"code":"9087"},{"x":-147.97245788574,"y":-1617.9775390625,"code":"9088"},{"x":-82.77734375,"y":-1615.6389160156,"code":"9089"},{"x":-107.89018249512,"y":-1649.8861083984,"code":"9090"},{"x":-130.62887573242,"y":-1685.9069824219,"code":"9091"},{"x":-16.434553146362,"y":-1670.6027832031,"code":"9092"},{"x":-102.92967224121,"y":-1804.6430664063,"code":"9093"},{"x":-52.484455108643,"y":-1760.3791503906,"code":"9094"},{"x":-38.371166229248,"y":-1865.0164794922,"code":"9095"},{"x":-27.483112335205,"y":-1783.0012207031,"code":"9096"},{"x":-17.173496246338,"y":-1886.9387207031,"code":"9097"},{"x":3.1609797477722,"y":-1805.4915771484,"code":"9098"},{"x":9.3448152542114,"y":-1910.5693359375,"code":"9099"},{"x":27.890850067139,"y":-1832.0930175781,"code":"9100"},{"x":47.030918121338,"y":-1930.6762695313,"code":"9101"},{"x":59.687953948975,"y":-1859.2763671875,"code":"9102"},{"x":85.914276123047,"y":-1978.5360107422,"code":"9103"},{"x":108.62252044678,"y":-2008.6540527344,"code":"9104"},{"x":139.58644104004,"y":-1971.5124511719,"code":"9105"},{"x":154.00888061523,"y":-1946.7583007813,"code":"9106"},{"x":137.76422119141,"y":-1922.5985107422,"code":"9107"},{"x":109.70868682861,"y":-1900.1694335938,"code":"9108"},{"x":86.381195068359,"y":-1822.8734130859,"code":"9109"},{"x":20.531059265137,"y":-1737.8999023438,"code":"9110"},{"x":125.27146148682,"y":-1781.5804443359,"code":"9111"},{"x":160.95896911621,"y":-1860.1069335938,"code":"9112"},{"x":205.51319885254,"y":-1877.2679443359,"code":"9113"},{"x":188.67405700684,"y":-1832.4387207031,"code":"9114"},{"x":270.400390625,"y":-1812.3804931641,"code":"9115"},{"x":296.07427978516,"y":-1784.06640625,"code":"9116"},{"x":321.7243347168,"y":-1755.7664794922,"code":"9117"},{"x":287.75616455078,"y":-1728.6472167969,"code":"9118"},{"x":254.39649963379,"y":-1755.8026123047,"code":"9119"},{"x":232.21168518066,"y":-1778.2803955078,"code":"9120"},{"x":179.36712646484,"y":-1731.6680908203,"code":"9121"},{"x":213.28810119629,"y":-1700.4151611328,"code":"9122"},{"x":236.56298828125,"y":-1672.70703125,"code":"9123"},{"x":194.93222045898,"y":-1640.8748779297,"code":"9124"},{"x":150.92175292969,"y":-1654.4763183594,"code":"9125"},{"x":115.18550872803,"y":-1679.8818359375,"code":"9126"},{"x":139.05323791504,"y":-1704.1013183594,"code":"9127"},{"x":177.12002563477,"y":-1681.1290283203,"code":"9128"},{"x":124.26740264893,"y":-1600.2818603516,"code":"9129"},{"x":92.077140808105,"y":-1578.4597167969,"code":"9130"},{"x":69.900650024414,"y":-1556.0500488281,"code":"9131"},{"x":43.629463195801,"y":-1594.4680175781,"code":"9132"},{"x":-32.327224731445,"y":-1556.0760498047,"code":"9133"},{"x":-62.70182800293,"y":-1518.9624023438,"code":"9134"},{"x":-23.499725341797,"y":-1489.4859619141,"code":"9135"},{"x":12.798816680908,"y":-1521.9652099609,"code":"9136"},{"x":112.20829772949,"y":-1510.1943359375,"code":"9137"},{"x":141.41571044922,"y":-1531.4499511719,"code":"9138"},{"x":172.38650512695,"y":-1560.9638671875,"code":"9139"},{"x":213.37115478516,"y":-1538.5693359375,"code":"9140"},{"x":181.76721191406,"y":-1504.3637695313,"code":"9141"},{"x":153.11860656738,"y":-1473.7055664063,"code":"9142"},{"x":181.72525024414,"y":-1446.0069580078,"code":"9143"},{"x":222.1319732666,"y":-1474.9735107422,"code":"9144"},{"x":257.80902099609,"y":-1508.0555419922,"code":"9145"},{"x":302.36294555664,"y":-1466.7805175781,"code":"9146"},{"x":327.43359375,"y":-1572.4595947266,"code":"9147"},{"x":376.68545532227,"y":-1613.8193359375,"code":"9148"},{"x":264.19937133789,"y":-1599.6833496094,"code":"9149"},{"x":296.95776367188,"y":-1631.5750732422,"code":"9150"},{"x":336.20071411133,"y":-1661.7042236328,"code":"9151"},{"x":371.90850830078,"y":-1688.9027099609,"code":"9152"},{"x":408.19897460938,"y":-1652.3526611328,"code":"9153"},{"x":482.81744384766,"y":-1695.4899902344,"code":"9154"},{"x":444.13436889648,"y":-1715.5695800781,"code":"9155"},{"x":415.75253295898,"y":-1750.6276855469,"code":"9156"},{"x":381.80648803711,"y":-1806.7263183594,"code":"9157"},{"x":359.66192626953,"y":-1832.7221679688,"code":"9158"},{"x":337.51217651367,"y":-1857.5415039063,"code":"9159"},{"x":283.48712158203,"y":-1913.0360107422,"code":"9160"},{"x":257.18014526367,"y":-1937.8416748047,"code":"9161"},{"x":239.14413452148,"y":-1966.7734375,"code":"9162"},{"x":216.37110900879,"y":-1992.1818847656,"code":"9163"},{"x":196.4766998291,"y":-2023.4451904297,"code":"9164"},{"x":234.02917480469,"y":-2044.75,"code":"9165"},{"x":251.40965270996,"y":-2019.3680419922,"code":"9166"},{"x":277.07366943359,"y":-1992.8375244141,"code":"9167"},{"x":296.23071289063,"y":-1963.3359375,"code":"9168"},{"x":311.83898925781,"y":-1937.9681396484,"code":"9169"},{"x":362.85647583008,"y":-1890.7777099609,"code":"9170"},{"x":393.24688720703,"y":-1865.4180908203,"code":"9171"},{"x":421.23541259766,"y":-1838.8874511719,"code":"9172"},{"x":463.40255737305,"y":-1775.1500244141,"code":"9173"},{"x":464.87399291992,"y":-1739.7834472656,"code":"9174"},{"x":571.39288330078,"y":-1684.9041748047,"code":"9175"},{"x":543.89892578125,"y":-1736.8942871094,"code":"9176"},{"x":541.19067382813,"y":-1762.2819824219,"code":"9177"},{"x":542.03228759766,"y":-1794.7651367188,"code":"9178"},{"x":526.35394287109,"y":-1823.7244873047,"code":"9179"},{"x":530.18414306641,"y":-1853.2639160156,"code":"9180"},{"x":466.10235595703,"y":-1886.9458007813,"code":"9181"},{"x":432.15661621094,"y":-1916.4638671875,"code":"9182"},{"x":352.16525268555,"y":-1992.0555419922,"code":"9183"},{"x":296.36557006836,"y":-2062.3430175781,"code":"9184"},{"x":329.69763183594,"y":-2095.4055175781,"code":"9185"},{"x":431.13494873047,"y":-2068.9138183594,"code":"9186"},{"x":476.84338378906,"y":-1957.9775390625,"code":"9187"},{"x":524.31469726563,"y":-1937.3402099609,"code":"9188"},{"x":568.86346435547,"y":-1911.3776855469,"code":"9189"},{"x":601.60778808594,"y":-1886.6081542969,"code":"9190"},{"x":600.12127685547,"y":-1936.2330322266,"code":"9191"},{"x":569.69812011719,"y":-1959.2707519531,"code":"9192"},{"x":470.78228759766,"y":-1987.6180419922,"code":"9193"},{"x":548.95880126953,"y":-1988.240234375,"code":"9194"},{"x":509.10345458984,"y":-2015.9930419922,"code":"9195"},{"x":433.83679199219,"y":-2069.7150878906,"code":"9196"},{"x":384.50933837891,"y":-2129.9582519531,"code":"9197"},{"x":404.27166748047,"y":-2222.0832519531,"code":"9198"},{"x":470.06311035156,"y":-2186.6831054688,"code":"9199"},{"x":488.64047241211,"y":-2285.2763671875,"code":"9200"},{"x":550.28009033203,"y":-2390.9594726563,"code":"9201"},{"x":551.72241210938,"y":-2349.0900878906,"code":"9202"},{"x":553.7626953125,"y":-2314.2734375,"code":"9203"},{"x":551.09069824219,"y":-2248.7790527344,"code":"9204"},{"x":552.52258300781,"y":-2219.2861328125,"code":"9205"},{"x":560.46600341797,"y":-2189.7861328125,"code":"9206"},{"x":558.97125244141,"y":-2160.2861328125,"code":"9207"},{"x":559.83239746094,"y":-2131.3762207031,"code":"9208"},{"x":557.73120117188,"y":-2103.06640625,"code":"9209"},{"x":675.45660400391,"y":-2450.7734375,"code":"9210"},{"x":681.64501953125,"y":-2418.3347167969,"code":"9211"},{"x":686.61383056641,"y":-2390.6101074219,"code":"9212"},{"x":687.48236083984,"y":-2362.31640625,"code":"9213"},{"x":690.10327148438,"y":-2331.0654296875,"code":"9214"},{"x":698.06634521484,"y":-2294.5026855469,"code":"9215"},{"x":698.34210205078,"y":-2269.16796875,"code":"9216"},{"x":699.18249511719,"y":-2238.5056152344,"code":"9217"},{"x":703.57458496094,"y":-2207.85546875,"code":"9218"},{"x":703.25238037109,"y":-2178.9763183594,"code":"9219"},{"x":704.72296142578,"y":-2150.6665039063,"code":"9220"},{"x":706.17254638672,"y":-2125.3178710938,"code":"9221"},{"x":709.99371337891,"y":-2094.5502929688,"code":"9222"},{"x":717.91540527344,"y":-2035.6749267578,"code":"9223"},{"x":724.09515380859,"y":-2005.595703125,"code":"9224"},{"x":726.11364746094,"y":-1980.8083496094,"code":"9225"},{"x":731.1142578125,"y":-1946.6137695313,"code":"9226"},{"x":733.75372314453,"y":-1918.3166503906,"code":"9227"},{"x":742.89678955078,"y":-1889.4262695313,"code":"9228"},{"x":751.99627685547,"y":-1860.5263671875,"code":"9229"},{"x":757.55535888672,"y":-1835.16796875,"code":"9230"},{"x":766.69635009766,"y":-1808.6374511719,"code":"9231"},{"x":766.94219970703,"y":-1780.9069824219,"code":"9232"},{"x":779.58880615234,"y":-1710.7069091797,"code":"9233"},{"x":782.20367431641,"y":-1682.4166259766,"code":"9234"},{"x":793.11779785156,"y":-1654.1166992188,"code":"9235"},{"x":794.57348632813,"y":-1621.0943603516,"code":"9236"},{"x":800.15460205078,"y":-1594.5374755859,"code":"9237"},{"x":769.15734863281,"y":-1517.2236328125,"code":"9238"},{"x":757.63647460938,"y":-1492.4582519531,"code":"9239"},{"x":750.80926513672,"y":-1464.7569580078,"code":"9240"},{"x":759.35656738281,"y":-1407.5430908203,"code":"9241"},{"x":760.82312011719,"y":-1376.2651367188,"code":"9242"},{"x":756.37023925781,"y":-1330.2581787109,"code":"9243"},{"x":758.41387939453,"y":-1304.3277587891,"code":"9244"},{"x":760.4638671875,"y":-1271.2944335938,"code":"9245"},{"x":841.01965332031,"y":-1301.9943847656,"code":"9246"},{"x":900.31994628906,"y":-1251.2360839844,"code":"9247"},{"x":962.57122802734,"y":-1268.3680419922,"code":"9248"},{"x":916.81060791016,"y":-1304.9971923828,"code":"9249"},{"x":905.87719726563,"y":-1339.2360839844,"code":"9250"},{"x":869.23614501953,"y":-1366.6544189453,"code":"9251"},{"x":846.77093505859,"y":-1394.1931152344,"code":"9252"},{"x":930.86163330078,"y":-1485.1027832031,"code":"9253"},{"x":901.62854003906,"y":-1528.8305664063,"code":"9254"},{"x":932.58679199219,"y":-1561.9053955078,"code":"9255"},{"x":898.01599121094,"y":-1591.4638671875,"code":"9256"},{"x":913.63989257813,"y":-1631.0485839844,"code":"9257"},{"x":908.58026123047,"y":-1680.0430908203,"code":"9258"},{"x":908.25177001953,"y":-1726.0915527344,"code":"9259"},{"x":914.44543457031,"y":-1796.9332275391,"code":"9260"},{"x":875.14385986328,"y":-1819.970703125,"code":"9261"},{"x":913.17010498047,"y":-1844.7916259766,"code":"9262"},{"x":870.888671875,"y":-1868.0417480469,"code":"9263"},{"x":911.90606689453,"y":-1888.6846923828,"code":"9264"},{"x":856.70599365234,"y":-1910.9805908203,"code":"9265"},{"x":910.48345947266,"y":-1934.7833251953,"code":"9266"},{"x":849.00329589844,"y":-1950.0068359375,"code":"9267"},{"x":903.59759521484,"y":-1964.8068847656,"code":"9268"},{"x":842.453125,"y":-1985.509765625,"code":"9269"},{"x":900.58935546875,"y":-2003.2583007813,"code":"9270"},{"x":842.40466308594,"y":-2021.5987548828,"code":"9271"},{"x":896.99774169922,"y":-2044.6206054688,"code":"9272"},{"x":829.95080566406,"y":-2106.62890625,"code":"9273"},{"x":890.45043945313,"y":-2134.9833984375,"code":"9274"},{"x":827.58190917969,"y":-2155.8142089844,"code":"9275"},{"x":884.50866699219,"y":-2178.1303710938,"code":"9276"},{"x":825.17401123047,"y":-2192.6745605469,"code":"9277"},{"x":880.33807373047,"y":-2221.8735351563,"code":"9278"},{"x":817.43304443359,"y":-2269.1223144531,"code":"9279"},{"x":878.49090576172,"y":-2281.5456542969,"code":"9280"},{"x":809.67956542969,"y":-2294.5361328125,"code":"9281"},{"x":874.87359619141,"y":-2310.4873046875,"code":"9282"},{"x":813.75372314453,"y":-2327.0275878906,"code":"9283"},{"x":863.62548828125,"y":-2348.8903808594,"code":"9284"},{"x":805.45458984375,"y":-2355.9831542969,"code":"9285"},{"x":860.04772949219,"y":-2377.25,"code":"9286"},{"x":806.87121582031,"y":-2393.8037109375,"code":"9287"},{"x":801.77374267578,"y":-2427.5217285156,"code":"9288"},{"x":950.17541503906,"y":-2436.9929199219,"code":"9289"},{"x":994.12274169922,"y":-2416.9306640625,"code":"9290"},{"x":961.46490478516,"y":-2391.5678710938,"code":"9291"},{"x":1003.6517944336,"y":-2362.6762695313,"code":"9292"},{"x":964.39349365234,"y":-2337.3178710938,"code":"9293"},{"x":1010.0933837891,"y":-2314.3291015625,"code":"9294"},{"x":964.29998779297,"y":-2289.5583496094,"code":"9295"},{"x":1013.585144043,"y":-2265.3984375,"code":"9296"},{"x":964.84912109375,"y":-2245.3303222656,"code":"9297"},{"x":1012.9049682617,"y":-2221.7387695313,"code":"9298"},{"x":979.58270263672,"y":-2181.4865722656,"code":"9299"},{"x":1020.4531860352,"y":-2158.0944824219,"code":"9300"},{"x":979.57885742188,"y":-2133.8581542969,"code":"9301"},{"x":1023.3827514648,"y":-2115.6013183594,"code":"9302"},{"x":985.86437988281,"y":-2051.3095703125,"code":"9303"},{"x":1059.4138183594,"y":-2050.6486816406,"code":"9304"},{"x":1133.3771972656,"y":-2048.4389648438,"code":"9305"},{"x":1099.4060058594,"y":-2003.5888671875,"code":"9306"},{"x":992.85186767578,"y":-2015.4055175781,"code":"9307"},{"x":1004.9475708008,"y":-1976.4914550781,"code":"9308"},{"x":1080.1566162109,"y":-1966.4652099609,"code":"9309"},{"x":1001.9356689453,"y":-1938.7569580078,"code":"9310"},{"x":1068.3026123047,"y":-1934.0775146484,"code":"9311"},{"x":1003.0715942383,"y":-1870.3498535156,"code":"9312"},{"x":1054.6960449219,"y":-1853.2316894531,"code":"9313"},{"x":998.73413085938,"y":-1835.5299072266,"code":"9314"},{"x":1054.0369873047,"y":-1817.8415527344,"code":"9315"},{"x":996.44519042969,"y":-1804.2734375,"code":"9316"},{"x":1002.0046386719,"y":-1738.1887207031,"code":"9317"},{"x":1007.0152587891,"y":-1692.7485351563,"code":"9318"},{"x":1009.063659668,"y":-1639.0346679688,"code":"9319"},{"x":1007.5717163086,"y":-1587.1055908203,"code":"9320"},{"x":1007.8425292969,"y":-1538.1569824219,"code":"9321"},{"x":1009.8638305664,"y":-1490.3873291016,"code":"9322"},{"x":991.84326171875,"y":-1392.4138183594,"code":"9323"},{"x":1206.3765869141,"y":-1256.6513671875,"code":"9324"},{"x":1151.7459716797,"y":-1287.9846191406,"code":"9325"},{"x":1204.5270996094,"y":-1311.0207519531,"code":"9326"},{"x":1149.8963623047,"y":-1334.0708007813,"code":"9327"},{"x":1200.9064941406,"y":-1357.1208496094,"code":"9328"},{"x":1147.4772949219,"y":-1384.3026123047,"code":"9329"},{"x":1196.14453125,"y":-1406.1903076172,"code":"9330"},{"x":1140.3162841797,"y":-1481.7553710938,"code":"9331"},{"x":1221.4600830078,"y":-1483.5708007813,"code":"9332"},{"x":1153.2701416016,"y":-1523.1486816406,"code":"9333"},{"x":1230.2770996094,"y":-1527.8721923828,"code":"9334"},{"x":1164.4307861328,"y":-1565.0875244141,"code":"9335"},{"x":1237.6911621094,"y":-1575.8647460938,"code":"9336"},{"x":1162.5869140625,"y":-1613.5277099609,"code":"9337"},{"x":1262.0091552734,"y":-1637.7512207031,"code":"9338"},{"x":1227.4664306641,"y":-1736.3762207031,"code":"9339"},{"x":1288.5411376953,"y":-1704.5250244141,"code":"9340"},{"x":1351.3620605469,"y":-1743.5083007813,"code":"9341"},{"x":1282.580078125,"y":-1772.4735107422,"code":"9342"},{"x":1215.5510253906,"y":-1794.3403320313,"code":"9343"},{"x":1228.8289794922,"y":-1861.0512695313,"code":"9344"},{"x":1301.6967773438,"y":-1830.4056396484,"code":"9345"},{"x":1385.7624511719,"y":-1801.5263671875,"code":"9346"},{"x":1390.1739501953,"y":-1865.3000488281,"code":"9347"},{"x":1313.1165771484,"y":-1870.0721435547,"code":"9348"},{"x":1263.2192382813,"y":-1922.0444335938,"code":"9349"},{"x":1360.8887939453,"y":-1945.6610107422,"code":"9350"},{"x":1290.3082275391,"y":-2001.7761230469,"code":"9351"},{"x":1127.673828125,"y":-2132.865234375,"code":"9352"},{"x":1107.8725585938,"y":-2171.2678222656,"code":"9353"},{"x":1138.2448730469,"y":-2210.8486328125,"code":"9354"},{"x":1098.9436035156,"y":-2242.7248535156,"code":"9355"},{"x":1143.4632568359,"y":-2276.9858398438,"code":"9356"},{"x":1103.0340576172,"y":-2302.9584960938,"code":"9357"},{"x":1147.5634765625,"y":-2335.4653320313,"code":"9358"},{"x":1090.5855712891,"y":-2360.8818359375,"code":"9359"},{"x":1087.3000488281,"y":-2401.6291503906,"code":"9360"},{"x":1175.5441894531,"y":-2396.927734375,"code":"9361"},{"x":1205.8970947266,"y":-2355.6303710938,"code":"9362"},{"x":1227.3927001953,"y":-2301.9345703125,"code":"9363"},{"x":1199.8991699219,"y":-2245.8735351563,"code":"9364"},{"x":1180.0726318359,"y":-2176.2470703125,"code":"9365"},{"x":1306.0710449219,"y":-2080.625,"code":"9366"},{"x":1348.8416748047,"y":-2168.0109863281,"code":"9367"},{"x":1380.3765869141,"y":-2258.9526367188,"code":"9368"},{"x":1390.6770019531,"y":-2358.1665039063,"code":"9369"},{"x":1366.7409667969,"y":-2466.8110351563,"code":"9370"},{"x":1296.7493896484,"y":-2558.3432617188,"code":"9371"},{"x":1413.8663330078,"y":-2606.1623535156,"code":"9372"},{"x":1594.7663574219,"y":-2508.2138671875,"code":"9373"},{"x":1583.8277587891,"y":-2363.6318359375,"code":"9374"},{"x":1603.5710449219,"y":-2279.240234375,"code":"9375"},{"x":1614.4672851563,"y":-2189.5275878906,"code":"9376"},{"x":1540.9575195313,"y":-2138.7861328125,"code":"9377"},{"x":1599.6800537109,"y":-2038.4526367188,"code":"9378"},{"x":1484.8383789063,"y":-1946.4165039063,"code":"9379"},{"x":1661.1246337891,"y":-1895.2449951172,"code":"9380"},{"x":1486.3830566406,"y":-1781.7891845703,"code":"9381"},{"x":1592.4521484375,"y":-1723.3624267578,"code":"9382"},{"x":1699.5831298828,"y":-1697.4276123047,"code":"9383"},{"x":1725.2248535156,"y":-1630.7484130859,"code":"9384"},{"x":1454.5555419922,"y":-1683.2845458984,"code":"9385"},{"x":1714.5651855469,"y":-1546.9458007813,"code":"9386"},{"x":1733.7318115234,"y":-1469.6234130859,"code":"9387"},{"x":1584.0625,"y":-1536.9415283203,"code":"9388"},{"x":1781.4957275391,"y":-1350.4221191406,"code":"9389"},{"x":1938.7570800781,"y":-1018.7138671875,"code":"9390"},{"x":-1021.8845825195,"y":-1994.0374755859,"code":"10000"},{"x":-946.05133056641,"y":-2059.5708007813,"code":"10001"},{"x":-846.64013671875,"y":-2153.4541015625,"code":"10002"},{"x":-720.03704833984,"y":-2267.4235839844,"code":"10003"},{"x":-567.19012451172,"y":-2297.6831054688,"code":"10005"},{"x":-643.64276123047,"y":-2397.4567871094,"code":"10006"},{"x":-710.05786132813,"y":-2500.2082519531,"code":"10007"},{"x":-788.90386962891,"y":-2397.5417480469,"code":"10008"},{"x":-778.62176513672,"y":-2611.2302246094,"code":"10009"},{"x":-848.00964355469,"y":-2760.0,"code":"10010"},{"x":-873.72888183594,"y":-2863.2985839844,"code":"10011"},{"x":-949.60260009766,"y":-3003.7858886719,"code":"10012"},{"x":-1184.2764892578,"y":-3463.6401367188,"code":"10013"},{"x":-1284.3541259766,"y":-3403.44140625,"code":"10014"},{"x":-1358.4816894531,"y":-3354.45703125,"code":"10015"},{"x":-1407.7902832031,"y":-3296.6528320313,"code":"10016"},{"x":-1471.8472900391,"y":-3266.0051269531,"code":"10017"},{"x":-1573.0844726563,"y":-3227.0913085938,"code":"10018"},{"x":-1573.0844726563,"y":-3227.0913085938,"code":"10019"},{"x":-1930.2440185547,"y":-3038.2138671875,"code":"10020"},{"x":-1804.8181152344,"y":-2797.4165039063,"code":"10021"},{"x":-1332.3444824219,"y":-2632.7375488281,"code":"10022"},{"x":-1237.0220947266,"y":-2800.9790039063,"code":"10023"},{"x":-1070.2985839844,"y":-2798.6389160156,"code":"10024"},{"x":-941.36663818359,"y":-2652.2802734375,"code":"10025"},{"x":-1019.6137084961,"y":-2617.4733886719,"code":"10026"},{"x":-1037.0651855469,"y":-2457.5346679688,"code":"10027"},{"x":-1207.3972167969,"y":-2458.1403808594,"code":"10028"},{"x":-1280.8916015625,"y":-2363.7055664063,"code":"10029"},{"x":-1156.0582275391,"y":-2324.7915039063,"code":"10030"},{"x":-1142.8206787109,"y":-2122.3347167969,"code":"10031"},{"x":-1141.9665527344,"y":-2022.0026855469,"code":"10032"},{"x":-1057.8874511719,"y":-2146.0083007813,"code":"10033"},{"x":-1086.5305175781,"y":-2231.6403808594,"code":"10034"},{"x":-984.72900390625,"y":-2211.5805664063,"code":"10035"},{"x":-1057.0612792969,"y":-2364.4816894531,"code":"10036"},{"x":-964.13317871094,"y":-2296.6179199219,"code":"10037"},{"x":-903.05792236328,"y":-2382.240234375,"code":"10038"},{"x":-917.56365966797,"y":-2530.4096679688,"code":"10039"},{"x":-474.59829711914,"y":-2845.0678710938,"code":"10040"},{"x":-504.41088867188,"y":-2782.5302734375,"code":"10041"},{"x":-424.00668334961,"y":-2731.7861328125,"code":"10042"},{"x":-459.76351928711,"y":-2650.931640625,"code":"10043"},{"x":-352.66604614258,"y":-2647.4084472656,"code":"10044"},{"x":-297.56530761719,"y":-2684.6904296875,"code":"10045"},{"x":-209.89566040039,"y":-2661.62890625,"code":"10046"},{"x":-236.75959777832,"y":-2585.5043945313,"code":"10047"},{"x":-244.77053833008,"y":-2511.7653808594,"code":"10048"},{"x":-301.76354980469,"y":-2463.3969726563,"code":"10049"},{"x":-169.87484741211,"y":-2423.2609863281,"code":"10050"},{"x":-145.40510559082,"y":-2464.0290527344,"code":"10051"},{"x":-74.323204040527,"y":-2423.9111328125,"code":"10052"},{"x":-114.78554534912,"y":-2489.470703125,"code":"10053"},{"x":-12.978828430176,"y":-2471.2014160156,"code":"10054"},{"x":54.585052490234,"y":-2498.4028320313,"code":"10055"},{"x":56.023921966553,"y":-2579.3178710938,"code":"10056"},{"x":-133.77590942383,"y":-2585.8427734375,"code":"10057"},{"x":-124.0620880127,"y":-2680.87890625,"code":"10058"},{"x":-47.660713195801,"y":-2703.9208984375,"code":"10059"},{"x":60.614250183105,"y":-2704.5400390625,"code":"10060"},{"x":151.79632568359,"y":-2609.5153808594,"code":"10061"},{"x":218.74485778809,"y":-2508.0222167969,"code":"10062"},{"x":216.63217163086,"y":-2449.0222167969,"code":"10063"},{"x":232.24067687988,"y":-2581.2719726563,"code":"10064"},{"x":319.8544921875,"y":-2603.1403808594,"code":"10065"},{"x":343.10870361328,"y":-2727.7387695313,"code":"10066"},{"x":342.80514526367,"y":-2806.2565917969,"code":"10067"},{"x":222.08653259277,"y":-2809.841796875,"code":"10068"},{"x":139.70875549316,"y":-2845.6511230469,"code":"10069"},{"x":140.58364868164,"y":-2956.08203125,"code":"10070"},{"x":142.61405944824,"y":-3027.5231933594,"code":"10071"},{"x":136.99057006836,"y":-3082.4460449219,"code":"10072"},{"x":134.88229370117,"y":-3140.8874511719,"code":"10073"},{"x":134.55319213867,"y":-3196.9763183594,"code":"10074"},{"x":137.20489501953,"y":-3256.5334472656,"code":"10075"},{"x":136.90292358398,"y":-3309.1843261719,"code":"10076"},{"x":231.04737854004,"y":-3296.2138671875,"code":"10077"},{"x":231.29327392578,"y":-3237.2219238281,"code":"10078"},{"x":233.31416320801,"y":-3179.9929199219,"code":"10079"},{"x":220.00987243652,"y":-3124.4958496094,"code":"10080"},{"x":253.93916320801,"y":-3047.2236328125,"code":"10081"},{"x":240.0265045166,"y":-2994.1252441406,"code":"10082"},{"x":253.2794342041,"y":-2944.5668945313,"code":"10083"},{"x":501.31994628906,"y":-2587.4873046875,"code":"10085"},{"x":501.59371948242,"y":-2646.5278320313,"code":"10086"},{"x":621.66955566406,"y":-2626.48046875,"code":"10087"},{"x":657.95031738281,"y":-2702.6457519531,"code":"10088"},{"x":557.25573730469,"y":-2723.8996582031,"code":"10089"},{"x":480.21716308594,"y":-2771.1220703125,"code":"10090"},{"x":548.96545410156,"y":-2798.8928222656,"code":"10091"},{"x":620.66687011719,"y":-2840.8093261719,"code":"10092"},{"x":486.93087768555,"y":-2918.7470703125,"code":"10093"},{"x":477.15866088867,"y":-2961.25,"code":"10094"},{"x":581.92266845703,"y":-2960.0693359375,"code":"10095"},{"x":475.35305786133,"y":-3007.3217773438,"code":"10096"},{"x":581.89324951172,"y":-3002.6276855469,"code":"10097"},{"x":473.53244018555,"y":-3084.1081542969,"code":"10098"},{"x":564.69610595703,"y":-3063.4899902344,"code":"10099"},{"x":549.59582519531,"y":-3117.8054199219,"code":"10100"},{"x":548.07312011719,"y":-3252.4333496094,"code":"10101"},{"x":761.43371582031,"y":-3197.5541992188,"code":"10102"},{"x":780.36627197266,"y":-3267.2524414063,"code":"10103"},{"x":858.76013183594,"y":-3309.2094726563,"code":"10104"},{"x":983.59204101563,"y":-3308.0690917969,"code":"10105"},{"x":1113.1137695313,"y":-3305.1486816406,"code":"10106"},{"x":1216.6917724609,"y":-3325.2189941406,"code":"10107"},{"x":1218.1235351563,"y":-3249.6943359375,"code":"10108"},{"x":1114.5041503906,"y":-3259.1442871094,"code":"10109"},{"x":983.85168457031,"y":-3255.2136230469,"code":"10110"},{"x":894.91137695313,"y":-3256.23046875,"code":"10111"},{"x":845.85693359375,"y":-3202.8271484375,"code":"10112"},{"x":937.34619140625,"y":-3203.740234375,"code":"10113"},{"x":1026.1749267578,"y":-3202.5693359375,"code":"10114"},{"x":1127.9708251953,"y":-3201.4191894531,"code":"10115"},{"x":1218.5554199219,"y":-3197.3176269531,"code":"10116"},{"x":1218.8428955078,"y":-3125.3359375,"code":"10117"},{"x":1130.5513916016,"y":-3150.1416015625,"code":"10118"},{"x":1029.3150634766,"y":-3148.3669433594,"code":"10119"},{"x":935.14862060547,"y":-3147.8098144531,"code":"10120"},{"x":845.08093261719,"y":-3150.8015136719,"code":"10121"},{"x":846.52368164063,"y":-3091.5949707031,"code":"10122"},{"x":937.10565185547,"y":-3094.2111816406,"code":"10123"},{"x":1029.4763183594,"y":-3095.4301757813,"code":"10124"},{"x":1127.7114257813,"y":-3093.1330566406,"code":"10125"},{"x":1141.5694580078,"y":-3041.7458496094,"code":"10126"},{"x":1032.0513916016,"y":-3041.75,"code":"10127"},{"x":936.71813964844,"y":-3043.4118652344,"code":"10128"},{"x":847.27087402344,"y":-3042.9594726563,"code":"10129"},{"x":796.18920898438,"y":-2985.1528320313,"code":"10130"},{"x":936.33923339844,"y":-2988.7416992188,"code":"10131"},{"x":1031.6276855469,"y":-2989.3403320313,"code":"10132"},{"x":1140.5041503906,"y":-2988.7595214844,"code":"10133"},{"x":1249.4041748047,"y":-2968.1401367188,"code":"10134"},{"x":1141.6721191406,"y":-2930.9624023438,"code":"10135"},{"x":1032.1513671875,"y":-2929.2290039063,"code":"10136"},{"x":936.22802734375,"y":-2931.6108398438,"code":"10137"},{"x":833.19458007813,"y":-2920.4348144531,"code":"10138"},{"x":867.67919921875,"y":-2876.1791992188,"code":"10139"},{"x":1049.1584472656,"y":-2876.1999511719,"code":"10140"},{"x":1644.1221923828,"y":6456.0561523438,"code":"1000"},{"x":1538.3503417969,"y":6344.6381835938,"code":"1001"},{"x":1579.3702392578,"y":6591.4409179688,"code":"1002"},{"x":1409.5551757813,"y":6563.380859375,"code":"1003"},{"x":525.22381591797,"y":6591.1264648438,"code":"1004"},{"x":664.33813476563,"y":6472.9379882813,"code":"1005"},{"x":529.42224121094,"y":6483.48828125,"code":"1006"},{"x":529.42248535156,"y":6483.48828125,"code":"1007"},{"x":264.91348266602,"y":6651.58203125,"code":"1008"},{"x":350.6750793457,"y":6493.5786132813,"code":"1009"},{"x":268.71212768555,"y":6608.3237304688,"code":"1010"},{"x":251.9838104248,"y":6486.3271484375,"code":"1011"},{"x":162.81225585938,"y":6609.9672851563,"code":"1012"},{"x":159.21286010742,"y":6470.6127929688,"code":"1013"},{"x":94.202827453613,"y":6532.0102539063,"code":"1014"},{"x":123.64725494385,"y":6432.8974609375,"code":"1015"},{"x":58.179302215576,"y":6489.2016601563,"code":"1016"},{"x":94.797012329102,"y":6396.873046875,"code":"1017"},{"x":17.470808029175,"y":6448.9428710938,"code":"1018"},{"x":51.979454040527,"y":6359.1142578125,"code":"1019"},{"x":-23.21159362793,"y":6411.6162109375,"code":"1020"},{"x":7.8913064002991,"y":6316.7319335938,"code":"1021"},{"x":-64.347145080566,"y":6370.0634765625,"code":"1022"},{"x":-39.561515808105,"y":6268.4052734375,"code":"1023"},{"x":-99.09156036377,"y":6333.6215820313,"code":"1024"},{"x":-82.781867980957,"y":6226.4506835938,"code":"1025"},{"x":-148.220703125,"y":6284.8950195313,"code":"1026"},{"x":-133.62596130371,"y":6179.8168945313,"code":"1027"},{"x":-190.1768951416,"y":6245.0219726563,"code":"1028"},{"x":-174.72891235352,"y":6134.8852539063,"code":"1029"},{"x":-230.4298248291,"y":6202.61328125,"code":"1030"},{"x":-217.51998901367,"y":6094.6030273438,"code":"1031"},{"x":-279.58258056641,"y":6155.5864257813,"code":"1032"},{"x":-267.09341430664,"y":6047.9760742188,"code":"1033"},{"x":-330.22689819336,"y":6108.1186523438,"code":"1034"},{"x":-307.57904052734,"y":6003.4912109375,"code":"1035"},{"x":-378.52648925781,"y":6057.66015625,"code":"1036"},{"x":-352.06726074219,"y":5955.1591796875,"code":"1037"},{"x":-469.18984985352,"y":6007.6665039063,"code":"1038"},{"x":-469.39916992188,"y":6099.9770507813,"code":"1039"},{"x":-392.09533691406,"y":6090.6328125,"code":"1040"},{"x":-433.38018798828,"y":6151.5864257813,"code":"1041"},{"x":-346.1640625,"y":6137.7934570313,"code":"1042"},{"x":-374.97473144531,"y":6208.701171875,"code":"1043"},{"x":-305.74212646484,"y":6179.0537109375,"code":"1044"},{"x":-310.18420410156,"y":6285.7768554688,"code":"1045"},{"x":-254.49468994141,"y":6231.5395507813,"code":"1046"},{"x":-275.02786254883,"y":6317.8974609375,"code":"1047"},{"x":-210.02728271484,"y":6272.1098632813,"code":"1048"},{"x":-242.01275634766,"y":6353.8388671875,"code":"1049"},{"x":-175.75666809082,"y":6312.71875,"code":"1050"},{"x":-196.32781982422,"y":6388.9331054688,"code":"1051"},{"x":-123.28033447266,"y":6359.677734375,"code":"1052"},{"x":-167.09519958496,"y":6425.7084960938,"code":"1053"},{"x":-85.186561584473,"y":6396.4775390625,"code":"1054"},{"x":-119.70399475098,"y":6479.458984375,"code":"1055"},{"x":-42.021728515625,"y":6441.3334960938,"code":"1056"},{"x":-76.130386352539,"y":6520.498046875,"code":"1057"},{"x":-4.3509998321533,"y":6476.8276367188,"code":"1058"},{"x":-37.633438110352,"y":6558.9624023438,"code":"1059"},{"x":34.14892578125,"y":6519.5629882813,"code":"1060"},{"x":12.325073242188,"y":6597.4770507813,"code":"1061"},{"x":74.358093261719,"y":6555.9448242188,"code":"1062"},{"x":86.009437561035,"y":6652.0385742188,"code":"1063"},{"x":10.838283538818,"y":6674.4462890625,"code":"1064"},{"x":-58.855964660645,"y":6644.7534179688,"code":"1065"},{"x":-112.46115112305,"y":6602.3979492188,"code":"1066"},{"x":-165.63864135742,"y":6555.3393554688,"code":"1067"},{"x":-270.03433227539,"y":6632.380859375,"code":"1068"},{"x":-201.63911437988,"y":6511.2241210938,"code":"1069"},{"x":-234.45983886719,"y":6465.0366210938,"code":"1070"},{"x":-273.66256713867,"y":6420.53125,"code":"1071"},{"x":-334.03851318359,"y":6390.0073242188,"code":"1072"},{"x":-386.79467773438,"y":6351.9189453125,"code":"1073"},{"x":-429.35076904297,"y":6311.615234375,"code":"1074"},{"x":-451.35699462891,"y":6268.455078125,"code":"1075"},{"x":-452.24588012695,"y":6208.68359375,"code":"1076"},{"x":-625.66784667969,"y":6126.9111328125,"code":"1077"},{"x":-568.72412109375,"y":5962.5751953125,"code":"1078"},{"x":-663.3935546875,"y":5785.9438476563,"code":"1079"},{"x":-745.76141357422,"y":5593.6225585938,"code":"1080"},{"x":-549.91040039063,"y":5539.8134765625,"code":"1081"},{"x":-521.32379150391,"y":5301.9467773438,"code":"1082"},{"x":-866.71606445313,"y":5274.794921875,"code":"1083"},{"x":-933.44134521484,"y":5172.6826171875,"code":"1084"},{"x":-1107.71484375,"y":4918.1157226563,"code":"1085"},{"x":-475.41387939453,"y":4956.7563476563,"code":"1086"},{"x":460.43829345703,"y":5615.6508789063,"code":"1087"},{"x":-110.91479492188,"y":4656.4223632813,"code":"1088"},{"x":-133.98173522949,"y":4332.919921875,"code":"1089"},{"x":-257.10409545898,"y":4196.37890625,"code":"1090"},{"x":-238.30830383301,"y":4471.0419921875,"code":"1091"},{"x":-371.33514404297,"y":4337.6025390625,"code":"1092"},{"x":-447.29046630859,"y":4500.8354492188,"code":"1093"},{"x":-605.73547363281,"y":4384.0766601563,"code":"1094"},{"x":-648.34130859375,"y":4479.708984375,"code":"1095"},{"x":-837.50177001953,"y":4377.8969726563,"code":"1096"},{"x":-845.03680419922,"y":4481.4077148438,"code":"1097"},{"x":-1145.6888427734,"y":4329.6235351563,"code":"1098"},{"x":-1209.3537597656,"y":4432.23046875,"code":"1099"},{"x":-1674.9997558594,"y":4365.5014648438,"code":"1100"},{"x":-1623.6866455078,"y":4518.2045898438,"code":"1101"},{"x":-1918.1656494141,"y":4536.6293945313,"code":"1102"},{"x":-1742.2661132813,"y":4626.1162109375,"code":"1103"},{"x":-2160.5085449219,"y":4566.4223632813,"code":"1104"},{"x":-2372.5200195313,"y":4271.5224609375,"code":"1105"},{"x":2170.171875,"y":-639.21948242188,"code":"9391"},{"x":2319.8759765625,"y":-512.19512939453,"code":"9392"},{"x":2502.6103515625,"y":-386.83917236328,"code":"9393"},{"x":2582.0139160156,"y":-645.29943847656,"code":"9394"},{"x":2790.5947265625,"y":-753.72619628906,"code":"9395"}] diff --git a/resources/nearestpostal/ocrp-postals.json b/resources/nearestpostal/ocrp-postals.json new file mode 100644 index 000000000..b4efe5803 --- /dev/null +++ b/resources/nearestpostal/ocrp-postals.json @@ -0,0 +1 @@ +[{"code":"3001","y":4938.10546875,"x":-1157.1995849609},{"code":"3002","y":5300.2319335938,"x":-524.3857421875},{"code":"3003","y":5575.2250976563,"x":-745.71496582031},{"code":"3004","y":5784.3740234375,"x":-662.01904296875},{"code":"3005","y":6009.9873046875,"x":-468.88970947266},{"code":"3006","y":6179.419921875,"x":-471.35647583008},{"code":"3007","y":6117.421875,"x":-350.86978149414},{"code":"3008","y":6058.3271484375,"x":-211.97036743164},{"code":"3009","y":6302.3364257813,"x":-452.68310546875},{"code":"3010","y":6231.6069335938,"x":-362.19027709961},{"code":"3011","y":6303.26171875,"x":-297.83703613281},{"code":"3012","y":6255.7983398438,"x":-199.59306335449},{"code":"3013","y":6192.8037109375,"x":-99.406196594238},{"code":"3014","y":6428.1215820313,"x":-260.72406005859},{"code":"3015","y":6371.9326171875,"x":-212.84980773926},{"code":"3016","y":6372.8686523438,"x":-97.161865234375},{"code":"3017","y":6320.5561523438,"x":24.29870223999},{"code":"3018","y":6574.2983398438,"x":-139.98452758789},{"code":"3019","y":6500.6508789063,"x":-94.954879760742},{"code":"3020","y":6451.2612304688,"x":-14.174062728882},{"code":"3021","y":6389.2724609375,"x":121.82452392578},{"code":"3022","y":6647.8134765625,"x":-42.935974121094},{"code":"3023","y":6587.7592773438,"x":-11.513336181641},{"code":"3024","y":6526.7407226563,"x":71.212539672852},{"code":"3025","y":6649.6870117188,"x":126.84742736816},{"code":"3026","y":6625.439453125,"x":348.04385375977},{"code":"3027","y":6490.7919921875,"x":419.14181518555},{"code":"3028","y":6550.9853515625,"x":1322.1228027344},{"code":"3029","y":6326.28125,"x":1455.2196044922},{"code":"3030","y":6437.6157226563,"x":1685.1595458984},{"code":"3031","y":5583.3940429688,"x":2295.7517089844},{"code":"2001","y":4258.8334960938,"x":-2178.1931152344},{"code":"2002","y":4319.2548828125,"x":-1634.7104492188},{"code":"2003","y":4522.8037109375,"x":-1154.7565917969},{"code":"2004","y":4296.00390625,"x":-624.09436035156},{"code":"2005","y":4355.1645507813,"x":-141.28918457031},{"code":"2006","y":4580.4780273438,"x":295.6540222168},{"code":"2007","y":4180.4365234375,"x":826.40551757813},{"code":"2008","y":4366.3447265625,"x":1286.6721191406},{"code":"2009","y":4854.3540039063,"x":1615.2026367188},{"code":"2010","y":4775.46484375,"x":1632.4442138672},{"code":"2011","y":4695.1557617188,"x":1654.5745849609},{"code":"2012","y":4535.265625,"x":1726.0280761719},{"code":"2013","y":4927.5654296875,"x":1725.6357421875},{"code":"2014","y":4855.7080078125,"x":1728.0529785156},{"code":"2015","y":4777.5185546875,"x":1736.1376953125},{"code":"2016","y":4719.7446289063,"x":1756.1616210938},{"code":"2017","y":4647.1538085938,"x":1754.3770751953},{"code":"2018","y":4602.0727539063,"x":1802.5849609375},{"code":"2019","y":5019.7221679688,"x":1837.4025878906},{"code":"2020","y":4925.3188476563,"x":1899.0174560547},{"code":"2021","y":4631.6372070313,"x":1953.5357666016},{"code":"2022","y":5172.7802734375,"x":1950.373046875},{"code":"2023","y":4786.7739257813,"x":2135.2263183594},{"code":"2024","y":4983.2602539063,"x":2165.8264160156},{"code":"2025","y":5007.197265625,"x":2368.9892578125},{"code":"2026","y":4666.9799804688,"x":2562.9858398438},{"code":"2027","y":5188.94140625,"x":3308.767578125},{"code":"1001","y":2349.3342285156,"x":-2550.39453125},{"code":"1002","y":3377.9497070313,"x":-2304.5493164063},{"code":"1003","y":2635.1474609375,"x":-2089.220703125},{"code":"1004","y":2577.0300292969,"x":-1274.3171386719},{"code":"1005","y":2711.8854980469,"x":-1130.5263671875},{"code":"1006","y":2876.7561035156,"x":-485.82522583008},{"code":"1007","y":3661.3662109375,"x":-15.28427028656},{"code":"1008","y":3398.0107421875,"x":345.8782043457},{"code":"1009","y":3572.2087402344,"x":351.85784912109},{"code":"1010","y":3554.6437988281,"x":457.79168701172},{"code":"1011","y":3480.3251953125,"x":659.57427978516},{"code":"1012","y":3595.0888671875,"x":876.22930908203},{"code":"1013","y":3663.6970214844,"x":925.42852783203},{"code":"1014","y":3590.9748535156,"x":974.62255859375},{"code":"1015","y":3601.75390625,"x":1266.9050292969},{"code":"1016","y":3628.4321289063,"x":1392.4855957031},{"code":"1017","y":3769.4313964844,"x":1495.1656494141},{"code":"1018","y":3678.767578125,"x":1516.5502929688},{"code":"1019","y":3569.0593261719,"x":1564.6318359375},{"code":"1020","y":3312.04296875,"x":1732.3898925781},{"code":"1021","y":3806.9226074219,"x":1627.5222167969},{"code":"1022","y":3742.4670410156,"x":1677.7314453125},{"code":"1023","y":3656.1884765625,"x":1658.7502441406},{"code":"1024","y":3697.3784179688,"x":1731.5983886719},{"code":"1025","y":3612.0498046875,"x":1716.2542724609},{"code":"1026","y":3864.3483886719,"x":1725.1228027344},{"code":"1027","y":3803.8784179688,"x":1765.2497558594},{"code":"1028","y":3742.0070800781,"x":1804.6389160156},{"code":"1029","y":3682.2900390625,"x":1841.1955566406},{"code":"1030","y":3911.8515625,"x":1814.4809570313},{"code":"1031","y":3848.5854492188,"x":1835.4071044922},{"code":"1032","y":3778.177734375,"x":1876.2606201172},{"code":"1033","y":3719.8615722656,"x":1907.8697509766},{"code":"1034","y":3900.4033203125,"x":1913.1685791016},{"code":"1035","y":3824.3405761719,"x":1951.1672363281},{"code":"1036","y":3766.7221679688,"x":1984.19140625},{"code":"1037","y":3528.4833984375,"x":2076.2502441406},{"code":"1038","y":3480.2133789063,"x":2215.1064453125},{"code":"1039","y":3948.63671875,"x":2343.3937988281},{"code":"1040","y":3777.9990234375,"x":2485.1499023438},{"code":"1041","y":4083.6472167969,"x":2433.5891113281},{"code":"1042","y":4095.6848144531,"x":2551.1811523438},{"code":"1043","y":4216.4931640625,"x":2501.0229492188},{"code":"1044","y":4281.84765625,"x":2546.1254882813},{"code":"1045","y":4239.150390625,"x":2637.4304199219},{"code":"1046","y":4128.2592773438,"x":2711.6701660156},{"code":"1047","y":4316.6225585938,"x":2731.896484375},{"code":"1048","y":4423.2265625,"x":2719.3979492188},{"code":"1049","y":4456.609375,"x":2848.3544921875},{"code":"1050","y":4377.6967773438,"x":2880.6806640625},{"code":"1051","y":4632.841796875,"x":2884.5471191406},{"code":"1052","y":4578.7763671875,"x":3715.103515625},{"code":"1053","y":4493.4497070313,"x":3797.9001464844},{"code":"901","y":1293.5513916016,"x":-3201.8759765625},{"code":"902","y":1216.0465087891,"x":-3213.9577636719},{"code":"903","y":1152.0489501953,"x":-3233.6806640625},{"code":"904","y":1091.4372558594,"x":-3252.9572753906},{"code":"905","y":1008.426574707,"x":-3265.4838867188},{"code":"906","y":913.53302001953,"x":-3252.5703125},{"code":"907","y":1129.8149414063,"x":-3157.0576171875},{"code":"908","y":1067.1193847656,"x":-3174.6633300781},{"code":"909","y":1435.5328369141,"x":-2809.2565917969},{"code":"910","y":1897.9064941406,"x":-2607.009765625},{"code":"911","y":2017.0283203125,"x":-1947.3098144531},{"code":"912","y":2810.4892578125,"x":-317.1279296875},{"code":"913","y":2525.0512695313,"x":-297.96936035156},{"code":"914","y":2798.5014648438,"x":-123.50941467285},{"code":"915","y":2872.9191894531,"x":-44.841407775879},{"code":"916","y":2799.7905273438,"x":55.50411605835},{"code":"917","y":3131.6091308594,"x":175.56591796875},{"code":"918","y":3058.5913085938,"x":166.85472106934},{"code":"919","y":2787.7529296875,"x":191.34045410156},{"code":"920","y":2588.626953125,"x":239.65928649902},{"code":"921","y":3103.6450195313,"x":254.8483581543},{"code":"922","y":2985.4584960938,"x":360.26403808594},{"code":"923","y":2960.2287597656,"x":443.1474609375},{"code":"924","y":2860.2282714844,"x":311.90908813477},{"code":"925","y":2624.3161621094,"x":353.99685668945},{"code":"926","y":2581.822265625,"x":375.78540039063},{"code":"927","y":2591.0922851563,"x":475.904296875},{"code":"928","y":2660.0766601563,"x":554.8154296875},{"code":"929","y":2604.2980957031,"x":571.32580566406},{"code":"930","y":2766.197265625,"x":602.42785644531},{"code":"931","y":2525.8842773438,"x":734.41259765625},{"code":"932","y":2325.4072265625,"x":728.35961914063},{"code":"933","y":2167.4350585938,"x":825.84948730469},{"code":"934","y":2875.3527832031,"x":856.36218261719},{"code":"935","y":2724.3225097656,"x":997.20190429688},{"code":"936","y":2649.3203125,"x":981.42303466797},{"code":"937","y":2652.0229492188,"x":1044.6373291016},{"code":"938","y":2308.9228515625,"x":1049.3106689453},{"code":"939","y":2649.26171875,"x":1120.7060546875},{"code":"940","y":2735.0209960938,"x":1201.6359863281},{"code":"941","y":2651.9516601563,"x":1200.8491210938},{"code":"942","y":2752.53515625,"x":1331.0969238281},{"code":"943","y":2167.517578125,"x":1364.7321777344},{"code":"944","y":2798.8046875,"x":1446.0278320313},{"code":"945","y":2227.029296875,"x":1561.7385253906},{"code":"946","y":2900.6560058594,"x":1595.3820800781},{"code":"947","y":2588.3059082031,"x":1689.3629150391},{"code":"948","y":3099.1669921875,"x":1771.2248535156},{"code":"949","y":3032.9753417969,"x":1984.8768310547},{"code":"950","y":2904.5712890625,"x":2056.9135742188},{"code":"951","y":3175.8649902344,"x":2083.9645996094},{"code":"952","y":3332.0219726563,"x":2163.9543457031},{"code":"953","y":3325.3828125,"x":2376.3032226563},{"code":"954","y":3161.3205566406,"x":2375.4978027344},{"code":"955","y":3444.4265136719,"x":2500.552734375},{"code":"956","y":3480.1342773438,"x":2703.6389160156},{"code":"957","y":3302.751953125,"x":2657.8728027344},{"code":"958","y":3206.134765625,"x":2576.388671875},{"code":"959","y":2566.7009277344,"x":2341.2834472656},{"code":"960","y":2593.2197265625,"x":2532.52734375},{"code":"961","y":3490.6088867188,"x":2958.2133789063},{"code":"962","y":2961.0805664063,"x":2903.1413574219},{"code":"963","y":3851.7277832031,"x":3540.4895019531},{"code":"801","y":727.49298095703,"x":-3133.0739746094},{"code":"802","y":657.52075195313,"x":-3103.111328125},{"code":"803","y":613.66979980469,"x":-3075.9448242188},{"code":"804","y":562.04333496094,"x":-3057.9353027344},{"code":"805","y":508.97872924805,"x":-3058.3159179688},{"code":"806","y":456.63592529297,"x":-3076.3896484375},{"code":"807","y":391.56103515625,"x":-3101.5087890625},{"code":"808","y":339.94281005859,"x":-3112.5197753906},{"code":"809","y":290.41351318359,"x":-3130.58984375},{"code":"810","y":226.77479553223,"x":-3123.1892089844},{"code":"811","y":66.97875213623,"x":-2999.1416015625},{"code":"812","y":741.36401367188,"x":-2991.2429199219},{"code":"813","y":644.49810791016,"x":-2953.4406738281},{"code":"814","y":466.29776000977,"x":-2934.0209960938},{"code":"815","y":404.0383605957,"x":-2940.0712890625},{"code":"816","y":278.16241455078,"x":-2258.9624023438},{"code":"817","y":809.28607177734,"x":-1807.1549072266},{"code":"818","y":651.705078125,"x":-1993.0378417969},{"code":"819","y":595.24615478516,"x":-2012.15234375},{"code":"820","y":550.56243896484,"x":-2026.0506591797},{"code":"821","y":500.66088867188,"x":-2034.6998291016},{"code":"822","y":444.19647216797,"x":-2027.5451660156},{"code":"823","y":377.19348144531,"x":-2017.7687988281},{"code":"824","y":316.75762939453,"x":-2013.2709960938},{"code":"825","y":252.41906738281,"x":-1996.9548339844},{"code":"826","y":206.4497833252,"x":-1978.0290527344},{"code":"827","y":165.70098876953,"x":-1955.1405029297},{"code":"828","y":122.37518310547,"x":-1913.8601074219},{"code":"829","y":648.15466308594,"x":-1875.0747070313},{"code":"830","y":593.49920654297,"x":-1905.2770996094},{"code":"831","y":546.6064453125,"x":-1925.5405273438},{"code":"832","y":441.55688476563,"x":-1935.1442871094},{"code":"833","y":402.51373291016,"x":-1916.3543701172},{"code":"834","y":360.62469482422,"x":-1902.5726318359},{"code":"835","y":300.27200317383,"x":-1903.6770019531},{"code":"836","y":253.40664672852,"x":-1894.8408203125},{"code":"837","y":204.42762756348,"x":-1863.98828125},{"code":"838","y":443.55130004883,"x":-1805.8703613281},{"code":"839","y":300.18054199219,"x":-1838.916015625},{"code":"840","y":330.66928100586,"x":-1781.8273925781},{"code":"841","y":360.45956420898,"x":-1728.2764892578},{"code":"842","y":374.64520263672,"x":-1664.080078125},{"code":"843","y":218.75659179688,"x":-1639.2198486328},{"code":"844","y":828.69781494141,"x":-1538.771484375},{"code":"845","y":402.57580566406,"x":-1537.548828125},{"code":"846","y":535.59680175781,"x":-1516.1257324219},{"code":"847","y":426.69454956055,"x":-1474.0634765625},{"code":"848","y":567.76055908203,"x":-1462.7553710938},{"code":"849","y":492.15582275391,"x":-1459.5189208984},{"code":"850","y":585.38360595703,"x":-1387.2258300781},{"code":"851","y":519.33111572266,"x":-1388.5043945313},{"code":"852","y":441.68988037109,"x":-1409.9630126953},{"code":"853","y":594.35089111328,"x":-1314.9973144531},{"code":"854","y":544.96209716797,"x":-1327.8444824219},{"code":"855","y":488.00241088867,"x":-1340.6954345703},{"code":"856","y":431.55682373047,"x":-1338.4265136719},{"code":"857","y":672.44427490234,"x":-1274.6931152344},{"code":"858","y":617.46813964844,"x":-1245.2126464844},{"code":"859","y":503.05047607422,"x":-1283.2934570313},{"code":"860","y":439.55072021484,"x":-1249.7810058594},{"code":"861","y":661.79766845703,"x":-1178.4837646484},{"code":"862","y":581.11590576172,"x":-1179.7543945313},{"code":"863","y":501.97787475586,"x":-1181.5584716797},{"code":"864","y":440.97116088867,"x":-1140.0174560547},{"code":"865","y":805.79510498047,"x":-1154.3947753906},{"code":"866","y":724.61206054688,"x":-1133.9838867188},{"code":"867","y":607.1767578125,"x":-1114.087890625},{"code":"868","y":537.60321044922,"x":-1098.7233886719},{"code":"869","y":489.72360229492,"x":-1067.2468261719},{"code":"870","y":439.80783081055,"x":-1011.0524902344},{"code":"871","y":816.91455078125,"x":-1076.4261474609},{"code":"872","y":741.80963134766,"x":-1074.1765136719},{"code":"873","y":689.38781738281,"x":-1048.7442626953},{"code":"874","y":567.39105224609,"x":-1010.6953735352},{"code":"875","y":529.04888916016,"x":-983.22827148438},{"code":"876","y":463.48492431641,"x":-898.82684326172},{"code":"877","y":829.03680419922,"x":-987.22875976563},{"code":"878","y":751.84381103516,"x":-997.12158203125},{"code":"879","y":672.67785644531,"x":-967.66253662109},{"code":"880","y":603.607421875,"x":-917.04614257813},{"code":"881","y":532.03741455078,"x":-917.29620361328},{"code":"882","y":542.07922363281,"x":-833.88854980469},{"code":"883","y":481.57461547852,"x":-806.93255615234},{"code":"884","y":827.77227783203,"x":-906.47698974609},{"code":"885","y":763.24426269531,"x":-890.11663818359},{"code":"886","y":680.55010986328,"x":-873.76550292969},{"code":"887","y":666.43908691406,"x":-797.44415283203},{"code":"888","y":576.69470214844,"x":-751.33190917969},{"code":"889","y":500.55163574219,"x":-743.53308105469},{"code":"890","y":793.35217285156,"x":-783.10540771484},{"code":"891","y":657.78405761719,"x":-716.87322998047},{"code":"892","y":530.25390625,"x":-664.23413085938},{"code":"893","y":863.29602050781,"x":-648.90368652344},{"code":"894","y":779.59210205078,"x":-633.57360839844},{"code":"895","y":719.57836914063,"x":-638.88598632813},{"code":"896","y":647.9873046875,"x":-636.62658691406},{"code":"897","y":553.20501708984,"x":-587.50799560547},{"code":"898","y":814.25256347656,"x":-560.58245849609},{"code":"899","y":767.3818359375,"x":-520.02551269531},{"code":"700","y":700.64111328125,"x":-571.45959472656},{"code":"701","y":637.80151367188,"x":-561.36743164063},{"code":"702","y":590.93304443359,"x":-539.97625732422},{"code":"703","y":1140.2042236328,"x":-433.81268310547},{"code":"704","y":691.09136962891,"x":-474.76422119141},{"code":"705","y":611.43249511719,"x":-465.47528076172},{"code":"706","y":640.12591552734,"x":-400.73538208008},{"code":"707","y":1908.4576416016,"x":-96.335205078125},{"code":"708","y":987.76916503906,"x":-198.64361572266},{"code":"709","y":882.60046386719,"x":-167.36044311523},{"code":"710","y":674.24920654297,"x":-309.75509643555},{"code":"711","y":595.60076904297,"x":-318.87194824219},{"code":"712","y":987.53381347656,"x":-75.180236816406},{"code":"713","y":823.92901611328,"x":-59.842529296875},{"code":"714","y":635.92706298828,"x":-218.04833984375},{"code":"715","y":576.41967773438,"x":-216.50061035156},{"code":"716","y":575.33795166016,"x":-130.02856445313},{"code":"717","y":1128.6805419922,"x":137.03723144531},{"code":"718","y":754.77294921875,"x":236.26745605469},{"code":"719","y":1275.2038574219,"x":701.95947265625},{"code":"720","y":1815.8348388672,"x":1260.0666503906},{"code":"721","y":1697.9013671875,"x":1561.1260986328},{"code":"722","y":1089.2875976563,"x":1368.2760009766},{"code":"723","y":755.73461914063,"x":1526.998046875},{"code":"724","y":2307.5356445313,"x":2103.1372070313},{"code":"725","y":1947.3375244141,"x":2232.0747070313},{"code":"726","y":1751.8459472656,"x":2287.455078125},{"code":"727","y":1591.4840087891,"x":2460.3469238281},{"code":"728","y":1543.1358642578,"x":2741.904296875},{"code":"601","y":-401.70004272461,"x":-2170.1918945313},{"code":"602","y":-320.08056640625,"x":-2095.6044921875},{"code":"603","y":-291.93835449219,"x":-1993.8319091797},{"code":"604","y":-482.5094909668,"x":-2045.9814453125},{"code":"605","y":-543.56640625,"x":-1966.7110595703},{"code":"606","y":-585.84185791016,"x":-1925.0095214844},{"code":"607","y":-623.39849853516,"x":-1879.5549316406},{"code":"608","y":-657.19378662109,"x":-1837.8598632813},{"code":"609","y":-697.56420898438,"x":-1789.5888671875},{"code":"610","y":-837.46893310547,"x":-1627.7038574219},{"code":"611","y":-1027.12109375,"x":-1616.0487060547},{"code":"612","y":-1212.0773925781,"x":-1831.5185546875},{"code":"613","y":-357.86618041992,"x":-1857.3803710938},{"code":"614","y":-437.69091796875,"x":-1872.9219970703},{"code":"615","y":-402.02850341797,"x":-1786.1512451172},{"code":"616","y":-471.51422119141,"x":-1708.7886962891},{"code":"617","y":-524.11822509766,"x":-1655.7954101563},{"code":"618","y":-610.51202392578,"x":-1541.7784423828},{"code":"619","y":-671.56671142578,"x":-1475.6530761719},{"code":"620","y":-702.57769775391,"x":-1434.8984375},{"code":"621","y":-748.59619140625,"x":-1380.9565429688},{"code":"622","y":-874.68371582031,"x":-1421.8699951172},{"code":"623","y":-930.08355712891,"x":-1506.8865966797},{"code":"624","y":-414.65509033203,"x":-1668.0230712891},{"code":"625","y":-426.90246582031,"x":-1557.7833251953},{"code":"626","y":-533.96380615234,"x":-1528.2631835938},{"code":"627","y":-544.32574462891,"x":-1441.5015869141},{"code":"628","y":-621.32452392578,"x":-1389.4838867188},{"code":"629","y":-672.78570556641,"x":-1392.0194091797},{"code":"630","y":-718.05810546875,"x":-1318.2437744141},{"code":"631","y":-285.54614257813,"x":-1684.1650390625},{"code":"632","y":-357.72055053711,"x":-1615.5467529297},{"code":"633","y":-271.11175537109,"x":-1560.7474365234},{"code":"634","y":-330.95303344727,"x":-1495.98046875},{"code":"635","y":-380.83596801758,"x":-1449.6312255859},{"code":"636","y":-484.35565185547,"x":-1376.4467773438},{"code":"637","y":-584.837890625,"x":-1304.0133056641},{"code":"638","y":-658.45391845703,"x":-1244.6477050781},{"code":"639","y":55.56721496582,"x":-1683.7844238281},{"code":"640","y":11.84765625,"x":-1635.1313476563},{"code":"641","y":-40.336242675781,"x":-1594.1485595703},{"code":"642","y":-98.619743347168,"x":-1560.8156738281},{"code":"643","y":-186.05480957031,"x":-1485.3469238281},{"code":"644","y":-254.33685302734,"x":-1433.6146240234},{"code":"645","y":-321.81958007813,"x":-1379.6147460938},{"code":"646","y":-418.45513916016,"x":-1309.513671875},{"code":"647","y":-462.97174072266,"x":-1124.4045410156},{"code":"648","y":121.23416137695,"x":-1531.9514160156},{"code":"649","y":18.461059570313,"x":-1554.6354980469},{"code":"650","y":28.417236328125,"x":-1479.9135742188},{"code":"651","y":-49.037536621094,"x":-1478.8175048828},{"code":"652","y":-116.52038574219,"x":-1420.2139892578},{"code":"653","y":-177.88665771484,"x":-1360.0806884766},{"code":"654","y":-229.92269897461,"x":-1302.8356933594},{"code":"655","y":-285.25299072266,"x":-1273.4992675781},{"code":"656","y":-377.30487060547,"x":-1232.4984130859},{"code":"657","y":-110.79866027832,"x":-1331.1934814453},{"code":"658","y":-185.93663024902,"x":-1178.2591552734},{"code":"659","y":-334.69082641602,"x":-1105.8634033203},{"code":"660","y":-416.73733520508,"x":-1027.3298339844},{"code":"661","y":328.47198486328,"x":-1283.0910644531},{"code":"662","y":54.734966278076,"x":-1189.9625244141},{"code":"663","y":-235.88246154785,"x":-1058.5267333984},{"code":"664","y":-276.53463745117,"x":-984.58038330078},{"code":"665","y":-353.22067260742,"x":-907.56323242188},{"code":"666","y":-427.62072753906,"x":-859.69799804688},{"code":"667","y":370.50329589844,"x":-1136.1538085938},{"code":"668","y":303.79638671875,"x":-1113.599609375},{"code":"669","y":-168.79837036133,"x":-935.3955078125},{"code":"670","y":-223.23612976074,"x":-876.76428222656},{"code":"671","y":-368.15795898438,"x":-777.52868652344},{"code":"672","y":-404.23446655273,"x":-701.28045654297},{"code":"673","y":363.22573852539,"x":-1037.5124511719},{"code":"674","y":304.93032836914,"x":-1037.9509277344},{"code":"675","y":228.22996520996,"x":-1031.5002441406},{"code":"676","y":149.99592590332,"x":-989.01538085938},{"code":"677","y":114.13235473633,"x":-968.74969482422},{"code":"678","y":62.731418609619,"x":-942.31646728516},{"code":"679","y":24.365104675293,"x":-919.74987792969},{"code":"680","y":-40.053043365479,"x":-861.88134765625},{"code":"681","y":-117.66655731201,"x":-825.42449951172},{"code":"682","y":-184.25291442871,"x":-783.73205566406},{"code":"683","y":-307.73989868164,"x":-709.78015136719},{"code":"684","y":386.08828735352,"x":-944.80895996094},{"code":"685","y":317.81390380859,"x":-968.25262451172},{"code":"686","y":203.56060791016,"x":-928.0654296875},{"code":"687","y":111.54509735107,"x":-902.43280029297},{"code":"688","y":52.463733673096,"x":-875.24945068359},{"code":"689","y":368.33419799805,"x":-874.88427734375},{"code":"690","y":314.63049316406,"x":-876.06768798828},{"code":"691","y":251.7301940918,"x":-831.26519775391},{"code":"692","y":175.02917480469,"x":-794.89886474609},{"code":"693","y":112.1298828125,"x":-801.43463134766},{"code":"694","y":-1.3726816177368,"x":-775.01611328125},{"code":"695","y":-66.570045471191,"x":-742.48254394531},{"code":"696","y":-143.27070617676,"x":-694.59838867188},{"code":"697","y":-259.83947753906,"x":-625.99719238281},{"code":"698","y":-344.18783569336,"x":-574.2646484375},{"code":"699","y":-417.8034362793,"x":-572.40075683594},{"code":"500","y":411.05798339844,"x":-816.73291015625},{"code":"501","y":329.6867980957,"x":-782.22149658203},{"code":"502","y":261.98202514648,"x":-750.27630615234},{"code":"503","y":180.52305603027,"x":-700.52392578125},{"code":"504","y":50.903945922852,"x":-695.24353027344},{"code":"505","y":-110.88291168213,"x":-599.31079101563},{"code":"506","y":-213.39039611816,"x":-539.40997314453},{"code":"507","y":-329.86734008789,"x":-458.75726318359},{"code":"508","y":-417.56732177734,"x":-478.90475463867},{"code":"509","y":-427.34091186523,"x":-402.49237060547},{"code":"510","y":-441.87588500977,"x":-303.77142333984},{"code":"511","y":428.39538574219,"x":-736.943359375},{"code":"512","y":332.8056640625,"x":-680.619140625},{"code":"513","y":299.62493896484,"x":-583.18212890625},{"code":"514","y":215.99865722656,"x":-594.54663085938},{"code":"515","y":156.23492431641,"x":-597.93444824219},{"code":"516","y":100.46592712402,"x":-597.35339355469},{"code":"517","y":44.716232299805,"x":-600.78454589844},{"code":"518","y":-46.86328125,"x":-472.81106567383},{"code":"519","y":-141.1171875,"x":-417.84649658203},{"code":"520","y":-244.76577758789,"x":-336.15817260742},{"code":"521","y":471.90353393555,"x":-625.01989746094},{"code":"522","y":385.64465332031,"x":-588.62451171875},{"code":"523","y":352.42486572266,"x":-492.50927734375},{"code":"524","y":283.33233642578,"x":-469.57983398438},{"code":"525","y":211.64205932617,"x":-487.58181762695},{"code":"526","y":158.52024841309,"x":-487.00375366211},{"code":"527","y":101.4418258667,"x":-469.28265380859},{"code":"528","y":41.685146331787,"x":-468.65365600586},{"code":"529","y":-85.742027282715,"x":-350.00003051758},{"code":"530","y":522.04522705078,"x":-495.36462402344},{"code":"531","y":476.88360595703,"x":-510.72842407227},{"code":"532","y":434.38583374023,"x":-478.30529785156},{"code":"533","y":375.96286010742,"x":-414.05786132813},{"code":"534","y":330.83197021484,"x":-410.84927368164},{"code":"535","y":281.62072753906,"x":-367.73321533203},{"code":"536","y":184.82946777344,"x":-399.0520324707},{"code":"537","y":97.2177734375,"x":-316.22943115234},{"code":"538","y":30.850257873535,"x":-312.99954223633},{"code":"539","y":-241.23577880859,"x":-194.30017089844},{"code":"540","y":-379.25860595703,"x":-87.543014526367},{"code":"541","y":505.8371887207,"x":-422.69653320313},{"code":"542","y":451.39288330078,"x":-388.92831420898},{"code":"543","y":407.55895996094,"x":-333.94604492188},{"code":"544","y":355.796875,"x":-308.14038085938},{"code":"545","y":296.03479003906,"x":-238.54907226563},{"code":"546","y":220.36071777344,"x":-263.16687011719},{"code":"547","y":184.46337890625,"x":-327.22750854492},{"code":"548","y":159.23709106445,"x":-270.91918945313},{"code":"549","y":528.10778808594,"x":-326.08764648438},{"code":"550","y":473.69287109375,"x":-263.13415527344},{"code":"551","y":380.75979614258,"x":-226.72441101074},{"code":"552","y":289.18664550781,"x":-153.16821289063},{"code":"553","y":225.45361328125,"x":-167.20080566406},{"code":"554","y":164.40895080566,"x":-162.67297363281},{"code":"555","y":50.27734375,"x":-172.71936035156},{"code":"556","y":-28.043262481689,"x":-189.40458679199},{"code":"557","y":490.81063842773,"x":-146.38990783691},{"code":"558","y":408.52575683594,"x":-157.74645996094},{"code":"559","y":342.14575195313,"x":-45.712036132813},{"code":"560","y":214.70751953125,"x":-50.461547851563},{"code":"561","y":144.36865234375,"x":-67.154541015625},{"code":"562","y":5.0144529342651,"x":-95.797630310059},{"code":"563","y":-48.079864501953,"x":-116.43576812744},{"code":"564","y":538.43688964844,"x":48.695190429688},{"code":"565","y":462.7607421875,"x":-46.297973632813},{"code":"566","y":391.09167480469,"x":45.85986328125},{"code":"567","y":295.50549316406,"x":151.28002929688},{"code":"568","y":165.45336914063,"x":85.49609375},{"code":"569","y":80.496955871582,"x":14.379183769226},{"code":"570","y":-42.911499023438,"x":-19.5556640625},{"code":"571","y":-195.55574035645,"x":-20.330459594727},{"code":"572","y":546.19665527344,"x":148.77624511719},{"code":"573","y":443.97045898438,"x":98.920288085938},{"code":"574","y":352.38659667969,"x":333.04968261719},{"code":"575","y":255.478515625,"x":305.72937011719},{"code":"576","y":110.80627441406,"x":253.21606445313},{"code":"577","y":45.401866912842,"x":98.846603393555},{"code":"578","y":17.024923324585,"x":220.99719238281},{"code":"579","y":-77.867950439453,"x":58.120056152344},{"code":"580","y":-113.89897155762,"x":132.86352539063},{"code":"581","y":-132.53469848633,"x":213.11917114258},{"code":"582","y":-176.59582519531,"x":312.00396728516},{"code":"583","y":-253.25666809082,"x":131.38232421875},{"code":"584","y":-305.43643188477,"x":266.38403320313},{"code":"585","y":-416.96405029297,"x":228.32000732422},{"code":"586","y":660.70788574219,"x":243.94610595703},{"code":"587","y":465.72290039063,"x":192.55560302734},{"code":"588","y":486.37939453125,"x":299.25537109375},{"code":"589","y":425.78894042969,"x":337.27014160156},{"code":"590","y":193.84533691406,"x":460.94189453125},{"code":"591","y":14.332397460938,"x":392.56890869141},{"code":"592","y":-13.026306152344,"x":564.986328125},{"code":"593","y":-111.27716064453,"x":466.33834838867},{"code":"594","y":-216.17413330078,"x":451.14453125},{"code":"595","y":-335.10650634766,"x":388.67727661133},{"code":"596","y":243.16967773438,"x":688.13818359375},{"code":"597","y":155.26257324219,"x":601.30517578125},{"code":"598","y":116.84545898438,"x":690.28015136719},{"code":"599","y":-169.75744628906,"x":567.26617431641},{"code":"400","y":131.34812927246,"x":1009.3156738281},{"code":"401","y":-33.256130218506,"x":1659.9888916016},{"code":"402","y":400.96273803711,"x":2572.1840820313},{"code":"403","y":-376.80261230469,"x":2507.4079589844},{"code":"404","y":-47.627777099609,"x":886.34252929688},{"code":"405","y":-123.52492523193,"x":799.28253173828},{"code":"406","y":-250.78694152832,"x":799.78082275391},{"code":"407","y":-304.49575805664,"x":713.90032958984},{"code":"408","y":-173.75784301758,"x":883.62060546875},{"code":"409","y":-223.99035644531,"x":956.50885009766},{"code":"410","y":-274.19442749023,"x":1078.4311523438},{"code":"411","y":-317.39031982422,"x":1158.3078613281},{"code":"412","y":-331.40765380859,"x":1093.4611816406},{"code":"413","y":-388.64819335938,"x":1025.1092529297},{"code":"414","y":-430.67269897461,"x":969.60015869141},{"code":"415","y":-473.81304931641,"x":910.70446777344},{"code":"416","y":-500.74810791016,"x":851.49780273438},{"code":"417","y":-553.27893066406,"x":832.13647460938},{"code":"418","y":-609.33093261719,"x":854.80963134766},{"code":"419","y":-639.69946289063,"x":907.86016845703},{"code":"420","y":-685.27478027344,"x":939.8984375},{"code":"421","y":-729.65747070313,"x":969.56402587891},{"code":"422","y":-771.72320556641,"x":1016.7731933594},{"code":"423","y":-798.59783935547,"x":1075.6462402344},{"code":"424","y":-798.59991455078,"x":1137.9982910156},{"code":"425","y":-395.87701416016,"x":1148.9865722656},{"code":"426","y":-453.09777832031,"x":1127.3017578125},{"code":"427","y":-478.78070068359,"x":1028.6091308594},{"code":"428","y":-518.48852539063,"x":970.76525878906},{"code":"429","y":-548.85009765625,"x":917.58422851563},{"code":"430","y":-602.59631347656,"x":981.11560058594},{"code":"431","y":-673.80572509766,"x":1024.8212890625},{"code":"432","y":-651.67102050781,"x":1133.890625},{"code":"433","y":-131.07865905762,"x":1009.4783935547},{"code":"434","y":-352.88928222656,"x":1262.1201171875},{"code":"435","y":-436.94595336914,"x":1240.4516601563},{"code":"436","y":-483.64242553711,"x":1233.9768066406},{"code":"437","y":-571.19836425781,"x":1219.3055419922},{"code":"438","y":-624.89605712891,"x":1226.8345947266},{"code":"439","y":-675.09429931641,"x":1240.1711425781},{"code":"440","y":-718.29010009766,"x":1239.5133056641},{"code":"441","y":-524.52587890625,"x":1325.2445068359},{"code":"442","y":-594.58868408203,"x":1316.3920898438},{"code":"443","y":-545.57263183594,"x":1392.7559814453},{"code":"444","y":-617.97320556641,"x":1383.9421386719},{"code":"445","y":-696.20989990234,"x":1343.5747070313},{"code":"446","y":-762.78662109375,"x":1311.3957519531},{"code":"447","y":-710.27087402344,"x":1408.767578125},{"code":"448","y":-775.66943359375,"x":1384.7670898438},{"code":"449","y":-997.48913574219,"x":1114.4642333984},{"code":"450","y":-684.07220458984,"x":2796.1713867188},{"code":"300","y":-1029.1674804688,"x":-1474.4401855469},{"code":"301","y":-986.41198730469,"x":-1411.9615478516},{"code":"302","y":-1057.6009521484,"x":-1361.8004150391},{"code":"303","y":-1151.2473144531,"x":-1329.8208007813},{"code":"304","y":-1247.7458496094,"x":-1315.2608642578},{"code":"305","y":-1343.1413574219,"x":-1282.4879150391},{"code":"306","y":-1425.3122558594,"x":-1248.8175048828},{"code":"307","y":-1493.1126708984,"x":-1197.3798828125},{"code":"308","y":-1549.4777832031,"x":-1154.4001464844},{"code":"309","y":-1611.0831298828,"x":-1113.0325927734},{"code":"310","y":-1661.9222412109,"x":-1076.4030761719},{"code":"311","y":-1789.0052490234,"x":-1195.6575927734},{"code":"312","y":-930.55511474609,"x":-1338.2587890625},{"code":"313","y":-1027.3132324219,"x":-1301.689453125},{"code":"314","y":-1127.6188964844,"x":-1264.3786621094},{"code":"315","y":-1220.0961914063,"x":-1244.1457519531},{"code":"316","y":-1314.6328125,"x":-1212.5389404297},{"code":"317","y":-1392.2125244141,"x":-1177.3619384766},{"code":"318","y":-1447.0068359375,"x":-1138.65625},{"code":"319","y":-1504.6511230469,"x":-1095.6893310547},{"code":"320","y":-1564.4343261719,"x":-1056.9562988281},{"code":"321","y":-1608.5399169922,"x":-1038.16796875},{"code":"322","y":-787.98168945313,"x":-1338.6042480469},{"code":"323","y":-842.04528808594,"x":-1295.6395263672},{"code":"324","y":-1050.41015625,"x":-1203.5720214844},{"code":"325","y":-1147.8741455078,"x":-1164.1453857422},{"code":"326","y":-1243.9017333984,"x":-1128.2504882813},{"code":"327","y":-1355.7624511719,"x":-1110.5888671875},{"code":"328","y":-1401.9780273438,"x":-1045.9108886719},{"code":"329","y":-1496.5798339844,"x":-1014.3173828125},{"code":"330","y":-1576.95703125,"x":-969.20568847656},{"code":"331","y":-773.15606689453,"x":-1273.9382324219},{"code":"332","y":-826.51312255859,"x":-1229.5341796875},{"code":"333","y":-916.15161132813,"x":-1188.6730957031},{"code":"334","y":-983.04528808594,"x":-1147.8227539063},{"code":"335","y":-1047.7581787109,"x":-1103.7037353516},{"code":"336","y":-1148.0686035156,"x":-1052.6170654297},{"code":"337","y":-1211.3900146484,"x":-1016.0389404297},{"code":"338","y":-1303.1352539063,"x":-977.30572509766},{"code":"339","y":-1419.7745361328,"x":-945.71728515625},{"code":"340","y":-1513.6687011719,"x":-911.27282714844},{"code":"341","y":-739.45391845703,"x":-1215.7504882813},{"code":"342","y":-789.98980712891,"x":-1163.5450439453},{"code":"343","y":-852.57861328125,"x":-1089.9608154297},{"code":"344","y":-938.64587402344,"x":-1063.3453369141},{"code":"345","y":-1006.9177246094,"x":-1016.7833862305},{"code":"346","y":-1107.9299316406,"x":-963.12231445313},{"code":"347","y":-1164.83984375,"x":-914.44989013672},{"code":"348","y":-1259.4299316406,"x":-892.11206054688},{"code":"349","y":-1458.5882568359,"x":-734.65557861328},{"code":"350","y":-756.03192138672,"x":-945.56298828125},{"code":"351","y":-889.03002929688,"x":-990.7685546875},{"code":"352","y":-930.48974609375,"x":-959.05487060547},{"code":"353","y":-992.16772460938,"x":-914.05560302734},{"code":"354","y":-1087.4909667969,"x":-850.46643066406},{"code":"355","y":-1217.6362304688,"x":-800.3779296875},{"code":"356","y":-1302.9851074219,"x":-712.58813476563},{"code":"357","y":-861.53546142578,"x":-888.98901367188},{"code":"358","y":-908.48413085938,"x":-798.34381103516},{"code":"359","y":-977.29077148438,"x":-807.25134277344},{"code":"360","y":-1035.8123779297,"x":-769.26702880859},{"code":"361","y":-1126.8742675781,"x":-712.06689453125},{"code":"362","y":-1183.0791015625,"x":-669.80010986328},{"code":"363","y":-1238.5677490234,"x":-634.66149902344},{"code":"364","y":-602.30310058594,"x":-806.42541503906},{"code":"365","y":-747.41845703125,"x":-799.17572021484},{"code":"366","y":-900.34143066406,"x":-694.83190917969},{"code":"367","y":-999.90704345703,"x":-696.64001464844},{"code":"368","y":-1107.3298339844,"x":-652.92785644531},{"code":"369","y":-608.15411376953,"x":-694.5859375},{"code":"370","y":-698.51239013672,"x":-694.25659179688},{"code":"371","y":-778.19567871094,"x":-693.95642089844},{"code":"372","y":-896.24670410156,"x":-562.8095703125},{"code":"373","y":-1025.0972900391,"x":-589.52954101563},{"code":"374","y":-1118.1575927734,"x":-581.38458251953},{"code":"375","y":-1227.7136230469,"x":-530.56713867188},{"code":"376","y":-613.31561279297,"x":-533.81781005859},{"code":"377","y":-751.38391113281,"x":-581.15228271484},{"code":"378","y":-745.66101074219,"x":-469.09088134766},{"code":"379","y":-968.99365234375,"x":-480.99627685547},{"code":"380","y":-595.65850830078,"x":-315.67556762695},{"code":"381","y":-750.01409912109,"x":-320.33477783203},{"code":"382","y":-923.56433105469,"x":-289.42834472656},{"code":"383","y":-1048.0467529297,"x":-311.15170288086},{"code":"384","y":-1338.1978759766,"x":-326.48291015625},{"code":"385","y":-1498.9143066406,"x":-329.00146484375},{"code":"386","y":-1644.8640136719,"x":-584.46209716797},{"code":"387","y":-1789.9696044922,"x":-579.78948974609},{"code":"388","y":-1718.1761474609,"x":-445.05377197266},{"code":"389","y":-601.87091064453,"x":-156.72050476074},{"code":"390","y":-778.25860595703,"x":-206.18516540527},{"code":"391","y":-838.03430175781,"x":-81.409629821777},{"code":"392","y":-985.25286865234,"x":-142.97489929199},{"code":"393","y":-1095.5246582031,"x":-166.83547973633},{"code":"394","y":-1169.5072021484,"x":-187.71894836426},{"code":"395","y":-640.91949462891,"x":-7.923168182373},{"code":"396","y":-569.12609863281,"x":196.48629760742},{"code":"397","y":-659.46252441406,"x":154.12565612793},{"code":"398","y":-751.23529052734,"x":126.70892333984},{"code":"399","y":-894.185546875,"x":68.73119354248},{"code":"200","y":-1062.0249023438,"x":8.5979700088501},{"code":"201","y":-585.22430419922,"x":330.74838256836},{"code":"202","y":-650.15972900391,"x":296.08462524414},{"code":"203","y":-716.81842041016,"x":272.53741455078},{"code":"204","y":-797.13336181641,"x":248.98770141602},{"code":"205","y":-920.1376953125,"x":193.83641052246},{"code":"206","y":-1077.30078125,"x":148.08184814453},{"code":"207","y":-627.24822998047,"x":455.06762695313},{"code":"208","y":-784.40118408203,"x":362.35665893555},{"code":"209","y":-905.72943115234,"x":349.94061279297},{"code":"210","y":-1000.5528564453,"x":328.09573364258},{"code":"211","y":-1089.4246826172,"x":263.54153442383},{"code":"212","y":-1088.5959472656,"x":352.72631835938},{"code":"213","y":-1157.7806396484,"x":321.50082397461},{"code":"214","y":-1160.3621826172,"x":401.33151245117},{"code":"215","y":-745.31518554688,"x":457.21755981445},{"code":"216","y":-902.50067138672,"x":452.47760009766},{"code":"217","y":-998.20635986328,"x":453.70645141602},{"code":"218","y":-1093.9069824219,"x":452.39398193359},{"code":"219","y":-544.27935791016,"x":728.31298828125},{"code":"220","y":-694.61840820313,"x":722.72320556641},{"code":"221","y":-749.31066894531,"x":723.95629882813},{"code":"222","y":-806.57281494141,"x":723.49822998047},{"code":"223","y":-899.6943359375,"x":721.2900390625},{"code":"224","y":-962.04711914063,"x":724.21478271484},{"code":"225","y":-1064.5396728516,"x":727.16473388672},{"code":"226","y":-1120.0651855469,"x":730.11486816406},{"code":"227","y":-793.83966064453,"x":832.13830566406},{"code":"228","y":-886.94445800781,"x":869.22790527344},{"code":"229","y":-956.98425292969,"x":875.58093261719},{"code":"230","y":-1042.4080810547,"x":882.78491210938},{"code":"231","y":-1133.8366699219,"x":909.62866210938},{"code":"101","y":-1295.8431396484,"x":-189.16575622559},{"code":"102","y":-1361.1325683594,"x":-199.61499023438},{"code":"103","y":-1439.3460693359,"x":-169.17350769043},{"code":"104","y":-1475.9370117188,"x":-130.83219909668},{"code":"105","y":-1511.0447998047,"x":-233.16012573242},{"code":"106","y":-1547.7369384766,"x":-186.84065246582},{"code":"107","y":-1603.7067871094,"x":-216.63500976563},{"code":"108","y":-1664.7286376953,"x":-217.02165222168},{"code":"109","y":-1725.0113525391,"x":-190.16036987305},{"code":"110","y":-1802.5281982422,"x":-111.65773010254},{"code":"111","y":-1852.7672119141,"x":-48.222949981689},{"code":"112","y":-1900.8654785156,"x":6.6181302070618},{"code":"113","y":-1950.4001464844,"x":63.619976043701},{"code":"114","y":-2000.5959472656,"x":109.64694213867},{"code":"115","y":-1398.8083496094,"x":-112.20764160156},{"code":"116","y":-1444.0457763672,"x":-88.230041503906},{"code":"117","y":-1531.6103515625,"x":-57.114601135254},{"code":"118","y":-1627.7312011719,"x":-123.47220611572},{"code":"119","y":-1665.7716064453,"x":-26.305255889893},{"code":"120","y":-1767.669921875,"x":-57.569725036621},{"code":"121","y":-1759.0911865234,"x":58.963958740234},{"code":"122","y":-1838.7308349609,"x":30.599849700928},{"code":"123","y":-1907.7905273438,"x":122.64105987549},{"code":"124","y":-1949.9763183594,"x":153.17626953125},{"code":"125","y":-1307.91015625,"x":-15.094520568848},{"code":"126","y":-1419.8579101563,"x":-7.4882292747498},{"code":"127","y":-1499.5307617188,"x":-11.558423995972},{"code":"128","y":-1582.7677001953,"x":70.528900146484},{"code":"129","y":-1691.8442382813,"x":145.45478820801},{"code":"130","y":-1780.08984375,"x":244.07884216309},{"code":"131","y":-1849.6875,"x":184.13423156738},{"code":"132","y":-2008.8780517578,"x":218.93841552734},{"code":"133","y":-1300.2211914063,"x":144.59962463379},{"code":"134","y":-1421.4899902344,"x":71.721168518066},{"code":"135","y":-1519.0656738281,"x":148.80706787109},{"code":"136","y":-1656.1225585938,"x":189.31973266602},{"code":"137","y":-1737.9329833984,"x":285.77676391602},{"code":"138","y":-1945.9948730469,"x":281.79132080078},{"code":"139","y":-2059.3486328125,"x":333.03134155273},{"code":"140","y":-1362.2398681641,"x":251.94816589355},{"code":"141","y":-1487.1766357422,"x":211.45455932617},{"code":"142","y":-1595.5262451172,"x":302.18811035156},{"code":"143","y":-1651.5061035156,"x":359.88793945313},{"code":"144","y":-1823.7247314453,"x":365.21774291992},{"code":"145","y":-1863.2066650391,"x":384.91525268555},{"code":"146","y":-2000.2724609375,"x":367.31072998047},{"code":"147","y":-2092.8442382813,"x":402.79830932617},{"code":"148","y":-1258.0133056641,"x":367.80456542969},{"code":"149","y":-1411.5725097656,"x":343.75473022461},{"code":"150","y":-1517.0571289063,"x":404.35696411133},{"code":"151","y":-1571.4686279297,"x":446.43557739258},{"code":"152","y":-1733.0635986328,"x":456.68957519531},{"code":"153","y":-1890.9268798828,"x":454.12655639648},{"code":"154","y":-1961.9718017578,"x":502.51138305664},{"code":"155","y":-1312.7757568359,"x":443.99783325195},{"code":"156","y":-1379.5179443359,"x":490.20916748047},{"code":"157","y":-1486.4421386719,"x":477.63247680664},{"code":"158","y":-1614.8630371094,"x":554.70751953125},{"code":"159","y":-1755.5095214844,"x":539.26306152344},{"code":"160","y":-1833.74609375,"x":534.57397460938},{"code":"161","y":-1909.0762939453,"x":577.22235107422},{"code":"162","y":-1287.4525146484,"x":753.47784423828},{"code":"163","y":-1384.0620117188,"x":751.55676269531},{"code":"164","y":-1665.7390136719,"x":783.65472412109},{"code":"165","y":-1814.6866455078,"x":752.93353271484},{"code":"166","y":-1967.1651611328,"x":732.77154541016},{"code":"167","y":-1328.3046875,"x":841.06085205078},{"code":"168","y":-1541.6588134766,"x":912.81323242188},{"code":"169","y":-1626.9591064453,"x":953.22534179688},{"code":"170","y":-1706.0562744141,"x":954.24676513672},{"code":"171","y":-1839.5078125,"x":892.42504882813},{"code":"172","y":-1989.8618164063,"x":876.90832519531},{"code":"173","y":-1831.7860107422,"x":1021.237487793},{"code":"174","y":-1991.3243408203,"x":1056.1282958984},{"code":"175","y":-1261.9050292969,"x":945.37976074219},{"code":"176","y":-1478.7492675781,"x":974.02563476563},{"code":"177","y":-1323.4599609375,"x":1167.0411376953},{"code":"178","y":-1492.2004394531,"x":1159.5765380859},{"code":"179","y":-1573.4239501953,"x":1146.4794921875},{"code":"180","y":-1628.5070800781,"x":1205.3771972656},{"code":"181","y":-1754.8991699219,"x":1216.984375},{"code":"182","y":-1883.3666992188,"x":1318.9350585938},{"code":"183","y":-1589.0551757813,"x":1258.5363769531},{"code":"184","y":-1690.0380859375,"x":1304.0158691406},{"code":"185","y":-1744.4010009766,"x":1340.3397216797},{"code":"186","y":-1503.7507324219,"x":1347.69921875},{"code":"187","y":-1563.7982177734,"x":1355.0493164063},{"code":"188","y":-1488.2723388672,"x":1423.1033935547},{"code":"189","y":-1667.5889892578,"x":1463.6748046875},{"code":"190","y":-1904.0637207031,"x":1487.2840576172},{"code":"191","y":-1002.7260742188,"x":1929.4655761719},{"code":"192","y":-1582.0932617188,"x":1714.1357421875},{"code":"193","y":-1688.6075439453,"x":1585.9519042969},{"code":"194","y":-1863.75390625,"x":1647.7005615234},{"code":"10","y":-2705.1564941406,"x":687.07366943359},{"code":"11","y":-2904.6411132813,"x":944.36273193359},{"code":"12","y":-2990.6240234375,"x":807.35510253906},{"code":"13","y":-3238.8312988281,"x":806.72766113281},{"code":"14","y":-3066.3818359375,"x":978.86743164063},{"code":"15","y":-3282.6921386719,"x":998.55688476563},{"code":"16","y":-3000.79296875,"x":1131.2945556641},{"code":"17","y":-2978.353515625,"x":1232.6954345703},{"code":"18","y":-3143.9951171875,"x":1213.3927001953},{"code":"19","y":-3272.7492675781,"x":1213.1508789063},{"code":"20","y":-2447.6203613281,"x":284.57476806641},{"code":"21","y":-2561.576171875,"x":314.84454345703},{"code":"22","y":-2753.4533691406,"x":345.09487915039},{"code":"23","y":-2968.2236328125,"x":252.94818115234},{"code":"24","y":-3118.5986328125,"x":230.67861938477},{"code":"25","y":-3228.7145996094,"x":235.11012268066},{"code":"26","y":-2615.921875,"x":496.35650634766},{"code":"27","y":-2775.2788085938,"x":577.41815185547},{"code":"28","y":-2977.8247070313,"x":558.623046875},{"code":"29","y":-3162.6711425781,"x":529.20104980469},{"code":"30","y":-2679.2045898438,"x":-151.14317321777},{"code":"31","y":-2482.7993164063,"x":8.0548686981201},{"code":"32","y":-2679.9594726563,"x":-42.670169830322},{"code":"33","y":-2406.2458496094,"x":125.01549530029},{"code":"34","y":-2578.5874023438,"x":103.35691833496},{"code":"35","y":-2692.7824707031,"x":56.17554473877},{"code":"36","y":-2470.1088867188,"x":210.39039611816},{"code":"37","y":-2711.9897460938,"x":209.27378845215},{"code":"38","y":-2936.818359375,"x":145.05467224121},{"code":"39","y":-3153.158203125,"x":139.71871948242},{"code":"40","y":-2656.0163574219,"x":-454.97610473633},{"code":"41","y":-2809.2387695313,"x":-483.02590942383},{"code":"42","y":-2644.0046386719,"x":-339.44714355469},{"code":"43","y":-2766.5698242188,"x":-342.82467651367},{"code":"44","y":-2371.0124511719,"x":-168.60151672363},{"code":"45","y":-2473.17578125,"x":-280.36245727539},{"code":"46","y":-2587.3823242188,"x":-236.79580688477},{"code":"47","y":-2659.7390136719,"x":-237.87594604492},{"code":"48","y":-2446.2788085938,"x":-125.50296783447},{"code":"49","y":-2585.3044433594,"x":-132.29989624023},{"code":"50","y":-2260.6943359375,"x":1218.2885742188},{"code":"51","y":-2389.1450195313,"x":1233.4946289063},{"code":"52","y":-2560.1733398438,"x":1262.8876953125},{"code":"53","y":-2077.64453125,"x":1383.1213378906},{"code":"54","y":-2142.9367675781,"x":1528.9184570313},{"code":"55","y":-2283.5036621094,"x":1619.3581542969},{"code":"56","y":-2605.6767578125,"x":1442.2821044922},{"code":"60","y":-2155.4575195313,"x":853.23693847656},{"code":"61","y":-2342.4645996094,"x":832.17572021484},{"code":"62","y":-2512.01953125,"x":865.92926025391},{"code":"63","y":-2145.572265625,"x":1003.2518310547},{"code":"64","y":-2272.0517578125,"x":996.4921875},{"code":"65","y":-2407.0234375,"x":979.04028320313},{"code":"66","y":-2513.568359375,"x":1026.2109375},{"code":"67","y":-2211.0874023438,"x":1108.9169921875},{"code":"68","y":-2326.1398925781,"x":1102.8514404297},{"code":"69","y":-2419.1809082031,"x":1084.7310791016},{"code":"70","y":-2234.6145019531,"x":-248.99447631836},{"code":"71","y":-2206.3369140625,"x":-46.829418182373},{"code":"72","y":-2135.2043457031,"x":136.44525146484},{"code":"73","y":-2203.4912109375,"x":300.81954956055},{"code":"74","y":-2188.2543945313,"x":468.12353515625},{"code":"75","y":-2181.0402832031,"x":554.84045410156},{"code":"76","y":-2346.5720214844,"x":550.06774902344},{"code":"77","y":-2154.216796875,"x":705.03173828125},{"code":"78","y":-2271.1315917969,"x":699.54187011719},{"code":"79","y":-2382.2238769531,"x":686.78234863281},{"code":"80","y":-2055.9750976563,"x":-726.21740722656},{"code":"81","y":-2261.4060058594,"x":-718.82543945313},{"code":"82","y":-2447.7976074219,"x":-685.59027099609},{"code":"83","y":-2606.6193847656,"x":-771.34912109375},{"code":"84","y":-2135.921875,"x":-591.43096923828},{"code":"85","y":-2304.93359375,"x":-579.3662109375},{"code":"86","y":-2199.0703125,"x":-468.21319580078},{"code":"87","y":-2273.2153320313,"x":-404.49740600586},{"code":"88","y":-1932.4854736328,"x":-333.16485595703},{"code":"89","y":-2188.0732421875,"x":-361.25445556641},{"code":"90","y":-2011.3282470703,"x":-1150.3947753906},{"code":"91","y":-2084.4724121094,"x":-1109.591796875},{"code":"92","y":-2175.3706054688,"x":-1025.4865722656},{"code":"93","y":-2646.8039550781,"x":-1303.173828125},{"code":"94","y":-1979.4582519531,"x":-1018.5178833008},{"code":"95","y":-2068.9506835938,"x":-951.47369384766},{"code":"96","y":-2145.671875,"x":-847.50787353516},{"code":"97","y":-2362.2272949219,"x":-879.15344238281},{"code":"98","y":-2606.4645996094,"x":-967.59759521484},{"code":"99","y":-2896.1499023438,"x":-962.28741455078}] diff --git a/resources/nearestpostal/old-postals.json b/resources/nearestpostal/old-postals.json new file mode 100644 index 000000000..d7d61bbe3 --- /dev/null +++ b/resources/nearestpostal/old-postals.json @@ -0,0 +1 @@ +[{"x":86.562103271484,"code":"943","y":6671.9248046875},{"x":149.82011413574,"code":"905","y":6626.5727539063},{"x":68.217254638672,"code":"907","y":6541.5356445313},{"x":-23.346632003784,"code":"909","y":6451.77734375},{"x":-108.99381256104,"code":"911","y":6375.0146484375},{"x":-172.21334838867,"code":"913","y":6297.0834960938},{"x":-233.10220336914,"code":"915","y":6239.2026367188},{"x":-297.5436706543,"code":"917","y":6178.9912109375},{"x":-382.01321411133,"code":"919","y":6093.9497070313},{"x":-461.79077148438,"code":"921","y":6014.802734375},{"x":-443.55471801758,"code":"931","y":6162.369140625},{"x":-458.41015625,"code":"933","y":6281.5859375},{"x":-385.89669799805,"code":"935","y":6359.4658203125},{"x":-270.35205078125,"code":"937","y":6443.2578125},{"x":-157.71032714844,"code":"939","y":6550.6806640625},{"x":-210.3383026123,"code":"951","y":6622.6640625},{"x":-31.549337387085,"code":"941","y":6656.8862304688},{"x":245.77008056641,"code":"906","y":6510.4443359375},{"x":429.27285766602,"code":"904","y":6529.2890625},{"x":110.38671112061,"code":"908","y":6400.533203125},{"x":-3.6271319389343,"code":"910","y":6303.6938476563},{"x":-96.377090454102,"code":"912","y":6208.0249023438},{"x":-217.46051025391,"code":"914","y":6110.0141601563},{"x":-676.19909667969,"code":"925","y":5801.8745117188},{"x":-706.35754394531,"code":"923","y":5616.5029296875},{"x":-519.33520507813,"code":"916","y":5395.7358398438},{"x":1303.0137939453,"code":"900","y":6595.7998046875},{"x":1603.3970947266,"code":"902","y":6491.8618164063},{"x":1886.0085449219,"code":"899","y":5079.6162109375},{"x":1788.5516357422,"code":"897","y":4989.876953125},{"x":1704.1827392578,"code":"892","y":4921.3110351563},{"x":1607.8809814453,"code":"891","y":4877.6196289063},{"x":1717.4890136719,"code":"890","y":4852.78125},{"x":1614.09765625,"code":"893","y":4765.3891601563},{"x":1723.0559082031,"code":"898","y":4775.953125},{"x":1617.3366699219,"code":"895","y":4668.5190429688},{"x":1778.3920898438,"code":"896","y":4640.166015625},{"x":1942.9837646484,"code":"894","y":4649.5942382813},{"x":2922.2026367188,"code":"888","y":4661.2055664063},{"x":2909.0971679688,"code":"886","y":4513.6303710938},{"x":2876.5305175781,"code":"887","y":4390.8217773438},{"x":2663.35546875,"code":"885","y":4275.1049804688},{"x":2495.06640625,"code":"884","y":4258.5727539063},{"x":2496.10546875,"code":"882","y":4106.2553710938},{"x":1715.6062011719,"code":"849","y":3870.0944824219},{"x":1550.8590087891,"code":"851","y":3813.3833007813},{"x":1377.8487548828,"code":"853","y":3716.5441894531},{"x":841.18804931641,"code":"855","y":3658.654296875},{"x":437.94216918945,"code":"857","y":3604.3444824219},{"x":852.81170654297,"code":"854","y":3571.2443847656},{"x":1376.8392333984,"code":"852","y":3637.2917480469},{"x":1578.0306396484,"code":"838","y":3601.8334960938},{"x":1627.2850341797,"code":"850","y":3800.0805664063},{"x":1908.0954589844,"code":"842","y":3882.6557617188},{"x":1944.0032958984,"code":"826","y":3822.4416503906},{"x":1987.0366210938,"code":"812","y":3773.9970703125},{"x":1905.9168701172,"code":"814","y":3727.8579101563},{"x":1836.1115722656,"code":"844","y":3851.7719726563},{"x":1753.9979248047,"code":"846","y":3802.1667480469},{"x":1798.6588134766,"code":"832","y":3744.2888183594},{"x":1831.5751953125,"code":"816","y":3686.3698730469},{"x":1729.3781738281,"code":"834","y":3699.3364257813},{"x":1662.4340820313,"code":"848","y":3747.6418457031},{"x":1754.8168945313,"code":"802","y":3257.6333007813},{"x":2098.8776855469,"code":"804","y":3171.4191894531},{"x":2162.4555664063,"code":"806","y":3330.73046875},{"x":2224.375,"code":"817","y":3513.6862792969},{"x":2746.0249023438,"code":"808","y":3538.4357910156},{"x":2674.5222167969,"code":"810","y":3319.9970703125},{"x":2559.47,"code":"891","y":4667.74},{"x":2449.01,"code":"893","y":4755.06},{"x":2324.4,"code":"895","y":4895.54},{"x":2125.37,"code":"892","y":4785.71},{"x":2443.46,"code":"897","y":4997.02},{"x":2330.8305664063,"code":"703","y":3029.5053710938},{"x":1966.3474121094,"code":"705","y":3046.0026855469},{"x":2108.5024414063,"code":"702","y":2949.1945800781},{"x":1704.8737792969,"code":"704","y":2835.9858398438},{"x":1262.6768798828,"code":"707","y":2723.7973632813},{"x":1186.4488525391,"code":"706","y":2611.5971679688},{"x":982.69891357422,"code":"708","y":2639.8837890625},{"x":1033.9487304688,"code":"709","y":2734.2944335938},{"x":694.43176269531,"code":"711","y":2748.4167480469},{"x":638.26849365234,"code":"710","y":2650.4138183594},{"x":452.25744628906,"code":"712","y":2587.8305664063},{"x":320.56289672852,"code":"714","y":2617.3139648438},{"x":230.18249511719,"code":"716","y":2583.0639648438},{"x":181.10194396973,"code":"713","y":2732.98046875},{"x":41.148876190186,"code":"715","y":2813.2275390625},{"x":-82.323280334473,"code":"717","y":2881.6723632813},{"x":121.24057769775,"code":"880","y":3062.2751464844},{"x":-113.98404693604,"code":"860","y":3575.7802734375},{"x":-53.25651550293,"code":"859","y":3689.0830078125},{"x":-2558.0139160156,"code":"719","y":2363.4548339844},{"x":2635.4721679688,"code":"701","y":2717.583984375},{"x":2517.9304199219,"code":"700","y":2568.7998046875},{"x":3512.3359375,"code":"818","y":3631.5275878906},{"x":-3263.6594238281,"code":"7068","y":1249.2192382813},{"x":-3194.7641601563,"code":"7069","y":1083.8669433594},{"x":-3302.8774414063,"code":"7067","y":1013.0196533203},{"x":-3140.6274414063,"code":"7065","y":747.37512207031},{"x":-3063.3779296875,"code":"7064","y":493.53082275391},{"x":-2945.9887695313,"code":"7066","y":438.0143737793},{"x":-3135.5329589844,"code":"7063","y":295.15551757813},{"x":-3042.9306640625,"code":"7062","y":69.664245605469},{"x":-2253.9182128906,"code":"7061","y":417.80316162109},{"x":-2194.9106445313,"code":"5172","y":-389.21865844727},{"x":-2016.1505126953,"code":"5171","y":-319.5969543457},{"x":-1823.2379150391,"code":"5145","y":-366.82104492188},{"x":-1630.048828125,"code":"5150","y":19.896743774414},{"x":-1539.7915039063,"code":"5151","y":124.91970062256},{"x":-1467.2502441406,"code":"5148","y":-43.919147491455},{"x":-1563.5693359375,"code":"5149","y":-94.713539123535},{"x":-1345.8419189453,"code":"5159","y":-145.51358032227},{"x":-1481.0773925781,"code":"5170","y":-179.78578186035},{"x":-1575.0087890625,"code":"5160","y":-264.79959106445},{"x":-1673.6806640625,"code":"5147","y":-387.5774230957},{"x":-1933.5513916016,"code":"5146","y":-561.177734375},{"x":-1653.2725830078,"code":"5173","y":-511.61639404297},{"x":-1561.8610839844,"code":"5152","y":-436.09411621094},{"x":-1498.7950439453,"code":"5153","y":-341.65521240234},{"x":-1505.5197753906,"code":"5174","y":-537.69158935547},{"x":-1392.8609619141,"code":"5176","y":-473.94982910156},{"x":-994.71197509766,"code":"5158","y":-274.48294067383},{"x":-1309.8743896484,"code":"5175","y":-570.92510986328},{"x":-782.87133789063,"code":"5154","y":-364.40274047852},{"x":-697.36480712891,"code":"5155","y":-412.85241699219},{"x":-571.72589111328,"code":"5156","y":-422.34417724609},{"x":-382.32586669922,"code":"5157","y":-427.07189941406},{"x":-1832.23828125,"code":"5045","y":-681.77423095703},{"x":-1641.64453125,"code":"5043","y":-836.45263671875},{"x":-1577.3637695313,"code":"5041","y":-973.44439697266},{"x":-1408.0444335938,"code":"5039","y":-1031.2971191406},{"x":-1298.9030761719,"code":"5023","y":-1142.2720947266},{"x":-1286.6090087891,"code":"5025","y":-1234.3831787109},{"x":-1273.1279296875,"code":"5027","y":-1324.1220703125},{"x":-1188.7946777344,"code":"5035","y":-1385.5386962891},{"x":-1149.3059082031,"code":"5033","y":-1446.9387207031},{"x":-1161.3114013672,"code":"5031","y":-1546.1472167969},{"x":-1107.6895751953,"code":"5029","y":-1626.4276123047},{"x":-1055.2192382813,"code":"5047","y":-1576.8664550781},{"x":-1008.6729125977,"code":"5013","y":-1506.0666503906},{"x":-1036.4976806641,"code":"5011","y":-1411.6555175781},{"x":-1148.1166992188,"code":"5037","y":-1262.9499511719},{"x":-1305.8084716797,"code":"5021","y":-1020.9360351563},{"x":-1347.8031005859,"code":"5019","y":-928.85711669922},{"x":-1442.8961181641,"code":"5017","y":-658.61346435547},{"x":-1264.1005859375,"code":"5014","y":-661.01092529297},{"x":-1191.6004638672,"code":"5012","y":-740.14709472656},{"x":-1082.5029296875,"code":"5000","y":-851.12213134766},{"x":-1280.3474121094,"code":"5015","y":-821.63592529297},{"x":-1203.0778808594,"code":"5001","y":-919.63604736328},{"x":-1149.4498291016,"code":"5003","y":-1003.4691772461},{"x":-1107.5891113281,"code":"5005","y":-1114.4835205078},{"x":-1052.7346191406,"code":"5007","y":-1206.6138916016},{"x":-927.08453369141,"code":"5006","y":-1142.8999023438},{"x":-976.15661621094,"code":"5004","y":-1049.6359863281},{"x":-1038.2449951172,"code":"5002","y":-958.74676513672},{"x":-831.11737060547,"code":"5008","y":-1224.3748779297},{"x":-987.62860107422,"code":"5009","y":-1307.0388183594},{"x":-729.24530029297,"code":"5010","y":-1440.48046875},{"x":-544.54803466797,"code":"5018","y":-1253.9721679688},{"x":-495.61187744141,"code":"5020","y":-988.37481689453},{"x":-491.57867431641,"code":"5038","y":-710.96923828125},{"x":-557.17596435547,"code":"5040","y":-621.27764892578},{"x":-707.77569580078,"code":"5042","y":-618.93872070313},{"x":-805.25079345703,"code":"5044","y":-616.58874511719},{"x":-962.95916748047,"code":"5032","y":-750.00250244141},{"x":-811.35357666016,"code":"5028","y":-891.71655273438},{"x":-717.61596679688,"code":"5026","y":-1003.8762817383},{"x":-694.80377197266,"code":"5034","y":-737.12493896484},{"x":-584.52288818359,"code":"5036","y":-767.84436035156},{"x":-581.65368652344,"code":"5022","y":-877.64154052734},{"x":-811.37286376953,"code":"5030","y":-744.24719238281},{"x":-1302.6306152344,"code":"5016","y":-612.07220458984},{"x":-327.88272094727,"code":"3200","y":-617.73034667969},{"x":-337.98959350586,"code":"3201","y":-744.0693359375},{"x":-303.22891235352,"code":"3206","y":-971.94708251953},{"x":-336.95086669922,"code":"3217","y":-1043.9637451172},{"x":-206.60340881348,"code":"3202","y":-773.65264892578},{"x":-193.12828063965,"code":"3203","y":-628.49157714844},{"x":-36.721061706543,"code":"3204","y":-640.13073730469},{"x":-98.784126281738,"code":"3207","y":-831.39990234375},{"x":-146.66743469238,"code":"3205","y":-1012.0247802734},{"x":-6.8592858314514,"code":"3212","y":-1054.5499267578},{"x":59.746517181396,"code":"3208","y":-888.09155273438},{"x":123.98522186279,"code":"3209","y":-687.40545654297},{"x":262.61029052734,"code":"3210","y":-747.658203125},{"x":182.95169067383,"code":"3211","y":-933.11267089844},{"x":135.08255004883,"code":"3213","y":-1073.6359863281},{"x":260.72418212891,"code":"3216","y":-1088.9971923828},{"x":301.37420654297,"code":"3214","y":-994.55541992188},{"x":316.84811401367,"code":"3215","y":-919.19842529297},{"x":434.6047668457,"code":"3224","y":-624.68597412109},{"x":446.94073486328,"code":"3218","y":-746.29705810547},{"x":450.97717285156,"code":"3219","y":-909.21655273438},{"x":449.12454223633,"code":"3220","y":-997.79150390625},{"x":454.33575439453,"code":"3222","y":-1089.8833007813},{"x":1023.6906738281,"code":"6049","y":137.22387695313},{"x":950.99084472656,"code":"6048","y":45.117008209229},{"x":862.94348144531,"code":"6047","y":-38.719150543213},{"x":771.35192871094,"code":"6045","y":-115.4857635498},{"x":866.32965087891,"code":"6046","y":-167.44415283203},{"x":1028.5715332031,"code":"6042","y":-149.74128723145},{"x":833.61846923828,"code":"6044","y":-257.19128417969},{"x":944.42395019531,"code":"6043","y":-217.06642150879},{"x":1123.1990966797,"code":"6040","y":-310.36340332031},{"x":1259.4490966797,"code":"6041","y":-332.83016967773},{"x":935.16058349609,"code":"6039","y":-425.7350769043},{"x":1135.1995849609,"code":"6032","y":-431.65249633789},{"x":1021.1713256836,"code":"6033","y":-488.36627197266},{"x":920.10662841797,"code":"6037","y":-543.91052246094},{"x":833.27398681641,"code":"6038","y":-517.97772216797},{"x":899.89617919922,"code":"6027","y":-646.68035888672},{"x":1088.0942382813,"code":"6026","y":-794.26922607422},{"x":1302.2657470703,"code":"6030","y":-763.60534667969},{"x":1328.7569580078,"code":"6031","y":-624.34423828125},{"x":1349.3546142578,"code":"6035","y":-519.28039550781},{"x":1243.6350097656,"code":"6034","y":-455.54959106445},{"x":1216.9826660156,"code":"6036","y":-578.32775878906},{"x":695.56658935547,"code":"6029","y":-754.56396484375},{"x":824.76574707031,"code":"6028","y":-785.29437255859},{"x":665.91009521484,"code":"6016","y":-919.88311767578},{"x":861.22680664063,"code":"6019","y":-916.35815429688},{"x":718.88787841797,"code":"6017","y":-1112.3721923828},{"x":853.96844482422,"code":"6018","y":-1095.8721923828},{"x":1123.6522216797,"code":"6025","y":-1006.1775512695},{"x":863.11303710938,"code":"6015","y":-1271.8859863281},{"x":723.14910888672,"code":"6014","y":-1317.9416503906},{"x":1166.3436279297,"code":"6020","y":-1523.3665771484},{"x":730.02954101563,"code":"6011","y":-1665.0665283203},{"x":894.63238525391,"code":"6012","y":-1661.5582275391},{"x":1015.5518798828,"code":"6013","y":-1688.7526855469},{"x":1252.6959228516,"code":"6021","y":-1707.7277832031},{"x":1360.6160888672,"code":"6022","y":-1745.5275878906},{"x":1230.0933837891,"code":"6023","y":-1789.23046875},{"x":1291.3160400391,"code":"6024","y":-1848.3137207031},{"x":1007.3212890625,"code":"6004","y":-1815.2941894531},{"x":731.57684326172,"code":"6010","y":-1830.6472167969},{"x":884.37677001953,"code":"6005","y":-1938.0804443359},{"x":1011.2045898438,"code":"6003","y":-1998.3082275391},{"x":972.08813476563,"code":"6006","y":-2150.6887207031},{"x":826.66424560547,"code":"6001","y":-2155.9091796875},{"x":829.28668212891,"code":"6002","y":-2327.7109375},{"x":958.46563720703,"code":"6007","y":-2321.8471679688},{"x":1113.6383056641,"code":"6009","y":-2264.0024414063},{"x":898.09838867188,"code":"6008","y":-2506.0053710938},{"x":495.47009277344,"code":"3700","y":-2182.3471679688},{"x":681.35766601563,"code":"3708","y":-2342.9074707031},{"x":484.73245239258,"code":"3701","y":-2612.1166992188},{"x":543.08093261719,"code":"3702","y":-2759.7192382813},{"x":505.80743408203,"code":"3703","y":-3089.125},{"x":1215.8486328125,"code":"3704","y":-3145.81640625},{"x":1209.2521972656,"code":"3705","y":-3280.4331054688},{"x":804.85455322266,"code":"3706","y":-2971.1442871094},{"x":214.95008850098,"code":"3601","y":-2435.2082519531},{"x":302.84631347656,"code":"3602","y":-2578.0971679688},{"x":311.59912109375,"code":"3603","y":-2754.0026855469},{"x":229.44653320313,"code":"3604","y":-3229.8137207031},{"x":129.58811950684,"code":"3605","y":-3137.7666015625},{"x":-155.05639648438,"code":"3608","y":-2574.6887207031},{"x":-31.786952972412,"code":"3600","y":-2480.2556152344},{"x":-373.63177490234,"code":"3606","y":-2636.1281738281},{"x":-505.33993530273,"code":"3607","y":-2867.5385742188},{"x":-994.02850341797,"code":"2011","y":-2987.5791015625},{"x":-889.05065917969,"code":"2012","y":-2840.0317382813},{"x":-854.32867431641,"code":"2001","y":-2760.9528808594},{"x":-1085.2026367188,"code":"2010","y":-2769.263671875},{"x":-1242.9083251953,"code":"2000","y":-2693.7443847656},{"x":-943.73431396484,"code":"2002","y":-2654.7915039063},{"x":-1016.409362793,"code":"2004","y":-2595.7719726563},{"x":-929.73431396484,"code":"2003","y":-2511.9802246094},{"x":-880.81207275391,"code":"2008","y":-2397.4858398438},{"x":-636.61480712891,"code":"2013","y":-2388.0776367188},{"x":-729.38702392578,"code":"2014","y":-2259.4194335938},{"x":-871.71197509766,"code":"2017","y":-2143.7553710938},{"x":-1028.2277832031,"code":"2016","y":-1999.7720947266},{"x":-1110.3527832031,"code":"2015","y":-2155.6333007813},{"x":-1167.7115478516,"code":"2006","y":-2325.6499023438},{"x":-1275.8255615234,"code":"2005","y":-2371.69140625},{"x":-1121.8416748047,"code":"2000-A","y":-2494.4777832031},{"x":-1061.1062011719,"code":"2007","y":-2382.3471679688},{"x":-580.79534912109,"code":"2203","y":-2142.7387695313},{"x":-590.90936279297,"code":"2201","y":-1772.0554199219},{"x":-584.51171875,"code":"2202","y":-1632.7944335938},{"x":-469.50967407227,"code":"2205","y":-1726.0638427734},{"x":-335.61196899414,"code":"2200","y":-2017.697265625},{"x":-127.336769104,"code":"2200-B","y":-2125.1303710938},{"x":-120.91368103027,"code":"2204-E","y":-2200.7053222656},{"x":-94.442344665527,"code":"2200-A","y":-2004.7775878906},{"x":-339.09243774414,"code":"4001","y":-1337.6887207031},{"x":-196.89817810059,"code":"4002","y":-1330.6166992188},{"x":-25.861728668213,"code":"4012","y":-1318.8470458984},{"x":137.55200195313,"code":"4013","y":-1305.8637695313},{"x":289.19641113281,"code":"4027","y":-1268.1220703125},{"x":449.06018066406,"code":"4030","y":-1354.3304443359},{"x":536.94622802734,"code":"4040","y":-1630.5998535156},{"x":536.25463867188,"code":"4035","y":-1797.0582275391},{"x":520.25738525391,"code":"4036","y":-1944.6691894531},{"x":401.54931640625,"code":"4037","y":-2056.8527832031},{"x":307.59085083008,"code":"4020","y":-2071.0666503906},{"x":254.96038818359,"code":"4019","y":-1973.1140136719},{"x":150.91586303711,"code":"4017-B","y":-1937.7692871094},{"x":38.102264404297,"code":"4017-A","y":-1955.5081787109},{"x":-31.021728515625,"code":"4017","y":-1897.7026367188},{"x":-127.3274307251,"code":"4029","y":-1808.0275878906},{"x":-236.60643005371,"code":"4004","y":-1558.9526367188},{"x":-329.37832641602,"code":"4003","y":-1494.0693359375},{"x":-141.15655517578,"code":"4026","y":-1448.0583496094},{"x":-39.136783599854,"code":"4007","y":-1420.9471435547},{"x":231.7325592041,"code":"4022","y":-1369.0054931641},{"x":318.41607666016,"code":"4023","y":-1442.2443847656},{"x":390.94958496094,"code":"4031","y":-1423.3608398438},{"x":428.03280639648,"code":"4032","y":-1513.1220703125},{"x":391.93807983398,"code":"4033","y":-1640.6499023438},{"x":439.65762329102,"code":"4034","y":-1737.4555664063},{"x":443.7272644043,"code":"4038","y":-1900.4166259766},{"x":180.27984619141,"code":"4016","y":-1860.3359375},{"x":36.757709503174,"code":"4015","y":-1782.4331054688},{"x":-26.464784622192,"code":"4006","y":-1675.0192871094},{"x":-127.49253082275,"code":"4005","y":-1608.9387207031},{"x":-30.159061431885,"code":"4011","y":-1526.3109130859},{"x":189.91856384277,"code":"4009","y":-1495.6553955078},{"x":305.44079589844,"code":"4021","y":-1619.7443847656},{"x":269.78140258789,"code":"4018","y":-1762.5219726563},{"x":147.50756835938,"code":"4008","y":-1671.6469726563},{"x":73.660415649414,"code":"4010","y":-1593.7331542969},{"x":331.54348754883,"code":"4025","y":-1841.7645263672},{"x":-1340.8931884766,"code":"7080","y":55.768138885498},{"x":-1332.0999755859,"code":"7054","y":320.19476318359},{"x":-1120.2449951172,"code":"7055","y":375.63632202148},{"x":-1117.3529052734,"code":"7056","y":303.58642578125},{"x":-891.33966064453,"code":"7045","y":-233.57189941406},{"x":-791.64801025391,"code":"7044","y":-195.82203674316},{"x":-884.37860107422,"code":"7046","y":-28.210813522339},{"x":-934.62835693359,"code":"7048","y":197.23640441895},{"x":-814.89788818359,"code":"7047","y":168.86380004883},{"x":-786.03167724609,"code":"7051","y":-5.8719277381897},{"x":-705.05114746094,"code":"7043","y":-148.79655456543},{"x":-634.74389648438,"code":"7040","y":-253.51084899902},{"x":-489.00610351563,"code":"7039","y":-327.92465209961},{"x":-546.36187744141,"code":"7041","y":-203.99140930176},{"x":-622.41693115234,"code":"7042","y":-103.6701965332},{"x":-699.83142089844,"code":"7052","y":68.661376953125},{"x":-700.49530029297,"code":"7049","y":172.53916931152},{"x":-601.97882080078,"code":"7050","y":198.47250366211},{"x":-599.10394287109,"code":"7053","y":63.867004394531},{"x":-373.92034912109,"code":"7038","y":-352.91354370117},{"x":-343.90069580078,"code":"7037","y":-250.24136352539},{"x":-387.09524536133,"code":"7032","y":-109.76367950439},{"x":-505.70803833008,"code":"7033","y":-36.610698699951},{"x":-483.45938110352,"code":"7034","y":71.944763183594},{"x":-412.13150024414,"code":"7030","y":191.13635253906},{"x":-333.69821166992,"code":"7031","y":60.058700561523},{"x":-221.66746520996,"code":"7036","y":-262.27194213867},{"x":-198.73419189453,"code":"7035","y":-137.1608581543},{"x":-152.12828063965,"code":"7023","y":-6.0297069549561},{"x":-183.48976135254,"code":"7029","y":182.83909606934},{"x":-61.367477416992,"code":"7028","y":167.45297241211},{"x":128.05473327637,"code":"7017","y":302.01406860352},{"x":61.293598175049,"code":"7018","y":147.34739685059},{"x":-29.117416381836,"code":"7024","y":-53.394104003906},{"x":45.76037979126,"code":"7025","y":-78.191307067871},{"x":-39.895267486572,"code":"7060","y":-186.81079101563},{"x":-82.533332824707,"code":"7057","y":-339.13973999023},{"x":67.906692504883,"code":"7058","y":-367.48083496094},{"x":110.71346282959,"code":"7020","y":-241.10014343262},{"x":135.33264160156,"code":"7026","y":-107.76362609863},{"x":205.72372436523,"code":"7027","y":-138.50616455078},{"x":219.2215423584,"code":"7019","y":58.603042602539},{"x":283.47610473633,"code":"7016","y":254.5747833252},{"x":301.69372558594,"code":"7015","y":364.34201049805},{"x":462.74099731445,"code":"7010","y":180.13360595703},{"x":406.57727050781,"code":"7012","y":49.082622528076},{"x":396.46041870117,"code":"7013","y":-38.310829162598},{"x":301.36041259766,"code":"7022","y":-177.65530395508},{"x":254.66317749023,"code":"7021","y":-296.93588256836},{"x":219.76881408691,"code":"7059","y":-411.46365356445},{"x":397.36877441406,"code":"7003","y":-324.13861083984},{"x":426.21887207031,"code":"7004","y":-233.24697875977},{"x":453.88812255859,"code":"7005","y":-108.11085510254},{"x":541.74627685547,"code":"7007","y":-5.4414224624634},{"x":575.82409667969,"code":"7011","y":158.64753723145},{"x":676.68243408203,"code":"7008","y":123.18357849121},{"x":723.22680664063,"code":"7009","y":244.74751281738},{"x":517.16015625,"code":"7002","y":-456.53591918945},{"x":626.36499023438,"code":"7000","y":-432.90869140625},{"x":704.80194091797,"code":"7001","y":-538.01922607422},{"x":671.29907226563,"code":"7014","y":475.06979370117},{"x":-2031.9427490234,"code":"600","y":296.28656005859},{"x":-1765.7897949219,"code":"601","y":175.83366394043},{"x":-1526.7915039063,"code":"602","y":408.36981201172},{"x":-1777.7299804688,"code":"604","y":326.8932800293},{"x":-1818.568359375,"code":"605","y":426.13464355469},{"x":-1630.3571777344,"code":"606","y":220.6837310791},{"x":-1932.0871582031,"code":"607","y":389.46981811523},{"x":-2060.2443847656,"code":"608","y":483.89483642578},{"x":-2013.6732177734,"code":"609","y":642.04449462891},{"x":-1896.2899169922,"code":"610","y":603.04187011719},{"x":-1404.6536865234,"code":"611","y":423.55599975586},{"x":-1825.6228027344,"code":"612","y":811.95281982422},{"x":-1529.9758300781,"code":"613","y":580.53961181641},{"x":-1409.0480957031,"code":"615","y":589.94470214844},{"x":-1334.1472167969,"code":"616","y":522.60955810547},{"x":-1213.1936035156,"code":"617","y":618.21862792969},{"x":-1180.7901611328,"code":"618","y":510.76986694336},{"x":-1299.5041503906,"code":"671","y":689.01409912109},{"x":-1144.3671875,"code":"622","y":424.55694580078},{"x":-1051.7818603516,"code":"620","y":544.96691894531},{"x":-1025.3001708984,"code":"621","y":430.43618774414},{"x":-1126.3487548828,"code":"614","y":726.71984863281},{"x":-1097.4809570313,"code":"670","y":811.7001953125},{"x":-996.61737060547,"code":"669","y":744.40856933594},{"x":-942.98980712891,"code":"668","y":668.84454345703},{"x":-923.57574462891,"code":"619","y":479.91137695313},{"x":-744.80084228516,"code":"628","y":334.69186401367},{"x":-743.13812255859,"code":"629","y":431.45672607422},{"x":-813.44805908203,"code":"623","y":485.75592041016},{"x":-863.67840576172,"code":"624","y":558.94451904297},{"x":-794.69256591797,"code":"630","y":654.52508544922},{"x":-813.05993652344,"code":"664","y":784.36145019531},{"x":-715.24786376953,"code":"667","y":623.75579833984},{"x":-675.76232910156,"code":"625","y":536.38952636719},{"x":-620.96557617188,"code":"626","y":451.35147094727},{"x":-594.49719238281,"code":"627","y":366.35159301758},{"x":-560.90936279297,"code":"632","y":576.48889160156},{"x":-627.74792480469,"code":"631","y":646.11163330078},{"x":-679.16296386719,"code":"665","y":783.04473876953},{"x":-538.17877197266,"code":"662","y":790.08337402344},{"x":-568.36474609375,"code":"663","y":713.31457519531},{"x":-462.79760742188,"code":"661","y":713.30029296875},{"x":-419.76467895508,"code":"660","y":641.28625488281},{"x":-449.95892333984,"code":"659","y":590.48620605469},{"x":-497.86734008789,"code":"633","y":514.89447021484},{"x":-483.19989013672,"code":"634","y":314.15603637695},{"x":-352.80349731445,"code":"637","y":338.94183349609},{"x":-279.12045288086,"code":"640","y":464.03915405273},{"x":-347.24758911133,"code":"658","y":528.89184570313},{"x":-274.19216918945,"code":"657","y":571.341796875},{"x":-226.9351348877,"code":"655","y":652.71105957031},{"x":-165.02833557129,"code":"656","y":560.61657714844},{"x":-161.6508026123,"code":"641","y":470.90316772461},{"x":-204.84515380859,"code":"636","y":383.53909301758},{"x":-266.88397216797,"code":"635","y":311.486328125},{"x":-70.392669677734,"code":"638","y":348.0475769043},{"x":10.413029670715,"code":"639","y":324.38928222656},{"x":-44.553020477295,"code":"642","y":440.04504394531},{"x":70.449249267578,"code":"643","y":430.55578613281},{"x":23.713340759277,"code":"644","y":513.18902587891},{"x":176.52671813965,"code":"645","y":460.02529907227},{"x":134.53395080566,"code":"646","y":541.45837402344},{"x":292.0491027832,"code":"647","y":478.88092041016},{"x":238.22354125977,"code":"648","y":638.22509765625},{"x":238.73492431641,"code":"649","y":750.35308837891},{"x":-80.695175170898,"code":"650","y":809.37780761719},{"x":-161.62283325195,"code":"651","y":866.01678466797},{"x":-197.71865844727,"code":"652","y":991.13940429688},{"x":-98.047714233398,"code":"653","y":998.18347167969},{"x":152.7631072998,"code":"654","y":1113.8444824219}] diff --git a/resources/nearestpostal/sv.lua b/resources/nearestpostal/sv.lua new file mode 100644 index 000000000..7e4ef67c4 --- /dev/null +++ b/resources/nearestpostal/sv.lua @@ -0,0 +1,35 @@ +-- version check +Citizen.CreateThread( + function() + local vRaw = LoadResourceFile(GetCurrentResourceName(), 'version.json') + if vRaw and config.versionCheck then + local v = json.decode(vRaw) + PerformHttpRequest( + 'https://raw.githubusercontent.com/blockba5her/nearest-postal/master/version.json', + function(code, res, headers) + if code == 200 then + local rv = json.decode(res) + if rv.version ~= v.version then + print( + ([[ + +------------------------------------------------------- +nearest-postal +UPDATE: %s AVAILABLE +CHANGELOG: %s +------------------------------------------------------- +]]):format( + rv.version, + rv.changelog + ) + ) + end + else + print('nearest-postal unable to check version') + end + end, + 'GET' + ) + end + end +) diff --git a/resources/nearestpostal/version.json b/resources/nearestpostal/version.json new file mode 100644 index 000000000..430cbe7de --- /dev/null +++ b/resources/nearestpostal/version.json @@ -0,0 +1,4 @@ +{ + "version": "1.4", + "changelog": "Performance Improvements; Config Updates; Bug Fixes" +} diff --git a/resources/security_cameras_V2/LICENSE b/resources/security_cameras_V2/LICENSE new file mode 100644 index 000000000..e62ec04cd --- /dev/null +++ b/resources/security_cameras_V2/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/resources/security_cameras_V2/README.md b/resources/security_cameras_V2/README.md new file mode 100644 index 000000000..710c7ec42 --- /dev/null +++ b/resources/security_cameras_V2/README.md @@ -0,0 +1,21 @@ +### 📷 [LX Security] 📷 + +[![Discord](https://i.gyazo.com/thumb/1200/0d6e0d0855dc4a9c1210b2009b51c14a-png.jpg)](https://discord.gg/hPcvqtr) +
+ +**LICENSE:** [Please read the license before using this.] + +GNU General Public License 3.0
+ +This work is licensed under a GNU General Public License 3.0. +
+ +**Features:** +- Camera menu with categories, to view all of the cameras at a specific location. +- Aces Support. +- Export so you can get the closest camera to you, which can be implemented into other systems, such as dispatch alerts. +- Several camera features such as rotating, zooming, and location cycling. +- Config options to disable the minimap & your server's HUD when using a camera. + +**Dependencies:** +xMenu by Xander1998 - https://github.com/xander1998/xmenu diff --git a/resources/security_cameras_V2/client/classes/camera.lua b/resources/security_cameras_V2/client/classes/camera.lua new file mode 100644 index 000000000..6d7bd5b28 --- /dev/null +++ b/resources/security_cameras_V2/client/classes/camera.lua @@ -0,0 +1,159 @@ +local CameraShakes = { + Hand = "HAND_SHAKE", + SmallExplosion = "SMALL_EXPLOSION_SHAKE", + MediumExplosion = "MEDIUM_EXPLOSION_SHAKE", + LargeExplosion = "LARGE_EXPLOSION_SHAKE", + Jolt = "JOLT_SHAKE", + Vibrate = "VIBRATE_SHAKE", + RoadVibration = "ROAD_VIBRATION_SHAKE", + Drunk = "DRUNK_SHAKE", + SkyDiving = "SKY_DIVING_SHAKE", + FamilyDrugTrip = "FAMILYS_DRUG_TRIP_SHAKE", + DeathFail = "DEATH_FAIL_IN_EFFECT_SHAKE" +} + +Camera = {} +Camera.__index = Camera + +function Camera.New() + local newCamera = {} + setmetatable(newCamera, Camera) + + newCamera.Handle = CreateCam("DEFAULT_SCRIPTED_CAMERA", true) + + return newCamera +end + +function Camera:IsActive() + return IsCamActive(self.Handle) +end + +function Camera:Render(render, ease, time) + RenderScriptCams(render, ease, time, 1, 1) +end + +function Camera:SetActive(bool) + SetCamActive(self.Handle, bool) +end + +function Camera:GetPosition() + return GetCamCoord(self.Handle) +end + +function Camera:SetPosition(pos) + SetCamCoord(self.Handle, pos.x, pos.y, pos.z) +end + +function Camera:GetRotation() + return GetCamRot(self.Handle, 2) +end + +function Camera:SetRotation(rot) + SetCamRot(self.Handle, rot.x, rot.y, rot.z, 2) +end + +function Camera:GetFOV() + return GetCamFov(self.Handle) +end + +function Camera:SetFOV(fov) + SetCamFov(self.Handle, fov) +end + +function Camera:GetNearClip() + return GetCamNearClip(self.Handle) +end + +function Camera:SetNearClip(clip) + SetCamNearClip(self.Handle, clip) +end + +function Camera:GetFarClip() + return GetCamFarClip(self.Handle) +end + +function Camera:SetFarClip(clip) + SetCamFarClip(self.Handle, clip) +end + +function Camera:SetNearDOF(dof) + SetCamNearDof(self.Handle, dof) +end + +function Camera:GetFarDOF() + return GetCamFarDof(self.Handle) +end + +function Camera:SetFarDOF(dof) + SetCamFarDof(self.Handle, dof) +end + +function Camera:SetDOFStrength(strength) + SetCamDofStrength(self.Handle, strength) +end + +function Camera:SetMotionBlur(strength) + SetCamMotionBlurStrength(self.Handle, strength) +end + +function Camera:Shake(shakeType, amplitude) + local shake = CameraShakes[shakeType] + if shake then + ShakeCam(self.Handle, shake, amplitude) + end +end + +function Camera:StopShake() + StopCamShaking(self.Handle, true) +end + +function Camera:IsShaking() + return IsCamShaking(self.Handle) +end + +function Camera:SetShakeAmplitude(amplitude) + SetCamShakeAmplitude(self.Handle, amplitude) +end + +function Camera:PointAtEntity(entity, offset) + PointCamAtEntity(self.Handle, entity, offset.x, offset.y, offset.z, true) +end + +function Camera:PointAtBone(ped, bone, offset) + PointCamAtPedBone(self.Handle, ped, GetPedBoneIndex(ped, bone), offset.x, offset.y, offset.z, true) +end + +function Camera:StopPoint() + StopCamPointing(self.Handle) +end + +function Camera:InterpTo(to, duration, easePos, easeRot) + SetCamActiveWithInterp(to, self.Handle, duration, easePos, easeRot) +end + +function Camera:IsInterpolating() + return IsCamInterpolating(self.Handle) +end + +function Camera:AttachToEntity(entity, offset) + AttachCamToEntity(self.Handle, entity, offset.x, offset.y, offset.z, true) +end + +function Camera:AttachToBone(ped, bone, offset) + AttachCamToPedBone(self.Handle, ped, GetPedBoneIndex(ped, bone), offset.x, offset.y, offset.z, true) +end + +function Camera:Detach() + DetachCam(self.Handle) +end + +function Camera:Delete() + DestroyCam(self.Handle, false) + RenderScriptCams(false, true, 500, true, true) + VehicleCamera = nil + CreatedCamera = false +end + +function Camera:Exists() + DoesCamExist(self.Handle) +end \ No newline at end of file diff --git a/resources/security_cameras_V2/client/classes/menu.lua b/resources/security_cameras_V2/client/classes/menu.lua new file mode 100644 index 000000000..38121627d --- /dev/null +++ b/resources/security_cameras_V2/client/classes/menu.lua @@ -0,0 +1,47 @@ +xMenu = {} +xMenu.__index = xMenu + +function xMenu.New(name, color) + local newMenu = {} + setmetatable(newMenu, xMenu) + + newMenu.Name = name + newMenu.Resource = GetCurrentResourceName() + newMenu.Handle = exports["xmenu"]:AddMenu(name, newMenu.Resource) + newMenu.Color = color + + return newMenu +end + +function xMenu:IsAnyMenuOpen() + return exports["xmenu"]:IsAnyMenuOpen() +end + +function xMenu:OpenMenu() + exports["xmenu"]:OpenMenu(self.Handle, self.Color) +end + +function xMenu:CloseMenu() + exports["xmenu"]:CloseMenu() +end + +function xMenu:BindSubMenu(name) + local newHandle = exports["xmenu"]:AddSubMenu(name, self.Handle, self.Resource) + return xSubMenu.New(name, newHandle) +end + +function xMenu:BindButton(name, callback) + exports["xmenu"]:AddButton(name, self.Handle, callback, self.Resource) +end + +function xMenu:BindCheckbox(name, callback) + exports["xmenu"]:AddCheckbox(name, self.Handle, callback, self.Resource) +end + +function xMenu:BindList(name, list, callback) + exports["xmenu"]:AddList(name, self.Handle, list, callback, self.Resource) +end + +function xMenu:ClearMenu() + exports["xmenu"]:ClearMenu(self.Handle) +end \ No newline at end of file diff --git a/resources/security_cameras_V2/client/classes/submenu.lua b/resources/security_cameras_V2/client/classes/submenu.lua new file mode 100644 index 000000000..717bde0b9 --- /dev/null +++ b/resources/security_cameras_V2/client/classes/submenu.lua @@ -0,0 +1,30 @@ +xSubMenu = {} +xSubMenu.__index = xMenu + +function xSubMenu.New(name, handle) + local newMenu = {} + setmetatable(newMenu, xMenu) + + newMenu.Name = name + newMenu.Handle = handle + newMenu.Resource = GetCurrentResourceName() + + return newMenu +end + +function xSubMenu:BindSubMenu(name) + local newHandle = exports["xmenu"]:AddSubMenu(name, self.Handle, self.Resource) + return xSubMenu.New(name, newHandle) +end + +function xMenu:BindButton(name, callback) + exports["xmenu"]:AddButton(name, self.Handle, callback, self.Resource) +end + +function xMenu:BindCheckbox(name, callback) + exports["xmenu"]:AddCheckbox(name, self.Handle, callback, self.Resource) +end + +function xMenu:BindList(name, list, callback) + exports["xmenu"]:AddList(name, self.Handle, list, callback, self.Resource) +end \ No newline at end of file diff --git a/resources/security_cameras_V2/client/classes/utils.lua b/resources/security_cameras_V2/client/classes/utils.lua new file mode 100644 index 000000000..69d557dbd --- /dev/null +++ b/resources/security_cameras_V2/client/classes/utils.lua @@ -0,0 +1,173 @@ +Utils = {} + +function Utils.GenerateUUID() + local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + return string.gsub(template, '[xy]', function (c) + local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb) + return string.format('%x', v) + end) +end + +function Utils.RequestCamera(name, camera) + if CCTV_Config.HideRadar then + DisplayRadar(false) + end + + if CCTV_Config.HideHUD then + Utils.ToggleHUD(true) + end + + camNumber = tonumber(camera) + if inCam then + inCam = false + PlaySoundFrontend(-1, "HACKING_SUCCESS", false) + Wait(250) + ClearPedTasks(PlayerPedId()) + else + if camNumber > 0 and camNumber < #CCTV_Config.Cameras + 1 then + exports["xmenu"]:CloseMenu() + PlaySoundFrontend(-1, "HACKING_SUCCESS", false) + Utils.UseCamera(name, camNumber) + end + end +end + +function Utils.ChangeCamera(name, camera) + changedCamera = true + RenderScriptCams(false, false, 0, 1, 0) + DestroyCam(cctvCam, false) + camNumber = tonumber(camera) + Utils.UseCamera(name, camera) +end + +function Utils.UseCamera(locationName, cameraUsed) + camFov = 110.0 + local location = nil + for k, v in pairs(CCTV_Config.Cameras) do + if locationName == v.name and cameraUsed == v.camera then + location = v.location + currentCamIndex = k + end + end + + if not inCam then + cameraScaleform = RequestScaleformMovie("TRAFFIC_CAM") -- Traffic Cam UI Header + while not HasScaleformMovieLoaded(cameraScaleform) do + Citizen.Wait(0) + end + PushScaleformMovieFunction(cameraScaleform, "PLAY_CAM_MOVIE") + PopScaleformMovieFunctionVoid() + scaleformState = "LOADED_SCALEFORM" + end + + cctvCam = CreateCam("DEFAULT_SCRIPTED_CAMERA", true) + SetCamCoord(cctvCam, location.x, location.y, location.z + 1.2) + SetCamRot(cctvCam, -15.0,0.0, location.w) + SetCamFov(cctvCam, camFov) + RenderScriptCams(true, false, 0, 1, 0) + SetFocusArea(location.x, location.y, location.z, 0.0, 0.0, 0.0) + inCam = true + if not changedCamera then + Wait(3000) -- Wait until scaleform has loaded fully and you can use the camera + scaleformState = "CAMERA_READY" + end +end + +function Utils.CloseCamera() + DestroyCam(cctvCam, false) + RenderScriptCams(false, false, 0, 1, 0) + ClearFocus() + ClearTimecycleModifier() + SetScaleformMovieAsNoLongerNeeded(cameraScaleform) + SetScaleformMovieAsNoLongerNeeded(controlsScaleform) + SetNightvision(false) + SetSeethrough(false) + cctvCam = 0 + cameraScaleform = nil + controlsScaleform = nil + currentCamIndex = 0 + inCam = false + scaleformState = "UNLOADED" + changedCamera = false +end + +function Utils.GetCamAmountByName(buildingName) + local cameraCount = 0 + for k, v in pairs(CCTV_Config.Cameras) do + if v.name == buildingName then + cameraCount = cameraCount + 1 + end + end + return cameraCount +end + +function Utils.CreateInstructions(passedScaleform, buttonsMessages) + local tempScaleform = RequestScaleformMovie(passedScaleform) + while not HasScaleformMovieLoaded(tempScaleform) do + Citizen.Wait(0) + end + PushScaleformMovieFunction(tempScaleform, "CLEAR_ALL") + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(tempScaleform, "SET_CLEAR_SPACE") + PushScaleformMovieFunctionParameterInt(200) + PopScaleformMovieFunctionVoid() + + local buttonCount = 0 + for k, v in pairs(buttonsMessages) do + PushScaleformMovieFunction(tempScaleform, "SET_DATA_SLOT") + PushScaleformMovieFunctionParameterInt(buttonCount) + Button(GetControlInstructionalButton(2, v.button, true)) + ButtonMessage(v.name) + PopScaleformMovieFunctionVoid() + buttonCount = buttonCount + 1 + end + + PushScaleformMovieFunction(tempScaleform, "DRAW_INSTRUCTIONAL_BUTTONS") + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(tempScaleform, "SET_BACKGROUND_COLOUR") + PushScaleformMovieFunctionParameterInt(0) + PushScaleformMovieFunctionParameterInt(0) + PushScaleformMovieFunctionParameterInt(0) + PushScaleformMovieFunctionParameterInt(70) + PopScaleformMovieFunctionVoid() + + return tempScaleform +end + +function ButtonMessage(text) + BeginTextCommandScaleformString("STRING") + AddTextComponentScaleform(text) + EndTextCommandScaleformString() +end + +function Button(ControlButton) + N_0xe83a3e3557a56640(ControlButton) +end + +Utils.ToggleHUD = function(toggledHud) + if toggledHud then + -- toggle it here + else + -- turn it off here + end +end + +Utils.HasPermission = function() + if CCTV_Config.UseAces then + return hasPermission + end + + return true +end + +Utils.Notification = function(msg, flash, saveToBrief, hudColorIndex) + local notify = GetCurrentResourceName()..':notification' + AddTextEntry(notify, msg) + BeginTextCommandThefeedPost(notify) + if hudColorIndex then ThefeedNextPostBackgroundColor(hudColorIndex) end + EndTextCommandThefeedPostTicker(flash or false, saveToBrief or true) + + msg, hudColorIndex, flash, saveToBrief, notify = nil, nil, nil, nil, nil +end \ No newline at end of file diff --git a/resources/security_cameras_V2/client/main.lua b/resources/security_cameras_V2/client/main.lua new file mode 100644 index 000000000..68feb5293 --- /dev/null +++ b/resources/security_cameras_V2/client/main.lua @@ -0,0 +1,35 @@ +-- Variables +local firstSpawn = false +hasPermission = false + +-- Events +AddEventHandler("onClientResourceStart", function(resourceName) -- When the resource is restarted, run this to get player permissions. + if GetCurrentResourceName() == resourceName then + if CCTV_Config.UseAces then + TriggerServerEvent("LX_Security_Server:GetPermissions") + end + + Utils.Notification("[~y~LX Security Loaded~w~]\n\nCreated By ~g~Luceefer#9955~w~!") + end +end) + +AddEventHandler("playerSpawned", function() -- When you first spawn in, run this to get player permissions. + if not firstSpawn then + if CCTV_Config.UseAces then + TriggerServerEvent("LX_Security_Server:GetPermissions") + end + + firstSpawn = true + Utils.Notification("[~y~LX Security Loaded~w~]\n\nCreated By ~g~Luceefer#9955~w~!") + end +end) + +-- Threads +CreateThread(function() + if CCTV_Config.UseAces then + RegisterNetEvent("LX_Security_Client:SetPermission") + AddEventHandler("LX_Security_Client:SetPermission", function(hasPerms) -- Set your permission on the client. + hasPermission = hasPerms + end) + end +end) \ No newline at end of file diff --git a/resources/security_cameras_V2/client/managers/camera.lua b/resources/security_cameras_V2/client/managers/camera.lua new file mode 100644 index 000000000..0f3dfc290 --- /dev/null +++ b/resources/security_cameras_V2/client/managers/camera.lua @@ -0,0 +1,245 @@ +local selectedLocation = nil +local selectedCamera = nil +AddedLocations = {} +scaleformState = "UNLOADED" +changedCamera = false + +-- Commands +RegisterCommand("cctv", function(source, args, raw) + local ped = PlayerPedId() + if Utils.HasPermission() then + AddedLocations = {} + local CameraMenu = xMenu.New("San Andreas CCTV Systems") + local GenStoreMenu = CameraMenu:BindSubMenu("General Stores") + local HwyMenu = CameraMenu:BindSubMenu("Traffic Cameras") + local EntertainmentMenu = CameraMenu:BindSubMenu("Entertainment") + local BankMenu = CameraMenu:BindSubMenu("Banks") + local HospitalMenu = CameraMenu:BindSubMenu("Hospitals") + local PoliceStationsMenu = CameraMenu:BindSubMenu("Police Stations") + + for k, v in pairs(CCTV_Config.Cameras) do + if v.type == "General Stores" then + if AddedLocations[v.name] == nil then + AddedLocations[v.name] = GenStoreMenu:BindSubMenu(v.name) + end + + if AddedLocations[v.name] then + AddedLocations[v.name]:BindButton(v.name .. " #" .. v.camera, function() + selectedLocation = v.name + selectedCamera = v.camera + currentCamIndex = k + Utils.RequestCamera(v.name, v.camera) + end) + end + end + + if v.type == "Traffic Cameras" then + if AddedLocations[v.name] == nil then + AddedLocations[v.name] = HwyMenu:BindSubMenu(v.name) + end + + if AddedLocations[v.name] then + AddedLocations[v.name]:BindButton(v.name .. " #" .. v.camera, function() + selectedLocation = v.name + selectedCamera = v.camera + currentCamIndex = k + Utils.RequestCamera(v.name, v.camera) + end) + end + end + + if v.type == "Entertainment" then + if AddedLocations[v.name] == nil then + AddedLocations[v.name] = EntertainmentMenu:BindSubMenu(v.name) + end + + if AddedLocations[v.name] then + AddedLocations[v.name]:BindButton(v.name .. " #" .. v.camera, function() + selectedLocation = v.name + selectedCamera = v.camera + currentCamIndex = k + Utils.RequestCamera(v.name, v.camera) + end) + end + end + + if v.type == "Banks" then + if AddedLocations[v.name] == nil then + AddedLocations[v.name] = BankMenu:BindSubMenu(v.name) + end + + if AddedLocations[v.name] then + AddedLocations[v.name]:BindButton(v.name .. " #" .. v.camera, function() + selectedLocation = v.name + selectedCamera = v.camera + currentCamIndex = k + Utils.RequestCamera(v.name, v.camera) + end) + end + end + + if v.type == "Hospitals" then + if AddedLocations[v.name] == nil then + AddedLocations[v.name] = HospitalMenu:BindSubMenu(v.name) + end + + if AddedLocations[v.name] then + AddedLocations[v.name]:BindButton(v.name .. " #" .. v.camera, function() + selectedLocation = v.name + selectedCamera = v.camera + currentCamIndex = k + Utils.RequestCamera(v.name, v.camera) + end) + end + end + + if v.type == "Police Stations" then + if AddedLocations[v.name] == nil then + AddedLocations[v.name] = PoliceStationsMenu:BindSubMenu(v.name) + end + + if AddedLocations[v.name] then + AddedLocations[v.name]:BindButton(v.name .. " #" .. v.camera, function() + selectedLocation = v.name + selectedCamera = v.camera + currentCamIndex = k + Utils.RequestCamera(v.name, v.camera) + end) + end + end + end + + CameraMenu:OpenMenu() + else + if CCTV_Config.ShowNoPerms then + Utils.Notification("[~y~LX Security~w~]\n\n~r~You don't have permission to do this") + end + end +end) + +currentCamIndex = 0 +switchingCam = false +inCam = false +cctvCam = 0 +cameraScaleform = nil +controlsScaleform = nil +camFov = 110.0 +local drawnControls = false + +Citizen.CreateThread(function () + while true do + Wait(0) + + if inCam then + + if IsDisabledControlJustPressed(0, 194) then -- Backspace + Utils.CloseCamera() + AddedLocations = {} + if CCTV_Config.HideRadar then + DisplayRadar(true) + end + + if CCTV_Config.HideHUD then + Utils.ToggleHUD(true) + end + end + + if currentCamIndex > 0 then + if CCTV_Config.Cameras[currentCamIndex].canRotate then + local rotation = GetCamRot(cctvCam, 2) + + if IsDisabledControlPressed(1, 108) then -- Num 4 (Rotate Left) + SetCamRot(cctvCam, rotation.x, 0.0, rotation.z + 0.3, 2) + --end + end + + if IsDisabledControlPressed(1, 107) then -- Num 6 (Rotate Right) + SetCamRot(cctvCam, rotation.x, 0.0, rotation.z - 0.3, 2) + end + + if IsDisabledControlPressed(1, 111) then -- Num 8 (Up) + if rotation.x <= 0.0 then + SetCamRot(cctvCam, rotation.x + 0.3, 0.0, rotation.z, 2) + end + end + + if IsDisabledControlPressed(1, 110) then -- Num 5 (Down) + if rotation.x <= 50.0 and rotation.x >= -88.0 then + SetCamRot(cctvCam, rotation.x - 0.3, 0.0, rotation.z, 2) + end + end + end + + if IsDisabledControlJustPressed(0, 175) then -- Next Camera + switchingCam = true + local AMOUNT_OF_CAMERAS = Utils.GetCamAmountByName(AddedLocations[selectedLocation].Name) + if selectedCamera + 1 > AMOUNT_OF_CAMERAS then + selectedCamera = 1 + else + selectedCamera = selectedCamera + 1 + end + + Utils.ChangeCamera(selectedLocation, selectedCamera) + end + + if IsDisabledControlJustPressed(0, 174) then -- Previous Camera + switchingCam = true + local AMOUNT_OF_CAMERAS = Utils.GetCamAmountByName(AddedLocations[selectedLocation].Name) + if selectedCamera - 1 <= 0 then + selectedCamera = AMOUNT_OF_CAMERAS + else + selectedCamera = selectedCamera - 1 + end + + Utils.ChangeCamera(selectedLocation, selectedCamera) + end + + if IsDisabledControlJustPressed(0, 241) then -- Zoom In + if camFov > -1.0 then + camFov = camFov - 3.0 + SetCamFov(cctvCam, camFov) + end + end + + if IsDisabledControlJustPressed(0, 242) then -- Zoom Out + if camFov < 110.0 then + camFov = camFov + 3.0 + SetCamFov(cctvCam, camFov) + end + end + end + end + + -- Handle Camera Scaleform and Timecycle + if inCam then + local location = CCTV_Config.Cameras[currentCamIndex].location + SetTimecycleModifier(CCTV_Config.TimecycleTypes[CCTV_Config.Cameras[currentCamIndex].cameraType]) + SetTimecycleModifierStrength(1.0) + PushScaleformMovieFunction(cameraScaleform, "SET_ALT_FOV_HEADING") + -- PushScaleformMovieFunctionParameterFloat(GetEntityCoords(location.w).z) + PushScaleformMovieFunctionParameterFloat(location.w) + PushScaleformMovieFunctionParameterFloat(1.0) + PushScaleformMovieFunctionParameterFloat(GetCamRot(cctvCam, 2).z) + PopScaleformMovieFunctionVoid() + DrawScaleformMovieFullscreen(cameraScaleform, 255, 255, 255, 255) + DisableAllControlActions(0) + end + + -- Handle Controls Scaleform + if inCam and scaleformState == "CAMERA_READY" then + local buttonsMessage = { + {name = "Exit", button = 194}, + {name = "Previous Camera", button = 174}, + {name = "Next Camera", button = 175}, + {name = "Zoom Out", button = 242}, + {name = "Zoom In", button = 241}, + {name = "Down", button = 112}, + {name = "Up", button = 111}, + {name = "Right", button = 109}, + {name = "Left", button = 108} + } + controlsScaleform = Utils.CreateInstructions("instructional_buttons", buttonsMessage) + DrawScaleformMovieFullscreen(controlsScaleform, 255, 255, 255, 255, 0) + end + end +end) \ No newline at end of file diff --git a/resources/security_cameras_V2/client/managers/exports.lua b/resources/security_cameras_V2/client/managers/exports.lua new file mode 100644 index 000000000..d9cdc27bf --- /dev/null +++ b/resources/security_cameras_V2/client/managers/exports.lua @@ -0,0 +1,24 @@ +-- Get Closest Camera +function GetClosestCam(ped) + local closest, closestDist + if ped == nil then + ped = PlayerPedId() + end + + local pedCoords = GetEntityCoords(ped, false) + + for k, v in pairs(CCTV_Config.Cameras) do + local camCoords = v.location + local dist = GetDistanceBetweenCoords(pedCoords, camCoords, false) -- False means not to use the Z coord + if not closestDist or dist < closestDist then + closest = v.name + closestDist = dist + end + end + + if closest then + return closest + else + return nil + end +end \ No newline at end of file diff --git a/resources/security_cameras_V2/fxmanifest.lua b/resources/security_cameras_V2/fxmanifest.lua new file mode 100644 index 000000000..94a9efa8c --- /dev/null +++ b/resources/security_cameras_V2/fxmanifest.lua @@ -0,0 +1,21 @@ +-- Manifest data +fx_version "adamant" +game "gta5" + +-- Resource Information +description "A security system to help you monitor all criminal activity in your server. // Modified by PhantomProductions" +version "v1.0.0" +url "https://github.com/aka-lucifer/lx_security" + +-- Resource Data +shared_script"shared/shared.lua" + +client_scripts { + "client/classes/*.lua", + "client/managers/*.lua", + "client/*.lua", +} + +server_script "server/main.lua" + +export "GetClosestCam" \ No newline at end of file diff --git a/resources/security_cameras_V2/server/main.lua b/resources/security_cameras_V2/server/main.lua new file mode 100644 index 000000000..383e93d06 --- /dev/null +++ b/resources/security_cameras_V2/server/main.lua @@ -0,0 +1,6 @@ +-- Events +RegisterNetEvent("LX_Security_Server:GetPermissions") +AddEventHandler("LX_Security_Server:GetPermissions", function() + local src = source + TriggerClientEvent("LX_Security_Client:SetPermission", src, IsPlayerAceAllowed(src, "lx-security")) +end) \ No newline at end of file diff --git a/resources/security_cameras_V2/shared/shared.lua b/resources/security_cameras_V2/shared/shared.lua new file mode 100644 index 000000000..d8d4a5962 --- /dev/null +++ b/resources/security_cameras_V2/shared/shared.lua @@ -0,0 +1,358 @@ +CCTV_Config = {} + +CCTV_Config.HideRadar = true -- Controls if the minimap will be disabled when in a camera. +CCTV_Config.HideHUD = true -- Controls if the HUD will be disabled when in a camera. (Reference Utils.ToggleHUD() in Utils.lua) + +CCTV_Config.UseAces = false -- Controls if you're using default permissions or not + +CCTV_Config.ShowNoPerms = true -- Controls whether or not to display the no permissions error + +CCTV_Config.Cameras = { -- All of the logged cameras + {location = vector4(34.12, -1348.48, 30.5, 59.20), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Innocence Boulevard)", camera = 1}, + {location = vector4(24.22, -1342.64, 30.5, 235.62), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Innocence Boulevard)", camera = 2}, + {location = vector4(30.99, -1341.13, 30.52, 49.42), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Innocence Boulevard)", camera = 3}, + {location = vector4(381.34, 323.01, 104.69, 34.69), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Clinton Avenue)", camera = 1}, + {location = vector4(373.53, 331.02, 104.69, 209.73), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Clinton Avenue)", camera = 2}, + {location = vector4(380.57, 330.62, 104.69, 32.19), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Clinton Avenue)", camera = 3}, + {location = vector4(2558.81, 390.11, 109.85, 143.36), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Palomino Freeway)", camera = 1}, + {location = vector4(2552.54, 380.92, 109.85, 313.33), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Palomino Freeway)", camera = 2}, + {location = vector4(2551.39, 387.73, 109.85, 135.86), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Palomino Freeway)", camera = 3}, + {location = vector4(-3036.09, 585.05, 9.6, 319.68), canRotate = true, cameraType = "low", type = "General Stores", name = "General Store (Inseno Road)", camera = 1}, + {location = vector4(-3040.77, 594.27, 9.08, 158.74), canRotate = true, cameraType = "medium", type = "General Stores", name = "General Store (Inseno Road)", camera = 2}, + {location = vector4(-3043.44, 582.91, 9.08, 336.27), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Inseno Road)", camera = 3}, + {location = vector4(-3046.84, 588.96, 9.08, 158.71), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Inseno Road)", camera = 4}, + {location = vector4(-3240.23, 1009.21, 13.90, 129.43), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Barbereno Road)", camera = 1}, + {location = vector4(-3246.92, 1000.3, 13.90, 311.88), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Barbereno Road)", camera = 2}, + {location = vector4(-3247.78, 1007.18, 14.01, 136.92), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Barbereno Road)", camera = 3}, + {location = vector4(548.98, 2674.68, 43.16, 35.94), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Harmony)", camera = 1}, + {location = vector4(537.4, 2671.29, 43.79, 128.4), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Harmony)", camera = 2}, + {location = vector4(539.14, 2671.23, 43.29, 233.44), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Harmony)", camera = 3}, + {location = vector4(549.85, 2666.71, 43.29, 50.89), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Harmony)", camera = 4}, + {location = vector4(543.36, 2664.36, 43.29, 233.4), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Harmony)", camera = 5}, + {location = vector4(1968.82, 3743.63, 33.49, 77.66), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Alhambra Drive)", camera = 1}, + {location = vector4(1657.69, 3744.0, 33.5, 257.56), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Alhambra Drive)", camera = 2}, + {location = vector4(1962.79, 3748.66, 33.49, 77.66), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Alhambra Drive)", camera = 3}, + {location = vector4(2683.92, 3287.4, 56.32, 107.43), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Senora Freeway)", camera = 1}, + {location = vector4(2673.82, 3281.56, 56.32, 292.39), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Senora Freeway)", camera = 2}, + {location = vector4(2675.99, 3288.17, 56.32, 109.95), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Senora Freeway)", camera = 3}, + {location = vector4(1740.25, 6406.94, 36.15, 201.8), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (East | Great Ocean Highway)", camera = 1}, + {location = vector4(1735.7, 6410.0, 36.15, 21.8), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (East | Great Ocean Highway)", camera = 2}, + {location = vector4(1729.81, 6419.38, 36.08, 199.44), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (East | Great Ocean Highway)", camera = 3}, + {location = vector4(1736.51, 6417.86, 36.08, 21.8), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (East | Great Ocean Highway)", camera = 4}, + {location = vector4(1133.25, -978.84, 47.48, 221.79), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Vespucci Boulevard)", camera = 1}, + {location = vector4(-1224.77, -910.71, 13.43, 335.67), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (San Andreas Avenue)", camera = 1}, + {location = vector4(-1483.36, -380.25, 41.31, 74.71), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Prosperity Street)", camera = 1}, + {location = vector4(-2966.23, 387.35, 16.27, 26.65), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (West | Great Ocean Highway)", camera = 1}, + {location = vector4(1169.49, 2711.16, 39.32, 118.61), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Route 68)", camera = 1}, + {location = vector4(-56.89, -1752.07, 30.54, 275.94), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Davis Avenue)", camera = 1}, + {location = vector4(-43.42, -1755.28, 30.54, 98.44), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Davis Avenue)", camera = 2}, + {location = vector4(-40.0, -1751.34, 30.09, 120.42), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Davis Avenue)", camera = 3}, + {location = vector4(-43.97, -1748.2, 30.12, 188.44), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Davis Avenue)", camera = 4}, + {location = vector4(1153.6, -326.81, 70.33, 325.41), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (West Mirror Drive)", camera = 1}, + {location = vector4(1164.76, -318.51, 70.25, 147.90), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (West Mirror Drive)", camera = 2}, + {location = vector4(1164.05, -313.02, 69.96, 170.47), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (West Mirror Drive)", camera = 3}, + {location = vector4(1159.16, -314.42, 69.81, 237.90), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (West Mirror Drive)", camera = 4}, + {location = vector4(-717.72, -915.68, 20.31, 318.77), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Ginger Street)", camera = 1}, + {location = vector4(-705.42, -909.55, 20.24, 136.27), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Ginger Street)", camera = 2}, + {location = vector4(-705.05, -903.92, 19.98, 161.27), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Ginger Street)", camera = 3}, + {location = vector4(-710.21, -904.43, 19.82, 228.77), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Ginger Street)", camera = 4}, + {location = vector4(-1827.22, 784.84, 139.4, 2.34), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (North Rockford Drive)", camera = 1}, + {location = vector4(-1822.38, 797.85, 139.17, 172.34), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (North Rockford Drive)", camera = 2}, + {location = vector4(-1825.91, 802.22, 138.91, 204.84), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (North Rockford Drive)", camera = 3}, + {location = vector4(-1829.37, 898.26, 138.8, 267.34), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (North Rockford Drive)", camera = 4}, + {location = vector4(1703.03, 4933.52, 43.18, 188.32), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Grapeseed)", camera = 1}, + {location = vector4(1701.05, 4919.84, 43.18, 10.82), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Grapeseed)", camera = 2}, + {location = vector4(1705.21, 4916.74, 42.73, 35.83), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Grapeseed)", camera = 3}, + {location = vector4(1708.04, 4920.94, 42.67, 103.32), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Grapeseed)", camera = 4}, + {location = vector4(-1090.0, -2588.47, 14.98, 104.98), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (LSIA)", camera = 1}, + {location = vector4(-1099.73, -2593.77, 15.08, 289.90), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (LSIA)", camera = 2}, + {location = vector4(-1097.69, -2587.18, 15.08, 107.48), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (LSIA)", camera = 3}, + {location = vector4(264.58, -987.13, 30.49, 296.89), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Strawberry Avenue)", camera = 1}, + {location = vector4(273.45, -979.77, 30.48, 119.43), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Strawberry Avenue)", camera = 2}, + {location = vector4(272.63, -986.63, 30.48, 297.0), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Strawberry Avenue)", camera = 3}, + {location = vector4(166.27, 6634.11, 32.86, 0.07), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Paleto Bay)", camera = 1}, + {location = vector4(163.78, 6644.98, 32.86, 185.2), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Paleto Bay)", camera = 2}, + {location = vector4(169.56, 6641.29, 32.81, 7.58), canRotate = true, cameraType = "highquality", type = "General Stores", name = "General Store (Paleto Bay)", camera = 3}, + + -- Highway Traffic Cameras + + {location = vector4(-1141.84, -656.03, 15.46, 291.61), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Del Perro Fwy", camera = 1}, + + {location = vector4(-988.14, -571.27, 25.02, 358.79), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Little Seoul Del Perro Fwy", camera = 1}, + + + {location = vector4(-523.43, -514.01, 29.7, 267.46), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Little Seoul Del Perro Fwy/La Puerta Fwy", camera = 1}, + + + {location = vector4(-227.05, -513.61, 30.35, 238.64), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Las Lagunas Blv La Puerta Fwy", camera = 1}, + + + {location = vector4(270.64, -510.93, 38.39, 236.37), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Vinewood Del Perro Fwy/Elgin Ave", camera = 1}, + + + {location = vector4(476.81, -484.67, 40.15, 53.99), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West Vinewood Los Santos Fwy/Del Perro Fwy", camera = 1}, + + + {location = vector4(579.07, -543.8, 41.66, 223.35), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East La Mesa Los Perro Fwy/Del Perro Fwy", camera = 1}, + + + {location = vector4(1020, -932.81, 34.37, 168.39), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "South Murrieta Heights Del Perro Fwy", camera = 1}, + + + {location = vector4(1064.98, -1448.59, 32.68, 315.01), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East La Mesa Eltsian Fields Fyw/Capital Blvd", camera = 1}, + + + {location = vector4(1229.26, -2020.53, 48.63, 186.99), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "South El Burro Heights Elysian Fields Fwy", camera = 1}, + + {location = vector4(963.99, -2596.72, 50.74, 90.22), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West Cypress Flats Elysian Fields Fwy", camera = 1}, + + + {location = vector4(236.31, -2678.4, 22.69, 65.79), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West Elysian Fields Fwy", camera = 1}, + + + {location = vector4(-536.69, -2239.02, 64.04, 48.86), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West La Puerta Fwy", camera = 1}, + + {location = vector4(-725.75, -2149.05, 17.89, 119.66), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West Davis Ave/Dutch London", camera = 1}, + + {location = vector4(-699.21, -2005.97, 30.76, 352.9), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Davis Ave", camera = 1}, + + {location = vector4(-668.8, -1918.78, 31.38, 43.62), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Dutch London St", camera = 1}, + + {location = vector4(-324.41, -2102.61, 27.79, 244.81), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Dutch London St/Davs Ave", camera = 1}, + + {location = vector4(-492.12, -1886.52, 22.16, 276.21), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East La Puerta/Davis Ave", camera = 1}, + + {location = vector4(-753.85, -1796.07, 33.05, 359.85), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Dutch London St/Davis Ave", camera = 1}, + + {location = vector4(-650.28, -1724.46, 41.64, 271.86), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East La Puerta Fwy/Mutiny Rd", camera = 1}, + + {location = vector4(-429.01, -1565.29, 43.34, 333.89), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North La Puerta/La Puerta Fwy", camera = 1}, + + {location = vector4(-403.82, -1373.75, 41.81, 248.17), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North La Puerta Fwy/Olympic Fwy", camera = 1}, + + {location = vector4(-404.26, -979.05, 41.64, 348.38), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North La Puerta Fwy/Olympic Fwy", camera = 2}, + + {location = vector4(-404.3, -698.54, 41.77, 340.45), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North La Puerta Fwy/Olympic Fwy", camera = 3}, + + {location = vector4(-152.9, -1220.86, 51.95, 294.69), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Olympic Fwy", camera = 1}, + + {location = vector4(596.12, -1203.31, 45.46, 258.47), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Olympic Fwy", camera = 2}, + + {location = vector4(1385.05, -1088.29, 57.75, 289.68), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Palomino Fwy", camera = 1}, + + {location = vector4(2127.29, -578.88, 99.76, 302.17), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Palomino Fwy", camera = 2}, + + {location = vector4(2444.51, -162.73, 92.7, 318.37), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Palomino Fwy", camera = 3}, + + {location = vector4(2592.35, 681.02, 97.84, 9.88), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Palomino Fwy", camera = 4}, + + {location = vector4(2354.46, 1170.33, 67.19, 307.91), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "East Palomino Fwy", camera = 5}, + + {location = vector4(2526.67, 642.45, 110.76, 175.82), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West Palomino Fwy", camera = 6}, + + {location = vector4(2133.19, 1341.78, 79.89, 18.76), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "West Palomino Fwy", camera = 7}, + + {location = vector4(526.95, -357.51, 48.97, 344.28), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 1}, + + {location = vector4(587.81, -326.89, 41.16, 313.77), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 2}, + + {location = vector4(834.75, 90.13, 73.15, 310.47), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 3}, + + {location = vector4(1287.24, 579.15, 84.91, 296.25), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 4}, + + {location = vector4(1606.99, 1070.94, 85.23, 329.8), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 5}, + + {location = vector4(1732.16, 1518.58, 89.14, 323.9), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 6}, + + {location = vector4(1902.79, 2371.38, 59.99, 335.66), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Los Santos Freeway", camera = 7}, + + {location = vector4(2003.39, 1590.59, 79.07, 9.69), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 1}, + + {location = vector4(2014.28, 2579.03, 59.3, 297.02), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 2}, + + {location = vector4(2248.09, 2779.26, 48.44, 293.72), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 3}, + + {location = vector4(2373.62, 2946.01, 53.6, 340.89), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 4}, + + {location = vector4(2772.44, 3350.43, 60.46, 322.44), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 5}, + + {location = vector4(2795.45, 4390.78, 53.87, 59.56), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 6}, + + {location = vector4(2789.62, 4420.52, 53.43, 346.86), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 7}, + + {location = vector4(2627.92, 5099.9, 49.46, 339.29), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 8}, + + {location = vector4(2621.93, 5123.63, 49.34, 342.12), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 9}, + + {location = vector4(2219.07, 6022.92, 56.43, 45.06), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 10}, + + {location = vector4(2118.21, 6026.24, 59.69, 47.04), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 11}, + + + {location = vector4(1783.16, 6355.11, 41.62, 59.11), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Senora Fwy", camera = 12}, + + {location = vector4(1031.51, 6504.69, 25.91, 58.03), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 1}, + + {location = vector4(183.46, 6546.85, 36.59, 116.53), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 2}, + + {location = vector4(-635.6, 5606.54, 43.49, 135.6), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 3}, + + {location = vector4(-1230.06, 5271.97, 55.2, 223.17), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 4}, + + {location = vector4(-1538.61, 4980.64, 66.88, 147.93), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 5}, + + {location = vector4(-1913.39, 4623.48, 63.04, 145.38), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 6}, + + {location = vector4(-2300.23, 4214.92, 45.76, 317.91), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 7}, + + {location = vector4(-2506.03, 3541.91, 19.46, 342.76), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 8}, + + {location = vector4(-2622.92, 2975.36, 22.91, 19.98), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 9}, + + {location = vector4(-2691.93, 2302.06, 24.53, 232.53), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 10}, + + {location = vector4(-3090.39, 1201.89, 26.05, 180.48), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 11}, + + {location = vector4(-3027.27, 311.33, 19.5, 340.22), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 12}, + + {location = vector4(-2225.42, -358.66, 18.12, 275.76), canRotate = true, cameraType = "highquality", type = "Traffic Cameras", name = "North Great Ocean Hwy", camera = 13}, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {location = vector4(112.17, -1312.33, 35.07, 236.35), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 1}, + {location = vector4(144.05, -1295.15, 32.27, 181.35), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 2}, + {location = vector4(145.08, -1292.26, 31.87, 328.85), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 3}, + {location = vector4(132.28, -1293.21, 29.87, 148.85), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 4}, + {location = vector4(120.34, -1289.46, 30.37, 216.92), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 5}, + {location = vector4(117.89, -1282.66, 30.37, 154.42), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 6}, + {location = vector4(110.67, -1281.92, 30.12, 219.42), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 7}, + {location = vector4(133.57, -1275.7, 35.75, 231.92), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 8}, + {location = vector4(132.44, -1274.22, 33.52, 21.92), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 9}, + {location = vector4(131.58, -1275.42, 34.34, 111.92), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 10}, + {location = vector4(100.56, -1280.87, 34.49, 289.42), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 11}, + {location = vector4(98.58, -1281.03, 33.54, 79.42), canRotate = true, cameraType = "highquality", type = "Entertainment", name = "Vanilla Unicorn", camera = 12}, + + {location = vector4(149.47, -1035.65, 31.08, 308.42), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 1}, + {location = vector4(152.69, -1041.89, 29.79, 55.92), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 2}, + {location = vector4(146.48, -1038.21, 29.79, 248.42), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 3}, + {location = vector4(143.44, -1039.94, 30.04, 315.89), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 4}, + {location = vector4(142.93, -1041.93, 30.11, 220.91), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 5}, + {location = vector4(145.15, -1043.27, 29.92, 220.92), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 6}, + {location = vector4(150.61, -1046.72, 29.91, 58.42), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 7}, + {location = vector4(149.90, -1051.08, 30.08, 18.42), canRotate = true, cameraType = "highquality", type = "Banks", name = "Legion Square", camera = 8}, + + {location = vector4(301.31, -581.95, 44.31, 193.39), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 1}, + {location = vector4(311.83, -597.61, 44.46, 21.78), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 2}, + {location = vector4(327.98, -591.3, 44.43, 119.31), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 3}, + {location = vector4(323.69, -602.56, 44.33, 44.28), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 4}, + {location = vector4(305.69, -569.71, 44.41, 213.83), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 5}, + {location = vector4(315.33, -579.04, 44.41, 136.33), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 6}, + {location = vector4(334.53, -570.0, 44.46, 141.33), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 7}, + {location = vector4(336.82, -586.6, 44.48, 211.33), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 8}, + {location = vector4(347.93, -602.31, 44.33, 1.33), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Pillbox Medical Center", camera = 9}, + {location = vector4(1836.64, 3671.79, 35.30, 241.95), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Sandy Shores Medical Center", camera = 1}, + {location = vector4(1818.46, 3680.81, 35.17, 61.15), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Sandy Shores Medical Center", camera = 2}, + {location = vector4(1830.45, 3693.33, 35.38, 62.7), canRotate = true, cameraType = "highquality", type = "Hospitals", name = "Sandy Shores Medical Center", camera = 3}, + + {location = vector4(433.3, -978.43, 32.65, 126.55), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 1}, + {location = vector4(423.99, -996.86, 32.96, 119.5), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 2}, + {location = vector4(438.44, -999.89, 31.51, 212.86), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 3}, + {location = vector4(438.91, -978.64, 31.64, 217.54), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 4}, + {location = vector4(441.1, -987.55, 31.97, 52.74), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 5}, + {location = vector4(444.4, -975.07, 32.22, 137.54), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 6}, + {location = vector4(449.24, -988.52, 31.79, 52.54), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 7}, + {location = vector4(449.3, -981.81, 31.77, 140.04), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 8}, + {location = vector4(460.48, -986.91, 31.45, 77.53), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 9}, + {location = vector4(450.83, -986.85, 31.35, 292.54), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 10}, + {location = vector4(458.93, -986.23, 27.42, 72.54), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 11}, + {location = vector4(465.14, -985.6, 26.77, 170.04), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 12}, + {location = vector4(463.39, -990.86, 26.7, 340.03), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 13}, + {location = vector4(459.23, -987.62, 26.66, 233.64), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 14}, + {location = vector4(465.33, -995.80, 25.31, 131.13), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 15}, + {location = vector4(469.49, -995.14, 25.76, 238.64), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 16}, + {location = vector4(478.41, -996.16, 24.99, 148.63), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 17}, + {location = vector4(487.01, -995.25, 24.56, 51.14), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 18}, + {location = vector4(462.42, -1007.64, 25.46, 341.14), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 19}, + {location = vector4(469.5, -1009.24, 26.86, 171.14), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 20}, + {location = vector4(489.89, -1003.8, 28.71, 302.0), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 21}, + {location = vector4(481.86, -977.89, 29.01, 28.63), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Mission Row", camera = 22}, + + {location = vector4(1856.12, 3683.28, 35.32, 175.73), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 1}, + {location = vector4(1865.0, 3688.08, 35.08, 247.7), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 2}, + {location = vector4(1851.76, 3682.04, 35.38, 325.73), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 3}, + {location = vector4(1847.48, 3689.51, 35.33, 258.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 4}, + {location = vector4(1853.08, 3692.62, 35.33, 188.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 5}, + {location = vector4(1855.6, 3690.09, 35.55, 348.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 6}, + {location = vector4(1844.85, 3694.13, 35.40, 250.73), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 7}, + {location = vector4(1849.12, 3683.57, 30.82, 155.73), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 8}, + {location = vector4(1850.36, 3684.23, 30.82, 273.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 9}, + {location = vector4(1853.0, 3687.34, 30.82, 63.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 10}, + {location = vector4(1854.4, 3687.96, 30.75, 343.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 11}, + {location = vector4(1859.26, 3686.51, 30.8, 68.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 12}, + {location = vector4(1860.23, 3688.5, 30.82, 298.23), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 13}, + {location = vector4(1858.38, 3691.48, 30.82, 300.73), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 14}, + {location = vector4(1855.94, 3694.82, 30.82, 305.73), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 15}, + {location = vector4(1853.61, 3700.67, 35.38, 350.2), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 16}, + {location = vector4(1853.61, 3700.67, 35.38, 350.2), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Sandy Shores", camera = 17}, + + {location = vector4(-434.9, 6011.41, 33.42, 341.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 1}, + {location = vector4(-447.43, 6023.68, 33.42, 348.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 2}, + {location = vector4(-458.63, 6015.94, 33.24, 11.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 3}, + {location = vector4(-441.21, 5994.84, 33.24, 106.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 4}, + {location = vector4(-442.96, 5983.43, 33.24, 111.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 5}, + {location = vector4(-430.89, 5989.2, 33.24, 261.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 6}, + {location = vector4(-441.45, 6013.17, 32.77, 76.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 7}, + {location = vector4(-447.4, 6007.07, 32.77, 1.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 8}, + {location = vector4(-451.49, 6011.69, 32.84, 293.12), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 9}, + {location = vector4(-439.7, 6013.18, 32.84, 166.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 10}, + {location = vector4(-433.59, 6001.16, 32.84, 358.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 11}, + {location = vector4(-440.92, 5999.96, 32.64, 271.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 12}, + {location = vector4(-447.12, 6005.48, 33.73, 256.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 13}, + {location = vector4(-440.15, 6002.3, 33.73, 43.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 14}, + {location = vector4(-440.73, 5998.79, 37.25, 1.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 15}, + {location = vector4(-435.49, 6004.22, 37.26, 86.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 16}, + {location = vector4(-444.82, 6006.2, 37.26, 256.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 17}, + {location = vector4(-449.02, 6012.96, 37.26, 178.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 18}, + {location = vector4(-441.52, 5999.8, 29.02, 311.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 19}, + {location = vector4(-431.88, 6007.97, 29.02, 111.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 20}, + {location = vector4(-439.14, 5999.31, 29.02, 278.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 21}, + {location = vector4(-432.19, 5999.29, 29.02, 93.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 22}, + {location = vector4(-443.38, 6007.69, 29.02, 253.92), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 23}, + {location = vector4(-446.74, 6009.03, 29.02, 276.42), canRotate = true, cameraType = "highquality", type = "Police Stations", name = "Paleto Bay", camera = 24} +} + +CCTV_Config.TimecycleTypes = { + ["blackwhite"] = "CAMERA_BW", + ["clear"] = "eyeINtheSKY", + ["highquality"] = "heliGunCam" +} \ No newline at end of file diff --git a/resources/wp-placeables/LICENSE b/resources/wp-placeables/LICENSE new file mode 100644 index 000000000..e72bfddab --- /dev/null +++ b/resources/wp-placeables/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/resources/wp-placeables/README.md b/resources/wp-placeables/README.md new file mode 100644 index 000000000..3b641de52 --- /dev/null +++ b/resources/wp-placeables/README.md @@ -0,0 +1,1978 @@ +# Waypoint Placeables + +![wp-placeables-screenshot](https://github.com/WaypointRP/wp-placeables/assets/18689469/292bfbd4-a531-4882-b01e-ccfdbfdcb17f) + +Waypoint Placeables is a framework that provides a simple mechanism to create useable items that place interactable props into the world. Each item can be configured with the default options and can easily be extended by providing a set of custom actions. The framework provides default options for placing items, picking up items, as well as configuring items to be a pushable prop. It is designed to be easy to use and highly customizable, allowing you to create a wide range of placeable and useable items from the selection of GTA props as well as custom props. + +Players can use the placeable props in a variety of ways to enhance their RP scenarios. Some examples include: building a construction site scene, creating a campsite in the woods with tents, chairs and campfires, blocking off roads for a crime scene, placing items in the world to push around to increase the realism of a scene, and much more. + +Preview: https://www.youtube.com/watch?v=nLiac1VYjxE + +### Overview: +- Player uses the item and the item placement mode is triggered +- A client side only (non-networked) prop is spawned and the player chooses where to place the prop +- After confirming the placement, the prop is spawned in as a networked prop so that all clients can see it and the item is removed from the player's inventory +- Players can interact with the prop using target to view the available options +- Players can place down multiple props to build a unique scene to enhance their RP scenarios +- When the player is done, they can clean up the scene by picking up the props and the item is given to the player (this is a default option that comes with all of the items) +- If an item is pushable and/or sitable, a player can stop interacting with the item by pressing 'E' (by default). +- While a player is pushing an item, a thread will run to check if something (like walking through a door, stumble animation, etc) caused them to break out of the pushing animation and will stick them back in the animation +- Adding a prop model to the config also enables world spawned props of the same model to be able to be picked up (ex: shopping carts that naturally spawn at mallmart can be picked up) +- Placed props do not persist through server restart. This script is intended to provide short term, temporary scenes per server session. + +## Placement Mode +When in placement mode, the player is able to position the prop in a radius around them. They can control its location, rotation, and height. +- E - Places the prop in its current position +- Shift + E - Attempts to snap the prop to the ground +- Scroll Wheel Up/Down - Rotates the item +- Shift + Scroll Wheel Up/Down - Raises or lowers the item +- Scroll Wheel Click - Change placement mode (changes the raycast to only detect world or everything) +- Right click / backspace - Exit placement mode without placing the item + +> While in placement mode the script will run at about 0.09ms - 0.1ms. This is primarily because we are using Raycast natives and have to run a quick thread to capture all of the players keypresses and movements. As soon as placement mode is exited, the script will return to 0.0ms. + +## Performance +This script was written with performance in mind and has been tested with 100+ props in the world with no noticeable performance impact. + +Resource monitor results: +- Idle: 0.0ms +- In item placement mode: 0.09ms - 0.1ms (primarily due to raycast natives and thread to capture keypresses) +- Pushing an object: 0.2ms (thread checking that push animation is still active) + +## Setup +1. Enable the script in your server.cfg +2. Add the items to your items.lua file +
+ Items (qb-inventory) + + ```lua + ------------------ + -- PLACEABLE ITEMS + ------------------ + -- Construction items + roadworkbarrier = { name = "roadworkbarrier", label = "Road Work Ahead Barrier", weight = 1000, type = "item", image = "roadworkahead.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A construction 'Road Work Ahead' barrier"}, + roadclosedbarrier = { name = "roadclosedbarrier", label = "Road Closed Barrier", weight = 1000, type = "item", image = "roadclosedbarrier.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A construction 'Road Closed' barrier"}, + constructionbarrier = { name = "constructionbarrier", label = "Fold-out Barrier", weight = 500, type = "item", image = "constructionbarrier.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A small construction barrier"}, + constructionbarrier2 = { name = "constructionbarrier2", label = "Construction Barrier", weight = 1000, type = "item", image = "constructionbarrier2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medium-sized construction barrier"}, + constructionbarrier3 = { name = "constructionbarrier3", label = "Construction Barrier", weight = 1000, type = "item", image = "constructionbarrier3.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medium-sized construction barrier"}, + roadconebig = { name = "roadconebig", label = "Road Cone Big", weight = 500, type = "item", image = "roadconebig.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A big road cone"}, + roadcone = { name = "roadcone", label = "Road Cone", weight = 500, type = "item", image = "roadcone.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A road cone"}, + roadpole = { name = "roadpole", label = "Road Pole", weight = 500, type = "item", image = "roadpole.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A road pole"}, + worklight = { name = "worklight", label = "Work light stand", weight = 500, type = "item", image = "worklight.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A tall worklight"}, + worklight2 = { name = "worklight2", label = "Work light stand", weight = 500, type = "item", image = "worklight2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A tall worklight"}, + worklight3 = { name = "worklight3", label = "Work light", weight = 500, type = "item", image = "worklight3.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A worklight"}, + constructiongenerator = { name = "constructiongenerator", label = "Construction Generator", weight = 2000, type = "item", image = "constructiongenerator.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A generator with lights"}, + trafficdevice = { name = "trafficdevice", label = "Traffic Device (Left)", weight = 1000, type = "item", image = "trafficdevice.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A traffic sign with an arrow pointing left"}, + trafficdevice2 = { name = "trafficdevice2", label = "Traffic Device (Right)", weight = 1000, type = "item", image = "trafficdevice.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A traffic sign with an arrow pointing right"}, + meshfence1 = { name = "meshfence1", label = "Mesh Fence Small", weight = 1000, type = "item", image = "meshfence.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A small mesh construction fence"}, + meshfence2 = { name = "meshfence2", label = "Mesh Fence Medium", weight = 1000, type = "item", image = "meshfence.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medium mesh construction fence"}, + meshfence3 = { name = "meshfence3", label = "Mesh Fence Large", weight = 1000, type = "item", image = "meshfence.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A large mesh construction fence"}, + waterbarrel = { name = "waterbarrel", label = "Water Barrel", weight = 500, type = "item", image = "waterbarrel.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A construction barrel full of water"}, + + -- Homeless / camping items + tent = { name = "tent", label = "Old Tent", weight = 1000, type = "item", image = "oldtent.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An old tent with several patches on it"}, + tent2 = { name = "tent2", label = "Tent", weight = 1000, type = "item", image = "tent.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A camping tent"}, + tent3 = { name = "tent3", label = "Large Tent", weight = 2000, type = "item", image = "largetent.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A large party tent"}, + sleepingbag = { name = "sleepingbag", label = "Sleeping Bag", weight = 1000, type = "item", image = "sleepingbag.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A sleeping bag rated for 20F"}, + hobostove = { name = "hobostove", label = "Hobo Stove", weight = 1000, type = "item", image = "hobostove.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A burn barrel"}, + campfire = { name = "campfire", label = "Camp Fire", weight = 1000, type = "item", image = "campfire.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Bundle of logs and kindling to make a camp fire"}, + hobomattress = { name = "hobomattress", label = "Hobo Mattress", weight = 1000, type = "item", image = "hobomattress.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An old, stained mattress"}, + hoboshelter = { name = "hoboshelter", label = "Hobo Shelter", weight = 1000, type = "item", image = "hoboshelter.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A cardboard homeless shelter"}, + canopy1 = { name = "canopy1", label = "Canopy (Green)", weight = 1000, type = "item", image = "canopy.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A green popup canopy"}, + canopy2 = { name = "canopy2", label = "Canopy (Blue)", weight = 1000, type = "item", image = "canopy.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A blue popup canopy"}, + canopy3 = { name = "canopy3", label = "Canopy (White)", weight = 1000, type = "item", image = "canopy.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A white popup canopy"}, + cot = { name = "cot", label = "Cot", weight = 1000, type = "item", image = "cot.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A camping cot"}, + + -- Triathlon items + tristarttable = { name = "tristarttable", label = "Triathlon Start Table", weight = 1000, type = "item", image = "tristarttable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Triathlon check in desk"}, + tristartbanner = { name = "tristartbanner", label = "Triathlon Start Banner", weight = 1000, type = "item", image = "tristartbanner.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Triathlon start banner"}, + trifinishbanner = { name = "trifinishbanner", label = "Triathlon Finish Banner", weight = 1000, type = "item", image = "trifinishbanner.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Triathlon finish banner"}, + + -- Tables + plastictable = { name = "plastictable", label = "Plastic Table (Collapsible)", weight = 1000, type = "item", image = "plastictable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Simple portable plastic table"}, + plastictable2 = { name = "plastictable2", label = "Plastic Table", weight = 1000, type = "item", image = "plastictable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Simple portable plastic table"}, + woodtable = { name = "woodtable", label = "Small Wood Table", weight = 1000, type = "item", image = "woodtable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Small portable wood table"}, + woodtable2 = { name = "woodtable2", label = "Wood Table", weight = 1000, type = "item", image = "woodtable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Portable wood table"}, + + -- Beach items + beachtowel = { name = "beachtowel", label = "Beach towel", weight = 500, type = "item", image = "beachtowel.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A towel for the beach"}, + beachumbrella = { name = "beachumbrella", label = "Beach umbrella", weight = 500, type = "item", image = "beachumbrella.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A beach umbrella (white and blue)"}, + beachumbrella2 = { name = "beachumbrella2", label = "Beach umbrella", weight = 500, type = "item", image = "beachumbrella.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A beach umbrella (green, white, blue)"}, + beachumbrella3 = { name = "beachumbrella3", label = "Beach umbrella", weight = 500, type = "item", image = "beachumbrella.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A beach umbrella (white)"}, + beachumbrella4 = { name = "beachumbrella4", label = "Beach umbrella", weight = 500, type = "item", image = "beachumbrella.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A beach umbrella (blue)"}, + beachball = { name = "beachball", label = "Beach ball", weight = 200, type = "item", image = "beachball.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A beach ball"}, + + -- Chairs + camp_chair_green = { name = "camp_chair_green", label = "Camp chair (green)", weight = 1000, type = "item", image = "campchair_green.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A lightweight, collapsible chair"}, + camp_chair_blue = { name = "camp_chair_blue", label = "Camp chair (blue)", weight = 1000, type = "item", image = "campchair_blue.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A lightweight, collapsible chair"}, + camp_chair_plaid = { name = "camp_chair_plaid", label = "Camp chair (plaid)", weight = 1000, type = "item", image = "campchair_plaid.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A lightweight, collapsible chair"}, + plastic_chair = { name = "plastic_chair", label = "Plastic chair", weight = 1000, type = "item", image = "plastic_chair.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A lightweight, plastic chair"}, + folding_chair = { name = "folding_chair", label = "Folding chair", weight = 1000, type = "item", image = "folding_chair.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A lightweight, folding chair"}, + + -- Misc + greenscreen = { name = "greenscreen", label = "Green Screen Set", weight = 2000, type = "item", image = "greenscreen.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A green screen production set"}, + ropebarrier = { name = "ropebarrier", label = "Rope Barrier", weight = 500, type = "item", image = "ropebarrier.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A rope barrier"}, + largesoccerball = { name = "largesoccerball", label = "Large Soccer ball", weight = 1000, type = "item", image = "soccerball.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A large soccer ball"}, + soccerball = { name = "soccerball", label = "Soccer ball", weight = 200, type = "item", image = "soccerball.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A soccer ball"}, + ramp1 = { name = "ramp1", label = "Wood Ramp (Gradual)", weight = 25000, type = "item", image = "woodramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A ramp with a slight incline"}, + ramp2 = { name = "ramp2", label = "Wood Ramp (Moderate)", weight = 25000, type = "item", image = "woodramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A ramp with a moderate incline"}, + ramp3 = { name = "ramp3", label = "Wood Ramp (Steep)", weight = 25000, type = "item", image = "woodramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A ramp with a steep incline"}, + ramp4 = { name = "ramp4", label = "Metal Ramp (Large)", weight = 50000, type = "item", image = "metalramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A large metal ramp with a moderate incline"}, + ramp5 = { name = "ramp5", label = "Metal Trailer Ramp", weight = 25000, type = "item", image = "metalramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A metal trailer ramp with a moderate incline"}, + skateramp = { name = "skateramp", label = "Skate ramp", weight = 50000, type = "item", image = "skateramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A skate ramp"}, + stuntramp1 = { name = "stuntramp1", label = "Stunt ramp S", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A short stunt ramp"}, + stuntramp2 = { name = "stuntramp2", label = "Stunt ramp M", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medium stunt ramp"}, + stuntramp3 = { name = "stuntramp3", label = "Stunt ramp L", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A large stunt ramp"}, + stuntramp4 = { name = "stuntramp4", label = "Stunt ramp XL", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A extra large stunt ramp"}, + stuntramp5 = { name = "stuntramp5", label = "Stunt ramp XXL", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A XXL stunt ramp"}, + stuntloop1 = { name = "stuntloop1", label = "Stunt half loop", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A stunt half loop"}, + stuntloop2 = { name = "stuntloop2", label = "Stunt loop", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A stunt full loop"}, + stuntloop3 = { name = "stuntloop3", label = "Stunt spiral", weight = 30000, type = "item", image = "stuntramp.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A stunt full loop"}, + stepladder = { name = "stepladder", label = "Step ladder", weight = 1000, type = "item", image = "stepladder.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Used to reach higher places"}, + trafficlight = { name = "trafficlight", label = "Traffic Light", weight = 1000, type = "item", image = "trafficlight.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A deployable traffic control device"}, + sexdoll = { name = "sexdoll", label = "Sex doll", weight = 1000, type = "item", image = "sexdoll.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A deflated mini-sex doll"}, + + -- Medical items + medbag = { name = "medbag", label = "Medical Bag", weight = 1000, type = "item", image = "medbag.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medical bag"}, + examlight = { name = "examlight", label = "Exam Light", weight = 1000, type = "item", image = "examlight.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medical exam light"}, + hazardbin = { name = "hazardbin", label = "Hazard Wastebin", weight = 1000, type = "item", image = "hazardbin.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A hazardous waste bin"}, + microscope = { name = "microscope", label = "Microscope", weight = 1000, type = "item", image = "microscope.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Make small things big"}, + oscillator = { name = "oscillator", label = "Oscillator", weight = 1000, type = "item", image = "oscillator.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A heart beat monitor"}, + medmachine = { name = "medmachine", label = "Medical Machine", weight = 1000, type = "item", image = "medmachine.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medical machine"}, + hospitalbedtable = { name = "hospitalbedtable", label = "Bedside Table", weight = 1000, type = "item", image = "hospitalbedtable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A hospital bedside table"}, + medtable = { name = "medtable", label = "Medical Table", weight = 1000, type = "item", image = "medtable.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A medical table with machines on it"}, + bodybag = { name = "bodybag", label = "Body Bag", weight = 1000, type = "item", image = "bodybag.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A body bag for putting deceased humans in"}, + + -- Cargo items + cargobox1 = { name = "cargobox1", label = "Large cardboardbox pallet", weight = 1000, type = "item", image = "cargobox1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox2 = { name = "cargobox2", label = "Large mixed pallet", weight = 1000, type = "item", image = "cargobox2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox3 = { name = "cargobox3", label = "Tall wrapped pallet", weight = 1000, type = "item", image = "cargobox3.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox4 = { name = "cargobox4", label = "Cardboardboxes pallet", weight = 1000, type = "item", image = "cargobox4.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox5 = { name = "cargobox5", label = "Sprunk boxes pallet", weight = 1000, type = "item", image = "cargobox5.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox6 = { name = "cargobox6", label = "Cardboardboxes wrapped", weight = 1000, type = "item", image = "cargobox6.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox7 = { name = "cargobox7", label = "Cardboardboxes fragile", weight = 1000, type = "item", image = "cargobox7.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + cargobox8 = { name = "cargobox8", label = "Cardboardboxes + keg", weight = 1000, type = "item", image = "cargobox8.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + pallet1 = { name = "pallet1", label = "Empty pallet", weight = 1000, type = "item", image = "pallet1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + pallet2 = { name = "pallet2", label = "Fertilizer pallet", weight = 1000, type = "item", image = "pallet2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + pallet3 = { name = "pallet3", label = "Weed bricks pallet", weight = 1000, type = "item", image = "pallet3.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + pallet4 = { name = "pallet4", label = "Barrell pallet", weight = 1000, type = "item", image = "pallet4.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + pallet5 = { name = "pallet5", label = "Slotmachine pallet", weight = 1000, type = "item", image = "pallet5.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + crate1 = { name = "crate1", label = "Gopostal crate", weight = 1000, type = "item", image = "crate1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + crate2 = { name = "crate2", label = "Wood crate", weight = 1000, type = "item", image = "crate2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + crate3 = { name = "crate3", label = "Cluckinbell crate", weight = 1000, type = "item", image = "crate3.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + crate4 = { name = "crate4", label = "Water crate", weight = 1000, type = "item", image = "crate4.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + crate5 = { name = "crate5", label = "Animal cage", weight = 1000, type = "item", image = "crate5.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + + -- Xmas items + snowman1 = { name = "snowman1", label = "Snowman (Red)", weight = 1000, type = "item", image = "snowman1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + snowman2 = { name = "snowman2", label = "Snowman (Blue)", weight = 1000, type = "item", image = "snowman2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + snowman3 = { name = "snowman3", label = "Snowman (Green)", weight = 1000, type = "item", image = "snowman3.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + snowman4 = { name = "snowman4", label = "Snowman", weight = 1000, type = "item", image = "snowman4.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + xmastree1 = { name = "xmastree1", label = "Giant Xmas Tree", weight = 1000, type = "item", image = "xmastree1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + xmastree2 = { name = "xmastree2", label = "Xmas Tree", weight = 1000, type = "item", image = "xmastree2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + candycane = { name = "candycane", label = "Candy Cane", weight = 1000, type = "item", image = "candycane.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + xmaspresent = { name = "xmaspresent", label = "Xmas Present", weight = 1000, type = "item", image = "xmaspresent.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = ""}, + + -- Pushables + shoppingcart1 = { name = "shoppingcart1", label = "Shopping Cart (Empty)", weight = 1000, type = "item", image = "shoppingcart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An empty, plastic shopping cart"}, + shoppingcart2 = { name = "shoppingcart2", label = "Shopping Cart (Full)", weight = 1000, type = "item", image = "shoppingcart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A full plastic shopping cart"}, + shoppingcart3 = { name = "shoppingcart3", label = "Shopping Cart (Empty)", weight = 1000, type = "item", image = "shoppingcart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An empty, metal shopping cart"}, + shoppingcart4 = { name = "shoppingcart4", label = "Shopping Cart (Full)", weight = 1000, type = "item", image = "shoppingcart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A full metal shopping cart"}, + wheelbarrow = { name = "wheelbarrow", label = "Wheelbarrow", weight = 1000, type = "item", image = "wheelbarrow.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Useful for moving materials"}, + warehousetrolly1 = { name = "warehousetrolly1", label = "Warehouse Trolly (Empty)", weight = 1000, type = "item", image = "warehousetrolly1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Industrial warehouse trolly"}, + warehousetrolly2 = { name = "warehousetrolly2", label = "Warehouse Trolly (Full)", weight = 1000, type = "item", image = "warehousetrolly2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Industrial warehouse trolly with a box on it"}, + roomtrolly = { name = "roomtrolly", label = "Room Trolly", weight = 1000, type = "item", image = "roomtrolly.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Room service cart"}, + janitorcart1 = { name = "janitorcart1", label = "Janitor Cart", weight = 1000, type = "item", image = "janitorcart1.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A janitorial cart with cleaning supplies"}, + janitorcart2 = { name = "janitorcart2", label = "Janitor Cart", weight = 1000, type = "item", image = "janitorcart2.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A Diamond Casino janitorial cart with cleaning supplies"}, + mopbucket = { name = "mopbucket", label = "Mop Bucket", weight = 500, type = "item", image = "mopbucket.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A mop bucket with cleaning solution"}, + metalcart = { name = "metalcart", label = "Metal Cart", weight = 1000, type = "item", image = "metalcart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An empty metal cart"}, + teacart = { name = "teacart", label = "Tea Cart", weight = 1000, type = "item", image = "teacart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An empty tea cart"}, + drinkcart = { name = "drinkcart", label = "Drink Cart", weight = 1000, type = "item", image = "drinkcart.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An empty drink cart"}, + handtruck1 = { name = "handtruck1", label = "Hand Truck", weight = 1000, type = "item", image = "handtruck.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "An empty hand truck"}, + handtruck2 = { name = "handtruck2", label = "Hand Truck (boxes)", weight = 1000, type = "item", image = "handtruck.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A hand truck with boxes"}, + trashbin = { name = "trashbin", label = "Trash Bin", weight = 1000, type = "item", image = "trashbin.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Trash bin"}, + lawnmower = { name = "lawnmower", label = "Lawnmower", weight = 1000, type = "item", image = "lawnmower.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "Cuts grass"}, + toolchest = { name = "toolchest", label = "Tool Chest", weight = 1000, type = "item", image = "toolchest.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A sturdy toolchest"}, + carjack = { name = "carjack", label = "Car jack", weight = 1000, type = "item", image = "carjack.png", unique = false, useable = true, shouldClose = true, combinable = nil, description = "A car jack"}, + + -- Addon placeables + + ----------------------- + -- END OF PLACEABLES -- + ----------------------- + ``` +
+ +
+ Items (ox_inventory) + ```lua + -- PLACEABLE ITEMS + ['roadworkbarrier'] = { + label = "Road Work Ahead Barrier", + weight = 1000, + stack = true, + close = true, + description = "A construction 'Road Work Ahead' barrier", + client = { + image = 'roadworkahead.png', + } + }, + ['roadclosedbarrier'] = { + label = "Road Closed Barrier", + weight = 1000, + stack = true, + close = true, + description = "A construction 'Road Closed' barrier" + }, + ['constructionbarrier'] = { + label = "Fold-out Barrier", + weight = 500, + stack = true, + close = true, + description = "A small construction barrier" + }, + ['constructionbarrier2'] = { + label = "Construction Barrier", + weight = 1000, + stack = true, + close = true, + description = "A medium-sized construction barrier" + }, + ['constructionbarrier3'] = { + label = "Construction Barrier", + weight = 1000, + stack = true, + close = true, + description = "A medium-sized construction barrier" + }, + ['roadconebig'] = { + label = "Road Cone Big", + weight = 500, + stack = true, + close = true, + description = "A big road cone" + }, + ['roadcone'] = { + label = "Road Cone", + weight = 500, + stack = true, + close = true, + description = "A road cone" + }, + ['roadpole'] = { + label = "Road Pole", + weight = 500, + stack = true, + close = true, + description = "A road pole" + }, + ['worklight'] = { + label = "Work light stand", + weight = 500, + stack = true, + close = true, + description = "A tall worklight" + }, + ['worklight2'] = { + label = "Work light stand", + weight = 500, + stack = true, + close = true, + description = "A tall worklight" + }, + ['worklight3'] = { + label = "Work light", + weight = 500, + stack = true, + close = true, + description = "A worklight" + }, + ['constructiongenerator'] = { + label = "Construction Generator", + weight = 2000, + stack = true, + close = true, + description = "A generator with lights" + }, + ['trafficdevice'] = { + label = "Traffic Device (Left)", + weight = 1000, + stack = true, + close = true, + description = "A traffic sign with an arrow pointing left", + client = { + image = 'trafficdevice.png', + } + }, + ['trafficdevice2'] = { + label = "Traffic Device (Right)", + weight = 1000, + stack = true, + close = true, + description = "A traffic sign with an arrow pointing right", + client = { + image = 'trafficdevice.png', + } + }, + ['meshfence1'] = { + label = "Mesh Fence Small", + weight = 1000, + stack = true, + close = true, + description = "A small mesh construction fence", + client = { + image = 'meshfence.png', + } + }, + ['meshfence2'] = { + label = "Mesh Fence Medium", + weight = 1000, + stack = true, + close = true, + description = "A medium mesh construction fence", + client = { + image = 'meshfence.png', + } + }, + ['meshfence3'] = { + label = "Mesh Fence Large", + weight = 1000, + stack = true, + close = true, + description = "A large mesh construction fence", + client = { + image = 'meshfence.png', + } + }, + ['waterbarrel'] = { + label = "Water Barrel", + weight = 500, + stack = true, + close = true, + description = "A construction barrel full of water" + }, + -- Homeless / camping items + ["tent"] = { + label = "Old Tent", + weight = 1000, + stack = true, + close = true, + description = "An old tent with several patches on it", + client = { + image = 'oldtent.png', + } + }, + ["tent2"] = { + label = "Tent", + weight = 1000, + stack = true, + close = true, + description = "A camping tent", + client = { + image = 'tent.png', + } + }, + ["tent3"] = { + label = "Large Tent", + weight = 2000, + stack = true, + close = true, + description = "A large party tent" + , + client = { + image = 'largetent.png', + } + }, + ["sleepingbag"] = { + label = "Sleeping Bag", + weight = 1000, + stack = true, + close = true, + description = "A sleeping bag rated for 20F" + }, + ["hobostove"] = { + label = "Hobo Stove", + weight = 1000, + stack = true, + close = true, + description = "A burn barrel" + }, + ["campfire"] = { + label = "Camp Fire", + weight = 1000, + stack = true, + close = true, + description = "Bundle of logs and kindling to make a camp fire" + }, + ["hobomattress"] = { + label = "Hobo Mattress", + weight = 1000, + stack = true, + close = true, + description = "An old, stained mattress" + }, + ["hoboshelter"] = { + label = "Hobo Shelter", + weight = 1000, + stack = true, + close = true, + description = "A cardboard homeless shelter" + }, + ["canopy1"] = { + label = "Canopy (Green)", + weight = 1000, + stack = true, + close = true, + description = "A green popup canopy", + client = { + image = 'canopy.png', + } + }, + ["canopy2"] = { + label = "Canopy (Blue)", + weight = 1000, + stack = true, + close = true, + description = "A blue popup canopy", + client = { + image = 'canopy.png', + } + }, + ["canopy3"] = { + label = "Canopy (White)", + weight = 1000, + stack = true, + close = true, + description = "A white popup canopy", + client = { + image = 'canopy.png', + } + }, + ["cot"] = { + label = "Cot", + weight = 1000, + stack = true, + close = true, + description = "A camping cot" + }, + -- Triathlon items + ["tristarttable"] = { + label = "Triathlon Start Table", + weight = 1000, + stack = true, + close = true, + description = "Triathlon check in desk" + }, + ["tristartbanner"] = { + label = "Triathlon Start Banner", + weight = 1000, + stack = true, + close = true, + description = "Triathlon start banner" + }, + ["trifinishbanner"] = { + label = "Triathlon Finish Banner", + weight = 1000, + stack = true, + close = true, + description = "Triathlon finish banner" + }, + -- Tables + ["plastictable"] = { + label = "Plastic Table (Collapsible)", + weight = 1000, + stack = true, + close = true, + description = "Simple portable plastic table", + client = { + image = 'plastictable.png', + } + }, + ["plastictable2"] = { + label = "Plastic Table", + weight = 1000, + stack = true, + close = true, + description = "Simple portable plastic table", + client = { + image = 'plastictable.png', + } + }, + ["woodtable"] = { + label = "Small Wood Table", + weight = 1000, + stack = true, + close = true, + description = "Small portable wood table", + client = { + image = 'woodtable.png', + } + }, + ["woodtable2"] = { + label = "Wood Table", + weight = 1000, + stack = true, + close = true, + description = "Portable wood table", + client = { + image = 'woodtable.png', + } + }, + -- Beach items + ["beachtowel"] = { + label = "Beach towel", + weight = 500, + stack = true, + close = true, + description = "A towel for the beach" + }, + ["beachumbrella"] = { + label = "Beach umbrella", + weight = 500, + stack = true, + close = true, + description = "A beach umbrella (white and blue)", + client = { + image = 'beachumbrella.png', + } + }, + ["beachumbrella2"] = { + label = "Beach umbrella", + weight = 500, + stack = true, + close = true, + description = "A beach umbrella (green, white, blue)", + client = { + image = 'beachumbrella.png', + } + }, + ["beachumbrella3"] = { + label = "Beach umbrella", + weight = 500, + stack = true, + close = true, + description = "A beach umbrella (white)", + client = { + image = 'beachumbrella.png', + } + }, + ["beachumbrella4"] = { + label = "Beach umbrella", + weight = 500, + stack = true, + close = true, + description = "A beach umbrella (blue)", + client = { + image = 'beachumbrella.png', + } + }, + ["beachball"] = { + label = "Beach ball", + weight = 200, + stack = true, + close = true, + description = "A beach ball" + }, + -- Chairs + ["camp_chair_green"] = { + label = "Camp chair (green)", + weight = 1000, + stack = true, + close = true, + description = "A lightweight, collapsible chair", + client = { + image = 'campchair_green.png', + } + }, + ["camp_chair_blue"] = { + label = "Camp chair (blue)", + weight = 1000, + stack = true, + close = true, + description = "A lightweight, collapsible chair", + client = { + image = 'campchair_blue.png', + } + }, + ["camp_chair_plaid"] = { + label = "Camp chair (plaid)", + weight = 1000, + stack = true, + close = true, + description = "A lightweight, collapsible chair", + client = { + image = 'campchair_plaid.png', + } + }, + ["plastic_chair"] = { + label = "Plastic chair", + weight = 1000, + stack = true, + close = true, + description = "A lightweight, plastic chair" + }, + ["folding_chair"] = { + label = "Folding chair", + weight = 1000, + stack = true, + close = true, + description = "A lightweight, folding chair" + }, + -- Misc + ["greenscreen"] = { + label = "Green Screen Set", + weight = 2000, + stack = true, + close = true, + description = "A green screen production set" + }, + ["ropebarrier"] = { + label = "Rope Barrier", + weight = 500, + stack = true, + close = true, + description = "A rope barrier" + }, + ["largesoccerball"] = { + label = "Large Soccer Ball", + weight = 1000, + stack = true, + close = true, + description = "A large soccer ball", + client = { + image = 'soccerball.png', + } + }, + ["soccerball"] = { + label = "Soccer Ball", + weight = 200, + stack = true, + close = true, + description = "A soccer ball" + }, + ["ramp1"] = { + label = "Wood Ramp (Gradual)", + weight = 25000, + stack = true, + close = true, + description = "A ramp with a slight incline", + client = { + image = 'woodramp.png', + } + }, + ["ramp2"] = { + label = "Wood Ramp (Moderate)", + weight = 25000, + stack = true, + close = true, + description = "A ramp with a moderate incline", + client = { + image = 'woodramp.png', + } + }, + ["ramp3"] = { + label = "Wood Ramp (Steep)", + weight = 25000, + stack = true, + close = true, + description = "A ramp with a steep incline", + client = { + image = 'woodramp.png', + } + }, + ["ramp4"] = { + label = "Metal Ramp (Large)", + weight = 50000, + stack = true, + close = true, + description = "A large metal ramp with a moderate incline", + client = { + image = 'metalramp.png', + } + }, + ["ramp5"] = { + label = "Metal Trailer Ramp", + weight = 25000, + stack = true, + close = true, + description = "A metal trailer ramp with a moderate incline", + client = { + image = 'metalramp.png', + } + }, + ["skateramp"] = { + label = "Skate Ramp", + weight = 50000, + stack = true, + close = true, + description = "A skate ramp" + }, + ["stuntramp1"] = { + label = "Stunt Ramp S", + weight = 30000, + stack = true, + close = true, + description = "A short stunt ramp" + }, + ["stuntramp2"] = { + label = "Stunt Ramp M", + weight = 30000, + stack = true, + close = true, + description = "A medium stunt ramp" + }, + ["stuntramp3"] = { + label = "Stunt Ramp L", + weight = 30000, + stack = true, + close = true, + description = "A large stunt ramp" + }, + ["stuntramp4"] = { + label = "Stunt Ramp XL", + weight = 30000, + stack = true, + close = true, + description = "An extra large stunt ramp" + }, + ["stuntramp5"] = { + label = "Stunt Ramp XXL", + weight = 30000, + stack = true, + close = true, + description = "A XXL stunt ramp" + }, + ["stuntloop1"] = { + label = "Stunt Half Loop", + weight = 30000, + stack = true, + close = true, + description = "A stunt half loop" + }, + ["stuntloop2"] = { + label = "Stunt Loop", + weight = 30000, + stack = true, + close = true, + description = "A stunt full loop" + }, + ["stuntloop3"] = { + label = "Stunt Spiral", + weight = 30000, + stack = true, + close = true, + description = "A stunt spiral" + }, + ["stepladder"] = { + label = "Step Ladder", + weight = 1000, + stack = true, + close = true, + description = "Used to reach higher places" + }, + ["trafficlight"] = { + label = "Traffic Light", + weight = 1000, + stack = true, + close = true, + description = "A deployable traffic control device" + }, + ["sexdoll"] = { + label = "Sex Doll", + weight = 1000, + stack = true, + close = true, + description = "A deflated mini-sex doll" + }, + + -- Medical items + ["medbag"] = { + label = "Medical Bag", + weight = 1000, + stack = true, + close = true, + description = "A medical bag" + }, + ["examlight"] = { + label = "Exam Light", + weight = 1000, + stack = true, + close = true, + description = "A medical exam light" + }, + ["hazardbin"] = { + label = "Hazard Wastebin", + weight = 1000, + stack = true, + close = true, + description = "A hazardous waste bin" + }, + ["microscope"] = { + label = "Microscope", + weight = 1000, + stack = true, + close = true, + description = "Make small things big" + }, + ["oscillator"] = { + label = "Oscillator", + weight = 1000, + stack = true, + close = true, + description = "A heart beat monitor" + }, + ["medmachine"] = { + label = "Medical Machine", + weight = 1000, + stack = true, + close = true, + description = "A medical machine" + }, + ["hospitalbedtable"] = { + label = "Bedside Table", + weight = 1000, + stack = true, + close = true, + description = "A hospital bedside table" + }, + ["medtable"] = { + label = "Medical Table", + weight = 1000, + stack = true, + close = true, + description = "A medical table with machines on it" + }, + ["bodybag"] = { + label = "Body Bag", + weight = 1000, + stack = true, + close = true, + description = "A body bag for putting deceased humans in" + }, + -- Cargo items + ["cargobox1"] = { + label = "Large cardboardbox pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox2"] = { + label = "Large mixed pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox3"] = { + label = "Tall wrapped pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox4"] = { + label = "Cardboardboxes pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox5"] = { + label = "Sprunk boxes pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox6"] = { + label = "Cardboardboxes wrapped", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox7"] = { + label = "Cardboardboxes fragile", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["cargobox8"] = { + label = "Cardboardboxes + keg", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["pallet1"] = { + label = "Empty pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["pallet2"] = { + label = "Fertilizer pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["pallet3"] = { + label = "Weed bricks pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["pallet4"] = { + label = "Barrell pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["pallet5"] = { + label = "Slotmachine pallet", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["crate1"] = { + label = "Gopostal crate", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["crate2"] = { + label = "Wood crate", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["crate3"] = { + label = "Cluckinbell crate", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["crate4"] = { + label = "Water crate", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["crate5"] = { + label = "Animal cage", + weight = 1000, + stack = true, + close = true, + description = "" + }, + -- Xmas items + ["snowman1"] = { + label = "Snowman (Red)", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["snowman2"] = { + label = "Snowman (Blue)", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["snowman3"] = { + label = "Snowman (Green)", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["snowman4"] = { + label = "Snowman", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["xmastree1"] = { + label = "Giant Xmas Tree", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["xmastree2"] = { + label = "Xmas Tree", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["candycane"] = { + label = "Candy Cane", + weight = 1000, + stack = true, + close = true, + description = "" + }, + ["xmaspresent"] = { + label = "Xmas Present", + weight = 1000, + stack = true, + close = true, + description = "" + }, + -- Pushables + ["shoppingcart1"] = { + label = "Shopping Cart (Empty)", + weight = 1000, + stack = true, + close = true, + description = "An empty, plastic shopping cart", + client = { + image = 'shoppingcart.png', + } + }, + ["shoppingcart2"] = { + label = "Shopping Cart (Full)", + weight = 1000, + stack = true, + close = true, + description = "A full plastic shopping cart", + client = { + image = 'shoppingcart.png', + } + }, + ["shoppingcart3"] = { + label = "Shopping Cart (Empty)", + weight = 1000, + stack = true, + close = true, + description = "An empty, metal shopping cart", + client = { + image = 'shoppingcart.png', + } + }, + ["shoppingcart4"] = { + label = "Shopping Cart (Full)", + weight = 1000, + stack = true, + close = true, + description = "A full metal shopping cart", + client = { + image = 'shoppingcart.png', + } + }, + ["wheelbarrow"] = { + label = "Wheelbarrow", + weight = 1000, + stack = true, + close = true, + description = "Useful for moving materials" + }, + ["warehousetrolly1"] = { + label = "Warehouse Trolly (Empty)", + weight = 1000, + stack = true, + close = true, + description = "Industrial warehouse trolly" + }, + ["warehousetrolly2"] = { + label = "Warehouse Trolly (Full)", + weight = 1000, + stack = true, + close = true, + description = "Industrial warehouse trolly with a box on it" + }, + ["roomtrolly"] = { + label = "Room Trolly", + weight = 1000, + stack = true, + close = true, + description = "Room service cart" + }, + ["janitorcart1"] = { + label = "Janitor Cart", + weight = 1000, + stack = true, + close = true, + description = "A janitorial cart with cleaning supplies" + }, + ["janitorcart2"] = { + label = "Janitor Cart", + weight = 1000, + stack = true, + close = true, + description = "A Diamond Casino janitorial cart with cleaning supplies" + }, + ["mopbucket"] = { + label = "Mop Bucket", + weight = 500, + stack = true, + close = true, + description = "A mop bucket with cleaning solution" + }, + ["metalcart"] = { + label = "Metal Cart", + weight = 1000, + stack = true, + close = true, + description = "An empty metal cart" + }, + ["teacart"] = { + label = "Tea Cart", + weight = 1000, + stack = true, + close = true, + description = "An empty tea cart" + }, + ["drinkcart"] = { + label = "Drink Cart", + weight = 1000, + stack = true, + close = true, + description = "An empty drink cart" + }, + ["handtruck1"] = { + label = "Hand Truck", + weight = 1000, + stack = true, + close = true, + description = "An empty hand truck", + client = { + image = 'handtruck.png', + } + }, + ["handtruck2"] = { + label = "Hand Truck (boxes)", + weight = 1000, + stack = true, + close = true, + description = "A hand truck with boxes", + client = { + image = 'handtruck.png', + } + }, + ["trashbin"] = { + label = "Trash Bin", + weight = 1000, + stack = true, + close = true, + description = "Trash bin" + }, + ["lawnmower"] = { + label = "Lawnmower", + weight = 1000, + stack = true, + close = true, + description = "Cuts grass" + }, + ["toolchest"] = { + label = "Tool Chest", + weight = 1000, + stack = true, + close = true, + description = "A sturdy toolchest" + }, + ["carjack"] = { + label = "Car jack", + weight = 1000, + stack = true, + close = true, + description = "A car jack" + } + + ``` +
+3. Add the images from `images/` to your inventory scripts +4. Update the Config framework variables to match the framework you are using + - Most actions are set to support QB, OX, and ESX by default. If you are using a different framework, you will need to update the functions in `framework.lua` to match your framework. Feel free to submit a PR to get support for your framework added to the main repo, so others can leverage it as well. +5. Add a way for players to acquire these new items (ex: add them to a shop, make them craftable, rewards for jobs, etc) + +
+ Sample ox_inventory shop + + ```lua + PropStore = { + name = "Prop Store", + blip = { + id = 478, colour = 69, scale = 0.5 + }, + inventory = { + { name = "yogamat_blue", price = 200 }, + { name = "yogamat_black", price = 200 }, + { name = "yogamat_red", price = 200 }, + { name = "camp_chair_green", price = 200 }, + { name = "camp_chair_blue", price = 200 }, + { name = "camp_chair_plaid", price = 200 }, + { name = "plastic_chair", price = 200 }, + { name = "folding_chair", price = 200 }, + { name = "roadworkbarrier", price = 200 }, + { name = "roadclosedbarrier", price = 200 }, + { name = "constructionbarrier", price = 200 }, + { name = "constructionbarrier2", price = 200 }, + { name = "constructionbarrier3", price = 200 }, + { name = "roadconebig", price = 200 }, + { name = "roadcone", price = 200 }, + { name = "roadpole", price = 200 }, + { name = "worklight", price = 200 }, + { name = "worklight2", price = 200 }, + { name = "worklight3", price = 200 }, + { name = "constructiongenerator", price = 500 }, + { name = "trafficdevice", price = 500 }, + { name = "trafficdevice2", price = 200 }, + { name = "tent", price = 200 }, + { name = "tent2", price = 200 }, + { name = "tent3", price = 200 }, + { name = "tristarttable", price = 200 }, + { name = "tristartbanner", price = 200 }, + { name = "trifinishbanner", price = 200 }, + { name = "plastictable", price = 200 }, + { name = "plastictable2", price = 200 }, + { name = "woodtable", price = 200 }, + { name = "woodtable2", price = 200 }, + { name = "beachtowel", price = 200 }, + { name = "beachumbrella", price = 200 }, + { name = "beachumbrella2", price = 200 }, + { name = "beachumbrella3", price = 200 }, + { name = "beachumbrella4", price = 200 }, + { name = "beachball", price = 200 }, + { name = "greenscreen", price = 200 }, + { name = "ropebarrier", price = 200 }, + { name = "largesoccerball", price = 2000 }, + { name = "soccerball", price = 200 }, + { name = "sleepingbag", price = 200 }, + { name = "ramp1", price = 5000 }, + { name = "ramp2", price = 5000 }, + { name = "ramp3", price = 5000 }, + { name = "ramp4", price = 5000 }, + { name = "ramp5", price = 5000 }, + { name = "skateramp", price = 2500 }, + { name = "meshfence1", price = 200 }, + { name = "meshfence2", price = 200 }, + { name = "meshfence3", price = 200 }, + { name = "canopy1", price = 200 }, + { name = "canopy2", price = 200 }, + { name = "canopy3", price = 200 }, + { name = "stepladder", price = 200 }, + { name = "shoppingcart1", price = 200 }, + { name = "shoppingcart2", price = 200 }, + { name = "shoppingcart3", price = 200 }, + { name = "shoppingcart4", price = 200 }, + { name = "wheelbarrow", price = 200 }, + { name = "warehousetrolly1", price = 200 }, + { name = "warehousetrolly2", price = 200 }, + { name = "roomtrolly", price = 200 }, + { name = "janitorcart1", price = 200 }, + { name = "janitorcart2", price = 200 }, + { name = "metalcart", price = 200 }, + { name = "teacart", price = 200 }, + { name = "drinkcart", price = 200 }, + { name = "handtruck1", price = 200 }, + { name = "handtruck2", price = 200 }, + { name = "trashbin", price = 200 }, + { name = "cot", price = 200 }, + { name = "mopbucket", price = 200 }, + { name = "lawnmower", price = 200 }, + { name = "toolchest", price = 200 }, + { name = "carjack", price = 200 }, + { name = "waterbarrel", price = 200 }, + { name = "cargobox1", price = 200 }, + { name = "cargobox2", price = 200 }, + { name = "cargobox3", price = 200 }, + { name = "cargobox4", price = 200 }, + { name = "cargobox5", price = 200 }, + { name = "cargobox6", price = 200 }, + { name = "cargobox7", price = 200 }, + { name = "cargobox8", price = 200 }, + { name = "pallet1", price = 200 }, + { name = "pallet2", price = 200 }, + { name = "pallet3", price = 200 }, + { name = "pallet4", price = 200 }, + { name = "pallet5", price = 200 }, + { name = "crate1", price = 200 }, + { name = "crate2", price = 200 }, + { name = "crate3", price = 200 }, + { name = "crate4", price = 200 }, + { name = "crate5", price = 200 }, + { name = "snowman1", price = 200 }, + { name = "snowman2", price = 200 }, + { name = "snowman3", price = 200 }, + { name = "snowman4", price = 200 }, + { name = "xmastree1", price = 200 }, + { name = "xmastree2", price = 200 }, + { name = "candycane", price = 200 }, + { name = "xmaspresent", price = 200 }, + -- Medical stuff, might want to be in an EMS only store + { name = "medbag", price = 0 }, + { name = "examlight", price = 0 }, + { name = "hazardbin", price = 0 }, + { name = "microscope", price = 0 }, + { name = "oscillator", price = 0 }, + { name = "medmachine", price = 0 }, + { name = "hospitalbed1", price = 0 }, + { name = "hospitalbed2", price = 0 }, + { name = "hospitalbedtable", price = 0 }, + { name = "medtable", price = 0 }, + { name = "bodybag", price = 0 }, + { name = "stretcher", price = 0 }, + }, + locations = { + vector3(-580.49, -1001.96, 21.33), + }, targets = { + { ped = `a_f_m_eastsa_02`, scenario = 'WORLD_HUMAN_COP_IDLES', loc = vector3(-580.49, -1001.96, 21.33), length = 0.7, width = 0.5, heading = 270.52, minZ = 37.5, maxZ = 38.9, distance = 2.5 }, + } + }, + ``` +
+ +
+ Sample qb shop + + ```lua + [14] = { + name = "roadworkbarrier", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 14, + }, + [15] = { + name = "roadclosedbarrier", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 15, + }, + [16] = { + name = "constructionbarrier", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 16, + }, + [17] = { + name = "constructionbarrier2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 17, + }, + [18] = { + name = "constructionbarrier3", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 18, + }, + [19] = { + name = "roadconebig", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 19, + }, + [20] = { + name = "roadcone", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 20, + }, + [21] = { + name = "roadpole", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 21, + }, + [22] = { + name = "worklight", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 22, + }, + [23] = { + name = "worklight2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 23, + }, + [24] = { + name = "worklight3", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 24, + }, + [25] = { + name = "constructiongenerator", + price = 500, + amount = 100, + info = {}, + type = "item", + slot = 25, + }, + [26] = { + name = "trafficdevice", + price = 500, + amount = 100, + info = {}, + type = "item", + slot = 26, + }, + [27] = { + name = "trafficdevice2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 27, + }, + [28] = { + name = "tent", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 28, + }, + [29] = { + name = "tent2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 29, + }, + [30] = { + name = "tent3", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 30, + }, + [31] = { + name = "tristarttable", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 31, + }, + [32] = { + name = "tristartbanner", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 32, + }, + [33] = { + name = "trifinishbanner", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 33, + }, + [34] = { + name = "plastictable", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 34, + }, + [35] = { + name = "plastictable2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 35, + }, + [36] = { + name = "woodtable", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 36, + }, + [37] = { + name = "woodtable2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 37, + }, + [38] = { + name = "beachtowel", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 38, + }, + [39] = { + name = "beachumbrella", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 39, + }, + [40] = { + name = "beachumbrella2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 40, + }, + [41] = { + name = "beachumbrella3", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 41, + }, + [42] = { + name = "beachumbrella4", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 42, + }, + [43] = { + name = "beachball", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 43, + }, + [44] = { + name = "greenscreen", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 44, + }, + [45] = { + name = "ropebarrier", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 45, + }, + [46] = { + name = "largesoccerball", + price = 2000, + amount = 100, + info = {}, + type = "item", + slot = 46, + }, + [47] = { + name = "soccerball", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 47, + }, + [48] = { + name = "sleepingbag", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 48, + }, + [49] = { + name = "ramp1", + price = 15000, + amount = 20, + info = {}, + type = "item", + slot = 49, + }, + [50] = { + name = "ramp2", + price = 15000, + amount = 20, + info = {}, + type = "item", + slot = 50, + }, + [51] = { + name = "ramp3", + price = 15000, + amount = 20, + info = {}, + type = "item", + slot = 51, + }, + [52] = { + name = "ramp4", + price = 15000, + amount = 20, + info = {}, + type = "item", + slot = 52, + }, + [53] = { + name = "ramp5", + price = 15000, + amount = 20, + info = {}, + type = "item", + slot = 53, + }, + [54] = { + name = "skateramp", + price = 15000, + amount = 20, + info = {}, + type = "item", + slot = 54, + }, + [55] = { + name = "meshfence1", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 55, + }, + [56] = { + name = "meshfence2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 56, + }, + [57] = { + name = "meshfence3", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 57, + }, + [58] = { + name = "canopy1", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 58, + }, + [59] = { + name = "canopy2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 59, + }, + [60] = { + name = "canopy3", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 60, + }, + [61] = { + name = "stepladder", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 61, + }, + [62] = { + name = "wheelbarrow", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 62, + }, + [63] = { + name = "warehousetrolly1", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 63, + }, + [64] = { + name = "warehousetrolly2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 64, + }, + [65] = { + name = "roomtrolly", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 65, + }, + [66] = { + name = "janitorcart1", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 66, + }, + [67] = { + name = "janitorcart2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 67, + }, + [68] = { + name = "metalcart", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 68, + }, + [69] = { + name = "teacart", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 69, + }, + [70] = { + name = "drinkcart", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 70, + }, + [71] = { + name = "handtruck1", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 71, + }, + [72] = { + name = "handtruck2", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 72, + }, + [73] = { + name = "trashbin", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 73, + }, + [74] = { + name = "cot", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 74, + }, + [75] = { + name = "mopbucket", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 75, + }, + [76] = { + name = "lawnmower", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 76, + }, + [77] = { + name = "toolchest", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 77, + }, + [78] = { + name = "carjack", + price = 200, + amount = 100, + info = {}, + type = "item", + slot = 78, + }, + [79] = { + name = "waterbarrel", + price = 500, + amount = 100, + info = {}, + type = "item", + slot = 79, + }, + ``` +
+ +6. If you want an item to be useable by players that are dead (such as a hospitalbed), you will need to make an update to qb-ambulancejob. Ambulancejob script has a thread that will continually run to put you back into the death animation. Look for the thread that has a check for `if not IsEntityPlayingAnim(ped, deadAnimDict, deadAnim, 3) then` and update it to the following: + ```lua + -- This resets the player back into the dead animation and runs it on a fast loop + -- If the player is sitting on a placeable prop, we dont want to reset the animation or it will kick them off of the prop + if ( + not exports['wp-placeables']:IsPlayerSittingOnPlaceableProp() and + not IsEntityPlayingAnim(ped, deadAnimDict, deadAnim, 3) + ) then + loadAnimDict(deadAnimDict) + TaskPlayAnim(ped, deadAnimDict, deadAnim, 1.0, 1.0, -1, 1, 0, 0, 0, 0) + end + ``` + +> Note: If you are using `ox` for any of the Framework options you need to uncomment `@ox_lib/init.lua` in the fxmanifest.lua. + +## Adding a new placeable item +If you want to add or modify a placeable item, follow the below instructions. + +> All props will receive the pickup action by default. + +1. First determine what prop(s) you want to add. It is recommended to use a site such as [Pleb Masters: Forge](https://forge.plebmasters.de/objects) to find props and the model names. +2. Add the new item to your items.lua file as you normally would (_don't forget to add an image to your inventory script_) +3. Add the item to the `Config.PlaceableProps` in config.lua + - If the prop is just a simple prop with no custom options then all you need to do is add: `{item = "", label = "}`. + - Required Fields: + - `item` - the name of the item you added to your items table + - `label` - the label of the item + - `model` - the model of the prop that will be spawned + - `isFrozen` - whether or not the prop will be frozen in place when it is spawned + - Optional Fields: + - `customTargetOptions` - use this if you want to add more options than just picking up the item + - `customPickupEvent` - use this if you want to add a custom event to be called when the item is picked up, rather than using the default handler + - If you want to put custom actions on the prop, then you will also need to include the `customTargetOptions`. + ```lua + local exampleCustomTargetOptions = { + event = "someScript:client:exampleEvent", + icon = "fas fa-chair", + label = "Example action", + } + + {item = "", model = "", customTargetOptions = exampleCustomTargetOptions} + ``` + - If you want to add custom action on pickup of the prop, you can add a `customPickupEvent`. Simply provide the name of the event that you want to call when the prop is picked up. _Most scenarios will not need this, but it is available if you need it._ + ```lua + {item = "", model = "", customPickupEvent = "someScript:client:customPickupEvent"} + + RegisterNetEvent('someScript:client:customPickupEvent', function(data) + -- Your custom logic goes here + + -- Use this event to handle the default pickup logic (removing prop, giving item back to player, etc) + TriggerEvent('wp-placeables:client:pickUpItem', data) + end) + ``` + - If you want the item to be a pushable object, utilize the default `pushTargetOptions`. If you also want the object to have the option to sit on it use `pushAndSitTargetOptions`. Most likely you will need to override the offset, rotation, and potentially the animations. Use the `setCustomTargetOptions()` helper function to override only the values you need and the rest will be copied. Reference the existing pushable objects to see how this is done. + ```lua + {item = "wheelbarrow", model = "prop_wheelbarrow01a", + customTargetOptions = setCustomTargetOptions( + pushAndSitTargetOptions, { + offset = {x = -0.4, y = -1.8, z = -0.6}, + rotation = {x = 0.0, y = 20.0, z = 90.0}, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + }, { + offset = {x = -0.25, y = 0.0, z = 1.4}, + rotation = {x = 13.0, y = 0.0, z = 255.0}, + animationDict = "anim@amb@business@bgen@bgen_no_work@", + animationName = "sit_phone_phoneputdown_idle_nowork", + } + ) + }, + ``` +> Ensure `item` matches the item you added in step 1 + +## Optional + +**Logging:** +- If you want to enable logging for the placement/pickup of items, set `Config.Log` equal to the logging framework you use, set as `'none'` if you do not want logs. Currently supports qb-logs by default. Modify the `CreateLog()` function in framework.lua to add support for your logging framework. + + +## Dependencies +- Framework: QBCore/ Qbox / ESX / Or other frameworks (_must implement framework specific solutions in framework.lua_) +- Inventory: QBCore / ESX / OX / or equivalent +- Notifications: QBCore / ESX / OX / or equivalent +- Target: qb-target / ox-target or equivalent script + +> If you are using a different script/framework than what we provide by default, simply add your solution to the framework.lua file, all framework specific logic is in this file. + +## Gallery +![wp-placeables-screenshot1](https://github.com/WaypointRP/wp-placeables/assets/18689469/0dda029f-3e62-4492-adf0-e8d77ad89994) +![wp-placeables-screenshot2](https://github.com/WaypointRP/wp-placeables/assets/18689469/7c279cff-1b0b-458b-9013-55f15dfc0a2e) +![wp-placeables-screenshot3](https://github.com/WaypointRP/wp-placeables/assets/18689469/bd2c99d7-de2c-415f-a9a4-d3946bac701b) +![wp-placeables-screenshot4](https://github.com/WaypointRP/wp-placeables/assets/18689469/71d10a9d-3140-4f36-a45c-4a8cc1130709) + +## Scripts that use Waypoint Placeables +Checkout these addon scripts that use Waypoint Placeables! + +- [Waypoint Fireworks](https://backsh00ter.tebex.io/package/5753511) +- [Waypoint Yogamats](https://github.com/WaypointRP/wp-yogamats) +- [Waypoint Printer](https://github.com/WaypointRP/wp-printer) +- [Waypoint Traffic Lights](https://github.com/WaypointRP/wp-trafficlights) +- [Waypoint Seats](https://github.com/WaypointRP/wp-seats) + +## Credit +@DonHulieo for providing insipiration and examples for structuring the framework.lua file. diff --git a/resources/wp-placeables/client/client.lua b/resources/wp-placeables/client/client.lua new file mode 100644 index 000000000..23bfec814 --- /dev/null +++ b/resources/wp-placeables/client/client.lua @@ -0,0 +1,24 @@ +function RequestNetworkControlOfObject(netId, itemEntity) + if NetworkDoesNetworkIdExist(netId) then + NetworkRequestControlOfNetworkId(netId) + while not NetworkHasControlOfNetworkId(netId) do + Wait(100) + NetworkRequestControlOfNetworkId(netId) + end + end + + if DoesEntityExist(itemEntity) then + NetworkRequestControlOfEntity(itemEntity) + while not NetworkHasControlOfEntity(itemEntity) do + Wait(100) + NetworkRequestControlOfEntity(itemEntity) + end + end +end + +function LoadAnimDict(dict) + while not HasAnimDictLoaded(dict) do + RequestAnimDict(dict) + Wait(10) + end +end diff --git a/resources/wp-placeables/client/placeables.lua b/resources/wp-placeables/client/placeables.lua new file mode 100644 index 000000000..85fde65aa --- /dev/null +++ b/resources/wp-placeables/client/placeables.lua @@ -0,0 +1,374 @@ +local animationDict = "pickup_object" +local animation = "pickup_low" +local isInPlaceItemMode = false + +-- Keeps track of the models that have already been set with target options, ensuring we don't create duplicate options for the same model +-- In some frameworks like OX, if you create targetOptions on a model that already has it, it will append the options, whereas +-- in QB it will override and only the last set of options will be used. We just need to add one option to the target model and then +-- the pickup event will use the statebag to determine the correct item to give back to the player +local targetModels = {} + +local function LoadPropDict(model) + while not HasModelLoaded(GetHashKey(model)) do + RequestModel(GetHashKey(model)) + Wait(10) + end +end + +-- Gets the direction the camera is looking for the raycast function +local function RotationToDirection(rotation) + local adjustedRotation = { + x = (math.pi / 180) * rotation.x, + y = (math.pi / 180) * rotation.y, + z = (math.pi / 180) * rotation.z, + } + local direction = { + x = -math.sin(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), + y = math.cos(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), + z = math.sin(adjustedRotation.x), + } + return direction +end + +-- Uses a RayCast to get the entity, coords, and whether we "hit" something with the raycast +-- Object passed in, is the current object that we want the raycast to ignore +local function RayCastGamePlayCamera(distance, object, raycastDetectWorldOnly) + local cameraRotation = GetGameplayCamRot() + local cameraCoord = GetGameplayCamCoord() + local direction = RotationToDirection(cameraRotation) + local destination = { + x = cameraCoord.x + direction.x * distance, + y = cameraCoord.y + direction.y * distance, + z = cameraCoord.z + direction.z * distance, + } + + -- Trace flag 4294967295 means the raycast will intersect with everything (including vehicles) + -- Trace flag 1 means the raycast will only intersect with the world (ignoring other entities like peds, cars, etc) + local traceFlag = 4294967295 + if raycastDetectWorldOnly then + traceFlag = 1 + end + + local a, hit, coords, d, entity = GetShapeTestResult(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, traceFlag, object, 0)) + return hit, coords, entity +end + +-- Used to Draw the text on the screen +local function Draw2DText(content, font, colour, scale, x, y) + SetTextFont(font) + SetTextScale(scale, scale) + SetTextColour(colour[1], colour[2], colour[3], 255) + SetTextEntry("STRING") + SetTextDropShadow(0, 0, 0, 0, 255) + SetTextDropShadow() + SetTextEdge(4, 0, 0, 0, 255) + SetTextOutline() + AddTextComponentString(content) + DrawText(x, y) +end + +-- This handles placing the actual item that is network synced +local function placeItem(item, coords, heading, shouldSnapToGround) + local ped = PlayerPedId() + local itemName = item.item + local itemModel = item.model + local shouldFreezeItem = item.isFrozen + + -- Cancel any active animation + ClearPedTasks(ped) + + Progressbar("place_item", "Placing " .. item.label, 750, false, true, { + disableMovement = false, + disableCarMovement = false, + disableMouse = false, + disableCombat = true, + }, { + animDict = animationDict, + anim = animation, + flags = 0, + }, nil, nil, function() -- Done + -- Stop playing the animation + StopAnimTask(ped, animationDict, animation, 1.0) + + -- Remove the item from the inventory + TriggerServerEvent("wp-placeables:server:RemoveItem", itemName) + + LoadPropDict(itemModel) + + -- Spawn prop on ground at the provided coords and heading + local obj = CreateObject(itemModel, GetEntityCoords(ped), true) + if obj ~= 0 then + SetEntityRotation(obj, 0.0, 0.0, heading, false, false) + SetEntityCoords(obj, coords) + + if shouldFreezeItem then + FreezeEntityPosition(obj, true) + end + + -- Some items dont go to the ground properly with this, and it actually makes them hover + if shouldSnapToGround then + PlaceObjectOnGroundProperly(obj) + end + + -- Use statebag property itemName to set the itemName on the entity. + -- This value is used to grant the correct item back to the player when they pick it up. + -- It also solves the issue of the same model being used for multiple items + Entity(obj).state:set("itemName", itemName, true) + + CreateLog(itemName, true) + end + + SetModelAsNoLongerNeeded(itemModel) + end, function() -- Cancel + StopAnimTask(ped, animationDict, animation, 1.0) + Notify("Canceled..", "error") + end) +end + +-- Starts a thread that puts the player into item placement mode +-- This will spawn a local object that only the player can see and move around to position it +-- Once the player places the object it will delete the local one and then create a new network synced object +local function startItemPlacementMode(item) + -- This is to prevent entering place mode multiple times if its already active + if isInPlaceItemMode then + Notify("Already placing an item", "error", 5000) + return + end + + isInPlaceItemMode = true + local ped = PlayerPedId() + local itemModel = item.model + + -- Create a local object for only this client (not synced to network) and make it transparent + local obj = CreateObject(itemModel, GetEntityCoords(ped), false, false) + SetEntityAlpha(obj, 150, false) + SetEntityCollision(obj, false, false) + + local zOffset = 0 + + -- This is used to determine if the raycast should only detect the world or if it should detect everything (including vehicles) + local raycastDetectWorldOnly = true + + CreateThread(function() + while isInPlaceItemMode do + -- Use raycast based on where the camera is pointed + local hit, coords, entity = RayCastGamePlayCamera(Config.ItemPlacementModeRadius, obj, raycastDetectWorldOnly) + + -- Move the object to the coords from the raycast + SetEntityCoords(obj, coords.x, coords.y, coords.z + zOffset) + + -- Display the controls + Draw2DText("[E] Place\n[Shift+E] Place on ground\n[Scroll Up/Down] Rotate\n[Shift+Scroll Up/Down] Raise/lower", 4, { 255, 255, 255, }, 0.4, 0.85, 0.85) + Draw2DText("[Scroll Click] Change mode\n[Right Click / Backspace] Exit place mode", 4, { 255, 255, 255, }, 0.4, 0.85, 0.945) + + -- Handle various key presses and actions + + -- Controls for placing item + + -- Pressed Shift + E - Place object on ground + if IsControlJustReleased(0, 38) and IsControlPressed(0, 21) then + isInPlaceItemMode = false + + local objHeading = GetEntityHeading(obj) + local snapToGround = true + + DeleteEntity(obj) + placeItem(item, vector3(coords.x, coords.y, coords.z + zOffset), objHeading, snapToGround) + + -- Pressed E - Place object at current position + elseif IsControlJustReleased(0, 38) then + isInPlaceItemMode = false + + local objHeading = GetEntityHeading(obj) + local snapToGround = false + + DeleteEntity(obj) + placeItem(item, vector3(coords.x, coords.y, coords.z + zOffset), objHeading, snapToGround) + end + + -- Controls for rotating item + + -- Mouse Wheel Up (and Shift not pressed), rotate by +10 degrees + if IsControlJustReleased(0, 241) and not IsControlPressed(0, 21) then + local objHeading = GetEntityHeading(obj) + SetEntityRotation(obj, 0.0, 0.0, objHeading + 10, false, false) + end + + -- Mouse Wheel Down (and shift not pressed), rotate by -10 degrees + if IsControlJustReleased(0, 242) and not IsControlPressed(0, 21) then + local objHeading = GetEntityHeading(obj) + SetEntityRotation(obj, 0.0, 0.0, objHeading - 10, false, false) + end + + -- Controls for raising/lowering item + + -- Shift + Mouse Wheel Up, move item up + if IsControlPressed(0, 21) and IsControlJustReleased(0, 241) then + zOffset = zOffset + 0.1 + if zOffset > Config.maxZOffset then + zOffset = Config.maxZOffset + end + end + + -- Shift + Mouse Wheel Down, move item down + if IsControlPressed(0, 21) and IsControlJustReleased(0, 242) then + zOffset = zOffset - 0.1 + if zOffset < Config.minZOffset then + zOffset = Config.minZOffset + end + end + + -- Mouse Wheel Click, change placement mode + if IsControlJustReleased(0, 348) then + raycastDetectWorldOnly = not raycastDetectWorldOnly + end + + -- Right click or Backspace to exit out of placement mode and delete the local object + if IsControlJustReleased(0, 177) then + isInPlaceItemMode = false + DeleteEntity(obj) + end + + Wait(1) + end + end) +end + +-- Handles picking up the prop, deleting it from the world and adding it to the players inventory +local function pickUpItem(itemData) + local ped = PlayerPedId() + local itemEntity = itemData.entity + local itemModel = itemData.itemModel + + -- When picking up the item, try to get the itemName from the statebag property first, else fallback to the itemName from the itemData provided by the target script + -- Using the statebag property ensures we get the correct item name if the prop model is shared by multiple items.. + local itemName = Entity(itemEntity).state.itemName or itemData.itemName + + if itemName then + -- Cancel any active animation + ClearPedTasks(ped) + + Progressbar("pickup_item", "Picking up item", 200, false, true, { + disableMovement = false, + disableCarMovement = false, + disableMouse = false, + disableCombat = true, + }, { + animDict = animationDict, + anim = animation, + flags = 0, + }, nil, nil, function() -- Done + -- Stop playing the animation + StopAnimTask(ped, animationDict, animation, 1.0) + + -- Add the item to the inventory + TriggerServerEvent("wp-placeables:server:AddItem", itemName) + + -- First request control of networkId and wait until have control of netId before deleting it + -- Item will not properly delete if the client doesn't have control of the networkId + local coords = GetEntityCoords(itemEntity) + local netId = NetworkGetNetworkIdFromEntity(itemEntity) + RequestNetworkControlOfObject(netId, itemEntity) + SetEntityAsMissionEntity(itemEntity, true, true) + DeleteEntity(itemEntity) + + local object = { coords = coords, model = itemModel, } + TriggerServerEvent("wp-placeables:server:deleteWorldObject", object) + + CreateLog(itemName, false) + end, function() -- Cancel + StopAnimTask(ped, animationDict, animation, 1.0) + Notify("Canceled..", "error") + end) + end +end + +RegisterNetEvent("wp-placeables:client:placeItem", function(item) + if not IsPedInAnyVehicle(PlayerPedId(), true) then + startItemPlacementMode(item) + else + Notify("You cannot place items while in a vehicle", "error", 5000) + end +end) + +RegisterNetEvent("wp-placeables:client:pickUpItem", function(data) + pickUpItem(data) +end) + +-- Setup each placeable prop to use QB target +-- Itemname is in the options so we know which item to give back when picked up +for _, prop in pairs(Config.PlaceableProps) do + local pickUpEvent = "wp-placeables:client:pickUpItem" + if prop.customPickupEvent then + pickUpEvent = prop.customPickupEvent + end + local targetOptions = { + { + event = pickUpEvent, + icon = "fas fa-hand-holding", + label = "Pick up", + itemName = prop.item, + itemModel = prop.model, + }, + } + + -- Add custom target options to the target options for this item prop + if prop.customTargetOptions then + for _, customOption in pairs(prop.customTargetOptions) do + -- Stamp the itemName and itemModel onto the data so the custom events have access to this info + customOption.itemName = prop.item + customOption.itemModel = prop.model + + targetOptions[#targetOptions + 1] = customOption + end + end + + -- Make sure we only define the target options once for each model + -- If you define the same model twice: + -- In qb-target, it will override the options, and the last one defined is used + -- In ox_target, it will append the options, resulting in N duplicate options + if not targetModels[prop.model] then + AddTargetModel(prop.model, { + options = targetOptions, + distance = 1.5, + }) + targetModels[prop.model] = true + end +end + +-- Delete the world object +-- object = {coords = coords, model = itemModel} +RegisterNetEvent("wp-placeables:client:deleteWorldObject", function(object) + local entity = GetClosestObjectOfType(object.coords.x, object.coords.y, object.coords.z, 0.1, object.model, false, false, false) + if DoesEntityExist(entity) then + SetEntityAsMissionEntity(entity, 1, 1) + DeleteObject(entity) + SetEntityAsNoLongerNeeded(entity) + end +end) + +-- Runs a thread to loop through the deleted world objects table and removes the item if it exists +-- This is to handle cases if the item were to have respawned +-- Disabling this for now since we dont need to care if the item respawns +-- There is currently an issue where this was being used for both player placed objects as well as world props +-- If you placed an item, picked it up and placed the same item down again, the cleanup thread would delete it since its at the same coords. +-- If we want to re-enable this, we need to find a way to only use this cleanup thread on world spawned props +-- AddEventHandler('QBCore:Client:OnPlayerLoaded', function() +-- QBCore.Functions.TriggerCallback('wp-placeables:server:GetDeletedWorldObjects', function(deletedObjects) +-- objects = deletedObjects +-- end) +-- end) +-- CreateThread(function() +-- while true do +-- for k = 1, #objects, 1 do +-- v = objects[k] +-- local entity = GetClosestObjectOfType(v.coords.x, v.coords.y, v.coords.z, 0.1, v.model, false, false, false) +-- if DoesEntityExist(entity) then +-- SetEntityAsMissionEntity(entity, 1, 1) +-- DeleteObject(entity) +-- SetEntityAsNoLongerNeeded(entity) +-- end +-- end +-- Wait(10000) +-- end +-- end) diff --git a/resources/wp-placeables/client/pushables.lua b/resources/wp-placeables/client/pushables.lua new file mode 100644 index 000000000..5001d09d1 --- /dev/null +++ b/resources/wp-placeables/client/pushables.lua @@ -0,0 +1,156 @@ +local isAttached = false +local isSittingOnObject = false +local pushableObject = nil + +-- Detaches the object from the player, stops the animation, and resets the variables +local function ReleasePushableObject() + DetachEntity(pushableObject, false, true) + SetEntityCollision(pushableObject, true, true) + ClearPedTasksImmediately(PlayerPedId()) + + -- Reset variables + isAttached = false + isSittingOnObject = false + pushableObject = nil +end + +-- Runs a thread while player is attached to the pushable object, disables some keys and listens for E keypress to release the object +-- Also checks that player is still in the animation, if not then puts them back into the animation +local function PushableObjectAttachedThread(animDict, anim) + CreateThread(function() + while isAttached do + -- Disables attacking controls + DisableControlAction(0, 24, true) -- disable attack + DisableControlAction(0, 25, true) -- disable aim + DisableControlAction(0, 47, true) -- disable weapon + DisableControlAction(0, 58, true) -- disable weapon + DisableControlAction(0, 263, true) -- disable melee + DisableControlAction(0, 264, true) -- disable melee + DisableControlAction(0, 257, true) -- disable melee + DisableControlAction(0, 140, true) -- disable melee + DisableControlAction(0, 141, true) -- disable melee + DisableControlAction(0, 142, true) -- disable melee + DisableControlAction(0, 143, true) -- disable melee + + -- Check to see if animation is still playing, if not then put the player back in the animation + local playerPed = PlayerPedId() + if not IsEntityPlayingAnim(playerPed, animDict, anim, 3) and not IsPedRagdoll(playerPed) then + local animFlag = isSittingOnObject and 5 or 51 + ClearPedTasks(playerPed) + LoadAnimDict(animDict) + TaskPlayAnim(playerPed, animDict, anim, 3.0, 3.0, -1, animFlag, 0, 0, 0, 0) + end + + -- Pressed E + if IsControlJustPressed(0, 38) then + ReleasePushableObject() + end + + Wait(5) -- Needs to be a small number so that player doesnt need to spam press E to get it to take + end + end) +end + +-- Attaches the object to the player and plays a pushing animation +local function PushObject(data) + local PlayerPed = PlayerPedId() + + pushableObject = data.entity + + if pushableObject then + local netId = NetworkGetNetworkIdFromEntity(pushableObject) + RequestNetworkControlOfObject(netId, pushableObject) + + LoadAnimDict(data.animationPushOptions.animationDict) + TaskPlayAnim(PlayerPed, data.animationPushOptions.animationDict, data.animationPushOptions.animationName, 8.0, 8.0, -1, 51, 0, 0, 0, 0) + + local offset = data.animationPushOptions.offset + local rotation = data.animationPushOptions.rotation + + SetTimeout(150, function() + isAttached = true + SetEntityCollision(pushableObject, false, false) + AttachEntityToEntity( + pushableObject, + PlayerPed, + GetPedBoneIndex(PlayerPed, 28422), + offset.x, + offset.y, + offset.z, + rotation.x, + rotation.y, + rotation.z, + false, -- p9 + false, -- usesoftpinner + true, -- collision + false, -- isPed + 2, -- rotationorder + true -- fixrot + ) + + PushableObjectAttachedThread(data.animationPushOptions.animationDict, data.animationPushOptions.animationName) + end) + end +end + +-- Attaches player to object and plays the sitting animation +local function SitOnObject(data) + local PlayerPed = PlayerPedId() + + pushableObject = data.entity + + if pushableObject ~= nil then + LoadAnimDict(data.animationSitOptions.animationDict) + TaskPlayAnim(PlayerPed, data.animationSitOptions.animationDict, data.animationSitOptions.animationName, 8.0, 8.0, -1, 5, 0, 0, 0, 0) + + local offset = data.animationSitOptions.offset + local rotation = data.animationSitOptions.rotation + + SetTimeout(150, function() + isAttached = true + isSittingOnObject = true + AttachEntityToEntity( + PlayerPed, + pushableObject, + GetPedBoneIndex(PlayerPed, 11816), + offset.x, + offset.y, + offset.z, + rotation.x, + rotation.y, + rotation.z, + false, -- p9 + false, -- usesoftpinner + false, -- collision -- if this is true, then the peds body will collide with things as you push it around + true, -- isPed + 2, -- rotationorder + true -- fixrot + ) + + PushableObjectAttachedThread(data.animationSitOptions.animationDict, data.animationSitOptions.animationName) + end) + end +end + +AddEventHandler("onResourceStop", function(resource) + if resource == GetCurrentResourceName() then + if pushableObject then + ReleasePushableObject() + DeleteObject(pushableObject) + ClearPedTasksImmediately(PlayerPedId()) + end + end +end) + +RegisterNetEvent("wp-placeables:client:pushObject", function(data) + PushObject(data) +end) + +RegisterNetEvent("wp-placeables:client:sitOnObject", function(data) + SitOnObject(data) +end) + +local function IsPlayerSittingOnPlaceableProp() + return isSittingOnObject +end +exports("IsPlayerSittingOnPlaceableProp", IsPlayerSittingOnPlaceableProp) diff --git a/resources/wp-placeables/fxmanifest.lua b/resources/wp-placeables/fxmanifest.lua new file mode 100644 index 000000000..71b42e09d --- /dev/null +++ b/resources/wp-placeables/fxmanifest.lua @@ -0,0 +1,24 @@ +fx_version "cerulean" +game "gta5" + +description "Waypoint Placeables" +author "BackSH00TER - Waypoint RP" +version "1.1.3" + +shared_script { + -- "@ox_lib/init.lua", -- Uncomment this if you are planning to integrate with any ox scripts + "shared/config.lua", + "shared/framework.lua", +} + +client_scripts { + "client/client.lua", + "client/pushables.lua", + "client/placeables.lua", +} + +server_scripts { + "server/server.lua", +} + +lua54 "yes" diff --git a/resources/wp-placeables/images/beachball.png b/resources/wp-placeables/images/beachball.png new file mode 100644 index 000000000..9736bf006 Binary files /dev/null and b/resources/wp-placeables/images/beachball.png differ diff --git a/resources/wp-placeables/images/beachtowel.png b/resources/wp-placeables/images/beachtowel.png new file mode 100644 index 000000000..547bb79a2 Binary files /dev/null and b/resources/wp-placeables/images/beachtowel.png differ diff --git a/resources/wp-placeables/images/beachumbrella.png b/resources/wp-placeables/images/beachumbrella.png new file mode 100644 index 000000000..d16889341 Binary files /dev/null and b/resources/wp-placeables/images/beachumbrella.png differ diff --git a/resources/wp-placeables/images/bodybag.png b/resources/wp-placeables/images/bodybag.png new file mode 100644 index 000000000..7492058f0 Binary files /dev/null and b/resources/wp-placeables/images/bodybag.png differ diff --git a/resources/wp-placeables/images/campchair_blue.png b/resources/wp-placeables/images/campchair_blue.png new file mode 100644 index 000000000..21a552488 Binary files /dev/null and b/resources/wp-placeables/images/campchair_blue.png differ diff --git a/resources/wp-placeables/images/campchair_green.png b/resources/wp-placeables/images/campchair_green.png new file mode 100644 index 000000000..0b31dc711 Binary files /dev/null and b/resources/wp-placeables/images/campchair_green.png differ diff --git a/resources/wp-placeables/images/campchair_plaid.png b/resources/wp-placeables/images/campchair_plaid.png new file mode 100644 index 000000000..ff92cd765 Binary files /dev/null and b/resources/wp-placeables/images/campchair_plaid.png differ diff --git a/resources/wp-placeables/images/campfire.png b/resources/wp-placeables/images/campfire.png new file mode 100644 index 000000000..a444073e5 Binary files /dev/null and b/resources/wp-placeables/images/campfire.png differ diff --git a/resources/wp-placeables/images/candycane.png b/resources/wp-placeables/images/candycane.png new file mode 100644 index 000000000..59d437f0b Binary files /dev/null and b/resources/wp-placeables/images/candycane.png differ diff --git a/resources/wp-placeables/images/canopy.png b/resources/wp-placeables/images/canopy.png new file mode 100644 index 000000000..40c9b072a Binary files /dev/null and b/resources/wp-placeables/images/canopy.png differ diff --git a/resources/wp-placeables/images/cargobox1.png b/resources/wp-placeables/images/cargobox1.png new file mode 100644 index 000000000..b97780b03 Binary files /dev/null and b/resources/wp-placeables/images/cargobox1.png differ diff --git a/resources/wp-placeables/images/cargobox2.png b/resources/wp-placeables/images/cargobox2.png new file mode 100644 index 000000000..c7f2413e2 Binary files /dev/null and b/resources/wp-placeables/images/cargobox2.png differ diff --git a/resources/wp-placeables/images/cargobox3.png b/resources/wp-placeables/images/cargobox3.png new file mode 100644 index 000000000..bc10b6c2d Binary files /dev/null and b/resources/wp-placeables/images/cargobox3.png differ diff --git a/resources/wp-placeables/images/cargobox4.png b/resources/wp-placeables/images/cargobox4.png new file mode 100644 index 000000000..95ee80312 Binary files /dev/null and b/resources/wp-placeables/images/cargobox4.png differ diff --git a/resources/wp-placeables/images/cargobox5.png b/resources/wp-placeables/images/cargobox5.png new file mode 100644 index 000000000..fa14924cc Binary files /dev/null and b/resources/wp-placeables/images/cargobox5.png differ diff --git a/resources/wp-placeables/images/cargobox6.png b/resources/wp-placeables/images/cargobox6.png new file mode 100644 index 000000000..d47910bec Binary files /dev/null and b/resources/wp-placeables/images/cargobox6.png differ diff --git a/resources/wp-placeables/images/cargobox7.png b/resources/wp-placeables/images/cargobox7.png new file mode 100644 index 000000000..7e1c20c8b Binary files /dev/null and b/resources/wp-placeables/images/cargobox7.png differ diff --git a/resources/wp-placeables/images/cargobox8.png b/resources/wp-placeables/images/cargobox8.png new file mode 100644 index 000000000..39aa28fda Binary files /dev/null and b/resources/wp-placeables/images/cargobox8.png differ diff --git a/resources/wp-placeables/images/carjack.png b/resources/wp-placeables/images/carjack.png new file mode 100644 index 000000000..6f0a32bb6 Binary files /dev/null and b/resources/wp-placeables/images/carjack.png differ diff --git a/resources/wp-placeables/images/constructionbarrier.png b/resources/wp-placeables/images/constructionbarrier.png new file mode 100644 index 000000000..665256506 Binary files /dev/null and b/resources/wp-placeables/images/constructionbarrier.png differ diff --git a/resources/wp-placeables/images/constructionbarrier2.png b/resources/wp-placeables/images/constructionbarrier2.png new file mode 100644 index 000000000..6116ebce9 Binary files /dev/null and b/resources/wp-placeables/images/constructionbarrier2.png differ diff --git a/resources/wp-placeables/images/constructionbarrier3.png b/resources/wp-placeables/images/constructionbarrier3.png new file mode 100644 index 000000000..4d215797d Binary files /dev/null and b/resources/wp-placeables/images/constructionbarrier3.png differ diff --git a/resources/wp-placeables/images/constructiongenerator.png b/resources/wp-placeables/images/constructiongenerator.png new file mode 100644 index 000000000..885daa543 Binary files /dev/null and b/resources/wp-placeables/images/constructiongenerator.png differ diff --git a/resources/wp-placeables/images/cot.png b/resources/wp-placeables/images/cot.png new file mode 100644 index 000000000..baf61e204 Binary files /dev/null and b/resources/wp-placeables/images/cot.png differ diff --git a/resources/wp-placeables/images/crate1.png b/resources/wp-placeables/images/crate1.png new file mode 100644 index 000000000..476e1bc12 Binary files /dev/null and b/resources/wp-placeables/images/crate1.png differ diff --git a/resources/wp-placeables/images/crate2.png b/resources/wp-placeables/images/crate2.png new file mode 100644 index 000000000..bb3086b85 Binary files /dev/null and b/resources/wp-placeables/images/crate2.png differ diff --git a/resources/wp-placeables/images/crate3.png b/resources/wp-placeables/images/crate3.png new file mode 100644 index 000000000..03eaa1367 Binary files /dev/null and b/resources/wp-placeables/images/crate3.png differ diff --git a/resources/wp-placeables/images/crate4.png b/resources/wp-placeables/images/crate4.png new file mode 100644 index 000000000..bc1288aa1 Binary files /dev/null and b/resources/wp-placeables/images/crate4.png differ diff --git a/resources/wp-placeables/images/crate5.png b/resources/wp-placeables/images/crate5.png new file mode 100644 index 000000000..8f532c5c6 Binary files /dev/null and b/resources/wp-placeables/images/crate5.png differ diff --git a/resources/wp-placeables/images/drinkcart.png b/resources/wp-placeables/images/drinkcart.png new file mode 100644 index 000000000..a7d5428c1 Binary files /dev/null and b/resources/wp-placeables/images/drinkcart.png differ diff --git a/resources/wp-placeables/images/examlight.png b/resources/wp-placeables/images/examlight.png new file mode 100644 index 000000000..73daed7f8 Binary files /dev/null and b/resources/wp-placeables/images/examlight.png differ diff --git a/resources/wp-placeables/images/folding_chair.png b/resources/wp-placeables/images/folding_chair.png new file mode 100644 index 000000000..a5b440cbb Binary files /dev/null and b/resources/wp-placeables/images/folding_chair.png differ diff --git a/resources/wp-placeables/images/greenscreen.png b/resources/wp-placeables/images/greenscreen.png new file mode 100644 index 000000000..1bbaec6d8 Binary files /dev/null and b/resources/wp-placeables/images/greenscreen.png differ diff --git a/resources/wp-placeables/images/handtruck.png b/resources/wp-placeables/images/handtruck.png new file mode 100644 index 000000000..842ed7fb5 Binary files /dev/null and b/resources/wp-placeables/images/handtruck.png differ diff --git a/resources/wp-placeables/images/hazardbin.png b/resources/wp-placeables/images/hazardbin.png new file mode 100644 index 000000000..4463739c0 Binary files /dev/null and b/resources/wp-placeables/images/hazardbin.png differ diff --git a/resources/wp-placeables/images/hobomattress.png b/resources/wp-placeables/images/hobomattress.png new file mode 100644 index 000000000..0e642d770 Binary files /dev/null and b/resources/wp-placeables/images/hobomattress.png differ diff --git a/resources/wp-placeables/images/hoboshelter.png b/resources/wp-placeables/images/hoboshelter.png new file mode 100644 index 000000000..b94d1c422 Binary files /dev/null and b/resources/wp-placeables/images/hoboshelter.png differ diff --git a/resources/wp-placeables/images/hobostove.png b/resources/wp-placeables/images/hobostove.png new file mode 100644 index 000000000..88ad78b50 Binary files /dev/null and b/resources/wp-placeables/images/hobostove.png differ diff --git a/resources/wp-placeables/images/hospitalbed1.png b/resources/wp-placeables/images/hospitalbed1.png new file mode 100644 index 000000000..9e3fc05fc Binary files /dev/null and b/resources/wp-placeables/images/hospitalbed1.png differ diff --git a/resources/wp-placeables/images/hospitalbed2.png b/resources/wp-placeables/images/hospitalbed2.png new file mode 100644 index 000000000..a31ef53f4 Binary files /dev/null and b/resources/wp-placeables/images/hospitalbed2.png differ diff --git a/resources/wp-placeables/images/hospitalbedtable.png b/resources/wp-placeables/images/hospitalbedtable.png new file mode 100644 index 000000000..a9ed19e40 Binary files /dev/null and b/resources/wp-placeables/images/hospitalbedtable.png differ diff --git a/resources/wp-placeables/images/janitorcart1.png b/resources/wp-placeables/images/janitorcart1.png new file mode 100644 index 000000000..296154227 Binary files /dev/null and b/resources/wp-placeables/images/janitorcart1.png differ diff --git a/resources/wp-placeables/images/janitorcart2.png b/resources/wp-placeables/images/janitorcart2.png new file mode 100644 index 000000000..35834b328 Binary files /dev/null and b/resources/wp-placeables/images/janitorcart2.png differ diff --git a/resources/wp-placeables/images/largetent.png b/resources/wp-placeables/images/largetent.png new file mode 100644 index 000000000..5b04ea85a Binary files /dev/null and b/resources/wp-placeables/images/largetent.png differ diff --git a/resources/wp-placeables/images/lawnmower.png b/resources/wp-placeables/images/lawnmower.png new file mode 100644 index 000000000..2c888485a Binary files /dev/null and b/resources/wp-placeables/images/lawnmower.png differ diff --git a/resources/wp-placeables/images/medbag.png b/resources/wp-placeables/images/medbag.png new file mode 100644 index 000000000..957f2d432 Binary files /dev/null and b/resources/wp-placeables/images/medbag.png differ diff --git a/resources/wp-placeables/images/medmachine.png b/resources/wp-placeables/images/medmachine.png new file mode 100644 index 000000000..cf4a94af5 Binary files /dev/null and b/resources/wp-placeables/images/medmachine.png differ diff --git a/resources/wp-placeables/images/medtable.png b/resources/wp-placeables/images/medtable.png new file mode 100644 index 000000000..6cd7f99a1 Binary files /dev/null and b/resources/wp-placeables/images/medtable.png differ diff --git a/resources/wp-placeables/images/meshfence.png b/resources/wp-placeables/images/meshfence.png new file mode 100644 index 000000000..2e7345310 Binary files /dev/null and b/resources/wp-placeables/images/meshfence.png differ diff --git a/resources/wp-placeables/images/metalcart.png b/resources/wp-placeables/images/metalcart.png new file mode 100644 index 000000000..39b50b772 Binary files /dev/null and b/resources/wp-placeables/images/metalcart.png differ diff --git a/resources/wp-placeables/images/metalramp.png b/resources/wp-placeables/images/metalramp.png new file mode 100644 index 000000000..88c961f02 Binary files /dev/null and b/resources/wp-placeables/images/metalramp.png differ diff --git a/resources/wp-placeables/images/microscope.png b/resources/wp-placeables/images/microscope.png new file mode 100644 index 000000000..b5c7ea6d1 Binary files /dev/null and b/resources/wp-placeables/images/microscope.png differ diff --git a/resources/wp-placeables/images/mopbucket.png b/resources/wp-placeables/images/mopbucket.png new file mode 100644 index 000000000..369ac4eeb Binary files /dev/null and b/resources/wp-placeables/images/mopbucket.png differ diff --git a/resources/wp-placeables/images/oldtent.png b/resources/wp-placeables/images/oldtent.png new file mode 100644 index 000000000..f2407d5c7 Binary files /dev/null and b/resources/wp-placeables/images/oldtent.png differ diff --git a/resources/wp-placeables/images/oscillator.png b/resources/wp-placeables/images/oscillator.png new file mode 100644 index 000000000..11f3ac5ca Binary files /dev/null and b/resources/wp-placeables/images/oscillator.png differ diff --git a/resources/wp-placeables/images/pallet1.png b/resources/wp-placeables/images/pallet1.png new file mode 100644 index 000000000..d89234dfa Binary files /dev/null and b/resources/wp-placeables/images/pallet1.png differ diff --git a/resources/wp-placeables/images/pallet2.png b/resources/wp-placeables/images/pallet2.png new file mode 100644 index 000000000..5a21abf46 Binary files /dev/null and b/resources/wp-placeables/images/pallet2.png differ diff --git a/resources/wp-placeables/images/pallet3.png b/resources/wp-placeables/images/pallet3.png new file mode 100644 index 000000000..fea01171f Binary files /dev/null and b/resources/wp-placeables/images/pallet3.png differ diff --git a/resources/wp-placeables/images/pallet4.png b/resources/wp-placeables/images/pallet4.png new file mode 100644 index 000000000..eda857541 Binary files /dev/null and b/resources/wp-placeables/images/pallet4.png differ diff --git a/resources/wp-placeables/images/pallet5.png b/resources/wp-placeables/images/pallet5.png new file mode 100644 index 000000000..279d92d95 Binary files /dev/null and b/resources/wp-placeables/images/pallet5.png differ diff --git a/resources/wp-placeables/images/plastic_chair.png b/resources/wp-placeables/images/plastic_chair.png new file mode 100644 index 000000000..e53727080 Binary files /dev/null and b/resources/wp-placeables/images/plastic_chair.png differ diff --git a/resources/wp-placeables/images/plastictable.png b/resources/wp-placeables/images/plastictable.png new file mode 100644 index 000000000..0070e7976 Binary files /dev/null and b/resources/wp-placeables/images/plastictable.png differ diff --git a/resources/wp-placeables/images/roadclosedbarrier.png b/resources/wp-placeables/images/roadclosedbarrier.png new file mode 100644 index 000000000..ae6241f68 Binary files /dev/null and b/resources/wp-placeables/images/roadclosedbarrier.png differ diff --git a/resources/wp-placeables/images/roadcone.png b/resources/wp-placeables/images/roadcone.png new file mode 100644 index 000000000..2540755de Binary files /dev/null and b/resources/wp-placeables/images/roadcone.png differ diff --git a/resources/wp-placeables/images/roadconebig.png b/resources/wp-placeables/images/roadconebig.png new file mode 100644 index 000000000..5f2a6b791 Binary files /dev/null and b/resources/wp-placeables/images/roadconebig.png differ diff --git a/resources/wp-placeables/images/roadpole.png b/resources/wp-placeables/images/roadpole.png new file mode 100644 index 000000000..b11074406 Binary files /dev/null and b/resources/wp-placeables/images/roadpole.png differ diff --git a/resources/wp-placeables/images/roadworkahead.png b/resources/wp-placeables/images/roadworkahead.png new file mode 100644 index 000000000..679e163f4 Binary files /dev/null and b/resources/wp-placeables/images/roadworkahead.png differ diff --git a/resources/wp-placeables/images/roomtrolly.png b/resources/wp-placeables/images/roomtrolly.png new file mode 100644 index 000000000..f539f4ef6 Binary files /dev/null and b/resources/wp-placeables/images/roomtrolly.png differ diff --git a/resources/wp-placeables/images/ropebarrier.png b/resources/wp-placeables/images/ropebarrier.png new file mode 100644 index 000000000..b84ae51a9 Binary files /dev/null and b/resources/wp-placeables/images/ropebarrier.png differ diff --git a/resources/wp-placeables/images/sexdoll.png b/resources/wp-placeables/images/sexdoll.png new file mode 100644 index 000000000..785011cba Binary files /dev/null and b/resources/wp-placeables/images/sexdoll.png differ diff --git a/resources/wp-placeables/images/shoppingcart.png b/resources/wp-placeables/images/shoppingcart.png new file mode 100644 index 000000000..5ac54c222 Binary files /dev/null and b/resources/wp-placeables/images/shoppingcart.png differ diff --git a/resources/wp-placeables/images/skateramp.png b/resources/wp-placeables/images/skateramp.png new file mode 100644 index 000000000..702d134b4 Binary files /dev/null and b/resources/wp-placeables/images/skateramp.png differ diff --git a/resources/wp-placeables/images/sleepingbag.png b/resources/wp-placeables/images/sleepingbag.png new file mode 100644 index 000000000..26f3bc33e Binary files /dev/null and b/resources/wp-placeables/images/sleepingbag.png differ diff --git a/resources/wp-placeables/images/snowman1.png b/resources/wp-placeables/images/snowman1.png new file mode 100644 index 000000000..72161c72e Binary files /dev/null and b/resources/wp-placeables/images/snowman1.png differ diff --git a/resources/wp-placeables/images/snowman2.png b/resources/wp-placeables/images/snowman2.png new file mode 100644 index 000000000..f80ba5d18 Binary files /dev/null and b/resources/wp-placeables/images/snowman2.png differ diff --git a/resources/wp-placeables/images/snowman3.png b/resources/wp-placeables/images/snowman3.png new file mode 100644 index 000000000..b33fe4af1 Binary files /dev/null and b/resources/wp-placeables/images/snowman3.png differ diff --git a/resources/wp-placeables/images/snowman4.png b/resources/wp-placeables/images/snowman4.png new file mode 100644 index 000000000..a39c72832 Binary files /dev/null and b/resources/wp-placeables/images/snowman4.png differ diff --git a/resources/wp-placeables/images/soccerball.png b/resources/wp-placeables/images/soccerball.png new file mode 100644 index 000000000..184b1d57e Binary files /dev/null and b/resources/wp-placeables/images/soccerball.png differ diff --git a/resources/wp-placeables/images/stepladder.png b/resources/wp-placeables/images/stepladder.png new file mode 100644 index 000000000..a8bfe7b06 Binary files /dev/null and b/resources/wp-placeables/images/stepladder.png differ diff --git a/resources/wp-placeables/images/stretcher.png b/resources/wp-placeables/images/stretcher.png new file mode 100644 index 000000000..50e989bb0 Binary files /dev/null and b/resources/wp-placeables/images/stretcher.png differ diff --git a/resources/wp-placeables/images/teacart.png b/resources/wp-placeables/images/teacart.png new file mode 100644 index 000000000..45ecab061 Binary files /dev/null and b/resources/wp-placeables/images/teacart.png differ diff --git a/resources/wp-placeables/images/tent.png b/resources/wp-placeables/images/tent.png new file mode 100644 index 000000000..91aa378fa Binary files /dev/null and b/resources/wp-placeables/images/tent.png differ diff --git a/resources/wp-placeables/images/toolchest.png b/resources/wp-placeables/images/toolchest.png new file mode 100644 index 000000000..1e30a1bec Binary files /dev/null and b/resources/wp-placeables/images/toolchest.png differ diff --git a/resources/wp-placeables/images/trafficdevice.png b/resources/wp-placeables/images/trafficdevice.png new file mode 100644 index 000000000..a77413578 Binary files /dev/null and b/resources/wp-placeables/images/trafficdevice.png differ diff --git a/resources/wp-placeables/images/trashbin.png b/resources/wp-placeables/images/trashbin.png new file mode 100644 index 000000000..5509ed633 Binary files /dev/null and b/resources/wp-placeables/images/trashbin.png differ diff --git a/resources/wp-placeables/images/trifinishbanner.png b/resources/wp-placeables/images/trifinishbanner.png new file mode 100644 index 000000000..829841d5a Binary files /dev/null and b/resources/wp-placeables/images/trifinishbanner.png differ diff --git a/resources/wp-placeables/images/tristartbanner.png b/resources/wp-placeables/images/tristartbanner.png new file mode 100644 index 000000000..2cee4c27c Binary files /dev/null and b/resources/wp-placeables/images/tristartbanner.png differ diff --git a/resources/wp-placeables/images/tristarttable.png b/resources/wp-placeables/images/tristarttable.png new file mode 100644 index 000000000..cf6af44e3 Binary files /dev/null and b/resources/wp-placeables/images/tristarttable.png differ diff --git a/resources/wp-placeables/images/warehousetrolly1.png b/resources/wp-placeables/images/warehousetrolly1.png new file mode 100644 index 000000000..f02a94053 Binary files /dev/null and b/resources/wp-placeables/images/warehousetrolly1.png differ diff --git a/resources/wp-placeables/images/warehousetrolly2.png b/resources/wp-placeables/images/warehousetrolly2.png new file mode 100644 index 000000000..a1be6e351 Binary files /dev/null and b/resources/wp-placeables/images/warehousetrolly2.png differ diff --git a/resources/wp-placeables/images/waterbarrel.png b/resources/wp-placeables/images/waterbarrel.png new file mode 100644 index 000000000..0f71400d8 Binary files /dev/null and b/resources/wp-placeables/images/waterbarrel.png differ diff --git a/resources/wp-placeables/images/wheelbarrow.png b/resources/wp-placeables/images/wheelbarrow.png new file mode 100644 index 000000000..3ffc35fe1 Binary files /dev/null and b/resources/wp-placeables/images/wheelbarrow.png differ diff --git a/resources/wp-placeables/images/woodramp.png b/resources/wp-placeables/images/woodramp.png new file mode 100644 index 000000000..02df6928b Binary files /dev/null and b/resources/wp-placeables/images/woodramp.png differ diff --git a/resources/wp-placeables/images/woodtable.png b/resources/wp-placeables/images/woodtable.png new file mode 100644 index 000000000..0242320d4 Binary files /dev/null and b/resources/wp-placeables/images/woodtable.png differ diff --git a/resources/wp-placeables/images/worklight.png b/resources/wp-placeables/images/worklight.png new file mode 100644 index 000000000..915377490 Binary files /dev/null and b/resources/wp-placeables/images/worklight.png differ diff --git a/resources/wp-placeables/images/worklight2.png b/resources/wp-placeables/images/worklight2.png new file mode 100644 index 000000000..c342e0c93 Binary files /dev/null and b/resources/wp-placeables/images/worklight2.png differ diff --git a/resources/wp-placeables/images/worklight3.png b/resources/wp-placeables/images/worklight3.png new file mode 100644 index 000000000..31e85bd5d Binary files /dev/null and b/resources/wp-placeables/images/worklight3.png differ diff --git a/resources/wp-placeables/images/xmaspresent.png b/resources/wp-placeables/images/xmaspresent.png new file mode 100644 index 000000000..829fe4bb9 Binary files /dev/null and b/resources/wp-placeables/images/xmaspresent.png differ diff --git a/resources/wp-placeables/images/xmastree1.png b/resources/wp-placeables/images/xmastree1.png new file mode 100644 index 000000000..e304af91b Binary files /dev/null and b/resources/wp-placeables/images/xmastree1.png differ diff --git a/resources/wp-placeables/images/xmastree2.png b/resources/wp-placeables/images/xmastree2.png new file mode 100644 index 000000000..a761f1d1e Binary files /dev/null and b/resources/wp-placeables/images/xmastree2.png differ diff --git a/resources/wp-placeables/server/server.lua b/resources/wp-placeables/server/server.lua new file mode 100644 index 000000000..c5eb1539c --- /dev/null +++ b/resources/wp-placeables/server/server.lua @@ -0,0 +1,37 @@ +-- Setup all the placeable props as useable items +for _, prop in pairs(Config.PlaceableProps) do + CreateUseableItem(prop.item, function(source, item) + TriggerClientEvent("wp-placeables:client:placeItem", source, prop) + end) +end + +-- Checks the config to see if the item is valid +local function containsItem(item) + for i = 1, #Config.PlaceableProps do + local v = Config.PlaceableProps[i] + if v.item == item then + return true + end + end +end + +-- This function is to handle the syncing of deleting world props between all clients +RegisterServerEvent("wp-placeables:server:deleteWorldObject", function(object) + TriggerClientEvent("wp-placeables:client:deleteWorldObject", -1, object) +end) + +RegisterNetEvent("wp-placeables:server:RemoveItem", function(itemName) + local src = source + RemoveItem(src, itemName, 1) +end) + +RegisterNetEvent("wp-placeables:server:AddItem", function(itemName) + local src = source + + if not containsItem(itemName) then + print(string.format("%s - tried to spawn an item that does not exist in the config (%s)", src, itemName)) + return + end + + AddItem(src, itemName, 1) +end) diff --git a/resources/wp-placeables/shared/config.lua b/resources/wp-placeables/shared/config.lua new file mode 100644 index 000000000..afd0a6fbb --- /dev/null +++ b/resources/wp-placeables/shared/config.lua @@ -0,0 +1,636 @@ +Config = {} +------------------------------------ +-- FRAMEWORK / SCRIPT CONFIGURATION +-- Adjust these settings to match the framework and scripts you are using +-- Note: If using ox for any option, enable @ox_lib/init.lua in the manifest! +------------------------------------ + +--- @type "qb" | "qbx" | "esx" +Config.Framework = "qb" + +-- The notification script you are using. +--- @type "qb" | "esx" | "ox" | "none" +Config.Notify = "qb" + +-- The target script you are using. +--- @type "qb" | "ox" +Config.Target = "qb" + +-- The inventory script you are using. +--- @type "qb" | "esx" | "ox" +Config.Inventory = "qb" + +-- The progress bar script you are using. +--- @type "qb" | "ox" | "none" +Config.ProgessBar = "qb" + +-- The logging script you are using. +--- @type "qb" | "none" +Config.Log = "qb" + +------------------------------------ +--- END FRAMEWORK / SCRIPT CONFIGURATION +------------------------------------ + +Config.ItemPlacementModeRadius = 10.0 -- Object can only be placed within this radius of the player + +-- These are necessary so people can't place props far away +Config.minZOffset = -2.0 -- The min z offset for placing objects +Config.maxZOffset = 2.0 -- The max z offset for placing objects + +-- Creates a deep copy of the table +-- This is necessary for getting around luas pass by reference of tables +--- @param orig table The table to be copied +--- @return table The deep copied table +local function deepcopy(orig) -- modified the deep copy function from http://lua-users.org/wiki/CopyTable + local orig_type = type(orig) + local copy + if orig_type == "table" then + if not orig.canOpen or orig.canOpen() then + local toRemove = {} + copy = {} + for orig_key, orig_value in next, orig, nil do + if type(orig_value) == "table" then + if not orig_value.canOpen or orig_value.canOpen() then + copy[deepcopy(orig_key)] = deepcopy(orig_value) + else + toRemove[orig_key] = true + end + else + copy[deepcopy(orig_key)] = deepcopy(orig_value) + end + end + for i = 1, #toRemove do table.remove(copy, i) --[[ Using this to make sure all indexes get re-indexed and no empty spaces are in the radialmenu ]] end + if copy and next(copy) then setmetatable(copy, deepcopy(getmetatable(orig))) end + end + elseif orig_type ~= "function" then + copy = orig + end + return copy +end + +-- Helper function to combine default options with custom target options for items +--- @param targetOptions table[] The default target options for the item (e.g., pushTargetOptions for push-only objects and pushAndSitTargetOptions for push-and-sit objects) +--- @param animationPushOptions? table The custom animation options for pushing the object (modifying offsets, rotations, animations) +--- @param animationSitOptions? table The custom animation options for sitting on the object (modifying offsets, rotations, animations) +--- @param otherOptions? table[] Any other custom target options you want to add to the item +--- @return table[] The combined target options with customizations applied +local function setCustomTargetOptions(targetOptions, animationPushOptions, animationSitOptions, otherOptions) + local customTargetOptions = deepcopy(targetOptions) + + if animationPushOptions then + customTargetOptions[1].animationPushOptions = animationPushOptions + end + + if animationSitOptions then + customTargetOptions[2].animationSitOptions = animationSitOptions + end + + if otherOptions then + for i = 1, #otherOptions do + customTargetOptions[#customTargetOptions + 1] = otherOptions[i] + end + end + + return customTargetOptions +end + +-- Default target options + +local pushAndSitTargetOptions = { + { + event = "wp-placeables:client:pushObject", + icon = "fas fa-shopping-cart", + label = "Push object", + animationPushOptions = { + offset = { x = -0.4, y = -1.7, z = -0.3, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + }, + }, + { + event = "wp-placeables:client:sitOnObject", + icon = "fas fa-chair", + label = "Sit on object", + animationSitOptions = { + offset = { x = 0.0, y = 0.15, z = 0.85, }, + rotation = { x = 0.0, y = 10.0, z = 175.0, }, + animationDict = "anim@amb@business@bgen@bgen_no_work@", + animationName = "sit_phone_phoneputdown_idle_nowork", + }, + }, +} + +local pushTargetOptions = { + { + event = "wp-placeables:client:pushObject", + icon = "fas fa-shopping-cart", + label = "Push cart", + animationPushOptions = { + offset = { x = -0.4, y = -1.7, z = -0.3, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + }, + }, +} + +-- Define custom target options here for addon items + +-- Uncomment this line if you are using wp-seats +local chairCustomTargetOptions = { + { + event = "wp-seats:client:sitOnChair", + icon = "fas fa-chair", + label = "Sit down", + }, +} + +-- Uncomment this line if you are using wp-yogamats +-- local yogaCustomTargetOptions = { +-- { +-- event = "wp-yogamats:client:useYogaMat", +-- icon = "fas fa-pray", +-- label = "Do yoga", +-- }, +-- } + +-- Uncomment this line if you are using wp-printer +-- local printerCustomTargetOptions = { +-- { +-- event = "wp-printer:client:UsePrinter", +-- icon = "fas fa-print", +-- label = "Use printer", +-- }, +-- } + +-- Uncomment this line if you are using wp-fireworks +-- local fireworkCustomTargetOptions = { +-- { +-- event = 'wp-fireworks:client:lightFireworkFuse', +-- icon = "fa-solid fa-fire", +-- label = "Light fuse" +-- }, +-- { +-- event = 'wp-fireworks:client:buildFireworkSequence', +-- icon = 'fa-solid fa-link', +-- label = 'Add to sequence' +-- } +-- } + +-- Uncomment this line if you are using wp-trafficlights +-- local trafficLightCustomTargetOptions = { +-- { +-- event = "wp-trafficlights:client:OpenMenu", +-- icon = "fas fa-traffic-light", +-- label = "Remote control traffic light", +-- }, +-- } + +-- Uncomment this line if you are using wp-trafficlights +-- local trafficLightCustomPickupEvent = "wp-trafficlights:RemoveTrafficLight" + +--- @class PlaceableProp +--- @field item string The item name as defined in your items.lua +--- @field label string The label to be used for this item (displayed in the progress bar) +--- @field model string The prop model to be used for this item +--- @field isFrozen boolean Whether or not the prop should be frozen in place when placed +--- @field customTargetOptions? table[] Optional - Custom target options for this item, if it should do more than just pickup +--- @field customPickupEvent? string Optional - If you want to override the default pickup event, set this to the event you want to be called when the "pickup" target option is used + +-- Add the props you want to be placeable here +-- Every prop will have the "pickup" target option added by default (to override use customPickupEvent) +--- @type PlaceableProp[] +Config.PlaceableProps = { + -- Constructions props + { item = "roadworkbarrier", label = "Road Work Ahead Barrier", model = "prop_barrier_work04a", isFrozen = true, }, + { item = "roadclosedbarrier", label = "Road Closed Barrier", model = "xm3_prop_xm3_road_barrier_01a", isFrozen = true, }, + { item = "constructionbarrier", label = "Fold-out Barrier", model = "prop_barrier_work01a", isFrozen = false, }, + { item = "constructionbarrier2", label = "Construction Barrier", model = "prop_barrier_work06a", isFrozen = true, }, + { item = "constructionbarrier3", label = "Construction Barrier", model = "prop_mp_barrier_02b", isFrozen = true, }, + { item = "roadconebig", label = "Big Road Cone", model = "prop_barrier_wat_03a", isFrozen = false, }, + { item = "roadcone", label = "Road Cone", model = "prop_roadcone01a", isFrozen = false, }, + { item = "roadpole", label = "Road Pole", model = "prop_roadpole_01a", isFrozen = false, }, + { item = "worklight", label = "Work Light", model = "prop_worklight_01a", isFrozen = false, }, + { item = "worklight2", label = "Work Light", model = "prop_worklight_04b", isFrozen = false, }, + { item = "worklight3", label = "Work Light", model = "prop_worklight_02a", isFrozen = false, }, + { item = "constructiongenerator", label = "Construction Generator", model = "prop_generator_03b", isFrozen = true, }, + { item = "trafficdevice", label = "Traffic Device (Left)", model = "prop_trafficdiv_01", isFrozen = true, }, + { item = "trafficdevice2", label = "Traffic Device (Right)", model = "prop_trafficdiv_02", isFrozen = true, }, + { item = "meshfence1", label = "Mesh Fence (Small)", model = "prop_fnc_omesh_01a", isFrozen = true, }, + { item = "meshfence2", label = "Mesh Fence (Medium)", model = "prop_fnc_omesh_02a", isFrozen = true, }, + { item = "meshfence3", label = "Mesh Fence (Large)", model = "prop_fnc_omesh_03a", isFrozen = true, }, + { item = "waterbarrel", label = "Water Barrel", model = "prop_barrier_wat_04a", isFrozen = false, }, + + -- Camping + Hobo props + { item = "tent", label = "Old Tent", model = "prop_skid_tent_03", isFrozen = true, }, + { item = "tent2", label = "Tent", model = "prop_skid_tent_01", isFrozen = true, }, + { item = "tent3", label = "Large Tent", model = "ba_prop_battle_tent_02", isFrozen = true, }, + { item = "hobostove", label = "Hobo Stove", model = "prop_hobo_stove_01", isFrozen = true, }, + { item = "campfire", label = "Campfire", model = "prop_beach_fire", isFrozen = true, }, + { item = "hobomattress", label = "Hobo Mattress", model = "prop_rub_matress_01", isFrozen = true, }, + { item = "hoboshelter", label = "Hobo Shelter", model = "prop_homeles_shelter_01", isFrozen = true, }, + { item = "sleepingbag", label = "Sleeping Bag", model = "prop_skid_sleepbag_1", isFrozen = true, }, + { item = "canopy1", label = "Canopy (Green)", model = "prop_gazebo_01", isFrozen = true, }, + { item = "canopy2", label = "Canopy (Blue)", model = "prop_gazebo_02", isFrozen = true, }, + { item = "canopy3", label = "Canopy (White)", model = "prop_gazebo_03", isFrozen = true, }, + { item = "cot", label = "Cot", model = "gr_prop_gr_campbed_01", isFrozen = true, }, + + -- Triathlon props + { item = "tristarttable", label = "Triathlon Start Table", model = "prop_tri_table_01", isFrozen = true, }, + { item = "tristartbanner", label = "Triathlon Start Banner", model = "prop_tri_start_banner", isFrozen = true, }, + { item = "trifinishbanner", label = "Triathlon Finish Banner", model = "prop_tri_finish_banner", isFrozen = true, }, + + -- Table props + { item = "plastictable", label = "Plastic Table", model = "prop_ven_market_table1", isFrozen = true, }, + { item = "plastictable2", label = "Plastic Table", model = "prop_table_03", isFrozen = true, }, + { item = "woodtable", label = "Small Wood Table", model = "prop_rub_table_01", isFrozen = true, }, + { item = "woodtable2", label = "Wood Table", model = "prop_rub_table_02", isFrozen = true, }, + + -- Beach props + { item = "beachtowel", label = "Beach Towel", model = "prop_cs_beachtowel_01", isFrozen = true, }, + { item = "beachumbrella", label = "Beach Umbrella", model = "prop_parasol_04b", isFrozen = true, }, + { item = "beachumbrella2", label = "Beach Umbrella", model = "prop_beach_parasol_02", isFrozen = true, }, + { item = "beachumbrella3", label = "Beach Umbrella", model = "prop_beach_parasol_06", isFrozen = true, }, + { item = "beachumbrella4", label = "Beach Umbrella", model = "prop_beach_parasol_10", isFrozen = true, }, + { item = "beachball", label = "Beach Ball", model = "prop_beachball_02", isFrozen = false, }, + + -- Ramp props + { item = "ramp1", label = "Wood Ramp (Gradual)", model = "prop_mp_ramp_01", isFrozen = true, }, + { item = "ramp2", label = "Wood Ramp (Moderate)", model = "prop_mp_ramp_02", isFrozen = true, }, + { item = "ramp3", label = "Wood Ramp (Steep)", model = "prop_mp_ramp_03", isFrozen = true, }, + { item = "ramp4", label = "Metal Ramp (Large)", model = "xs_prop_arena_pipe_ramp_01a", isFrozen = true, }, + { item = "ramp5", label = "Metal Trailer Ramp", model = "xs_prop_x18_flatbed_ramp", isFrozen = true, }, + { item = "skateramp", label = "Skate Ramp", model = "prop_skate_flatramp", isFrozen = true, }, + { item = "stuntramp1", label = "Stunt Ramp S", model = "stt_prop_ramp_adj_flip_s", isFrozen = true, }, + { item = "stuntramp2", label = "Stunt Ramp M", model = "stt_prop_ramp_adj_flip_m", isFrozen = true, }, + { item = "stuntramp3", label = "Stunt Ramp L", model = "stt_prop_ramp_jump_l", isFrozen = true, }, + { item = "stuntramp4", label = "Stunt Ramp XL", model = "stt_prop_ramp_jump_xl", isFrozen = true, }, + { item = "stuntramp5", label = "Stunt Ramp XXL", model = "stt_prop_ramp_jump_xxl", isFrozen = true, }, + { item = "stuntloop1", label = "Stunt Half Loop", model = "stt_prop_ramp_adj_hloop", isFrozen = true, }, + { item = "stuntloop2", label = "Stunt Loop", model = "stt_prop_ramp_adj_loop", isFrozen = true, }, + { item = "stuntloop3", label = "Stunt Spiral", model = "stt_prop_ramp_spiral_s", isFrozen = true, }, + + -- EMS/Hospital props + { item = "medbag", label = "Medical Bag", model = "xm_prop_x17_bag_med_01a", isFrozen = true, }, + { item = "examlight", label = "Exam Light", model = "v_med_examlight", isFrozen = true, }, + { item = "hazardbin", label = "Hazard Bin", model = "v_med_medwastebin", isFrozen = true, }, + { item = "microscope", label = "Microscope", model = "v_med_microscope", isFrozen = true, }, + { item = "oscillator", label = "Oscillator", model = "v_med_oscillator3", isFrozen = true, }, + { item = "medmachine", label = "Medical Machine", model = "v_med_oscillator4", isFrozen = true, }, + { item = "bodybag", label = "Body Bag", model = "xm_prop_body_bag", isFrozen = true, }, + + -- Chairs + { item = "camp_chair_green", label = "Camp Chair (Green)", model = "prop_skid_chair_01", isFrozen = true, customTargetOptions = chairCustomTargetOptions, }, + { item = "camp_chair_blue", label = "Camp Chair (Blue)", model = "prop_skid_chair_02", isFrozen = true, customTargetOptions = chairCustomTargetOptions, }, + { item = "camp_chair_plaid", label = "Camp Chair (Plaid)", model = "prop_skid_chair_03", isFrozen = true, customTargetOptions = chairCustomTargetOptions, }, + { item = "plastic_chair", label = "Plastic Chair", model = "prop_chair_08", isFrozen = true, customTargetOptions = chairCustomTargetOptions, }, + { item = "folding_chair", label = "Folding Chair", model = "xm3_prop_xm3_folding_chair_01a", isFrozen = true, customTargetOptions = chairCustomTargetOptions, }, + + -- Cargo props + { item = "cargobox1", label = "Large cardboardbox pallet", model = "prop_mb_cargo_03a", isFrozen = false, }, + { item = "cargobox2", label = "Large mixed pallet", model = "prop_mb_cargo_02a", isFrozen = false, }, + { item = "cargobox3", label = "Tall wrapped pallet", model = "hei_prop_carrier_cargo_04b", isFrozen = false, }, + { item = "cargobox4", label = "Cardboardboxes pallet", model = "prop_boxpile_02c", isFrozen = false, }, + { item = "cargobox5", label = "Sprunk boxes pallet", model = "prop_boxpile_03a", isFrozen = false, }, + { item = "cargobox6", label = "Cardboardboxes wrapped", model = "prop_boxpile_04a", isFrozen = false, }, + { item = "cargobox7", label = "Cardboardboxes fragile", model = "prop_boxpile_06a", isFrozen = false, }, + { item = "cargobox8", label = "Cardboardboxes + keg", model = "prop_boxpile_09a", isFrozen = false, }, + { item = "pallet1", label = "Empty pallet", model = "prop_pallet_01a", isFrozen = false, }, + { item = "pallet2", label = "Fertilizer pallet", model = "bkr_prop_fertiliser_pallet_01a", isFrozen = false, }, + { item = "pallet3", label = "Weed bricks pallet", model = "hei_prop_heist_weed_pallet", isFrozen = false, }, + { item = "pallet4", label = "Barrell pallet", model = "xm3_prop_xm3_pallet_ch_01a", isFrozen = false, }, + { item = "pallet5", label = "Slotmachine pallet", model = "sf_prop_sf_slot_pallet_01a", isFrozen = false, }, + { item = "crate1", label = "Gopostal crate", model = "prop_box_wood03a", isFrozen = false, }, + { item = "crate2", label = "Wood crate", model = "prop_box_wood04a", isFrozen = false, }, + { item = "crate3", label = "Cluckinbell crate", model = "vw_prop_vw_boxwood_01a", isFrozen = false, }, + { item = "crate4", label = "Water crate", model = "prop_watercrate_01", isFrozen = false, }, + { item = "crate5", label = "Animal cage", model = "v_med_apecrate", isFrozen = false, }, + + -- Xmas props + { item = "snowman1", label = "Snowman (Red)", model = "xm3_prop_xm3_snowman_01a", isFrozen = true, }, + { item = "snowman2", label = "Snowman (Blue)", model = "xm3_prop_xm3_snowman_01b", isFrozen = true, }, + { item = "snowman3", label = "Snowman (Green)", model = "xm3_prop_xm3_snowman_01c", isFrozen = true, }, + { item = "snowman4", label = "Snowman", model = "prop_prlg_snowpile", isFrozen = true, }, + { item = "xmastree1", label = "Giant Xmas Tree", model = "prop_xmas_ext", isFrozen = true, }, + { item = "xmastree2", label = "Xmas Tree", model = "prop_xmas_tree_int", isFrozen = true, }, + { item = "candycane", label = "Candy Cane", model = "w_me_candy_xm3", isFrozen = true, }, + { item = "xmaspresent", label = "Xmas Present", model = "xm3_prop_xm3_present_01a", isFrozen = true, }, + + -- Misc props + { item = "greenscreen", label = "Green Screen", model = "prop_ld_greenscreen_01", isFrozen = true, }, + { item = "ropebarrier", label = "Rope Barrier", model = "vw_prop_vw_barrier_rope_01a", isFrozen = false, }, + { item = "largesoccerball", label = "Large Soccer Ball", model = "stt_prop_stunt_soccer_ball", isFrozen = false, }, + { item = "soccerball", label = "Soccer Ball", model = "p_ld_soc_ball_01", isFrozen = false, }, + { item = "stepladder", label = "Step Ladder", model = "v_med_cor_stepladder", isFrozen = true, }, + { item = "sexdoll", label = "Sex Doll", model = "prop_defilied_ragdoll_01", isFrozen = true, }, + + -- Pushable items + { item = "shoppingcart1", label = "Shopping Cart (Empty)", model = "prop_rub_trolley01a", isFrozen = false, customTargetOptions = pushAndSitTargetOptions, }, + { item = "shoppingcart2", label = "Shopping Cart (Full)", model = "prop_skid_trolley_2", isFrozen = false, customTargetOptions = pushTargetOptions, }, + { item = "shoppingcart3", label = "Shopping Cart (Empty)", model = "prop_rub_trolley02a", isFrozen = false, customTargetOptions = pushAndSitTargetOptions, }, + { item = "shoppingcart4", label = "Shopping Cart (Full)", model = "prop_skid_trolley_1", isFrozen = false, customTargetOptions = pushTargetOptions, }, + { + item = "wheelbarrow", + label = "Wheelbarrow", + model = "prop_wheelbarrow01a", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushAndSitTargetOptions, { + offset = { x = -0.4, y = -1.8, z = -0.6, }, + rotation = { x = 0.0, y = 20.0, z = 90.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + }, { + offset = { x = -0.25, y = 0.0, z = 1.4, }, + rotation = { x = 13.0, y = 0.0, z = 255.0, }, + animationDict = "anim@amb@business@bgen@bgen_no_work@", + animationName = "sit_phone_phoneputdown_idle_nowork", + } + ), + }, + { + item = "warehousetrolly1", + label = "Warehouse Trolly (Empty)", + model = "hei_prop_hei_warehousetrolly_02", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushAndSitTargetOptions, { + offset = { x = -0.4, y = -1.5, z = -0.9, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + }, { + offset = { x = -0.15, y = 0.15, z = 1.25, }, + rotation = { x = 0.0, y = 10.0, z = 175.0, }, + animationDict = "anim@amb@business@bgen@bgen_no_work@", + animationName = "sit_phone_phoneputdown_idle_nowork", + } + ), + }, + { + item = "warehousetrolly2", + label = "Warehouse Trolly (Full)", + model = "prop_flattruck_01d", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.5, z = -0.9, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "roomtrolly", + label = "Room Trolly", + model = "ch_prop_ch_room_trolly_01a", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.75, z = -0.8, }, + rotation = { x = 0.0, y = 0.0, z = 90.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "janitorcart1", + label = "Janitor Cart", + model = "prop_cleaning_trolly", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.3, y = -1.6, z = -0.9, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "janitorcart2", + label = "Janitor Cart", + model = "ch_prop_ch_trolly_01a", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.3, y = -1.75, z = -0.3, }, + rotation = { x = 0.0, y = 0.0, z = 270.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "mopbucket", + label = "Mop Bucket", + model = "prop_tool_mopbucket", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.3, y = -1.9, z = -0.8, }, + rotation = { x = 0.0, y = 0.0, z = 270.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "metalcart", + label = "Metal Cart", + model = "prop_gold_trolly", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.75, z = -0.35, }, + rotation = { x = 0.0, y = 0.0, z = 270.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "teacart", + label = "Tea Cart", + model = "prop_tea_trolly", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.75, z = -0.4, }, + rotation = { x = 0.0, y = 0.0, z = 90.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "drinkcart", + label = "Drink Cart", + model = "h4_int_04_drink_cart", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.75, z = -0.4, }, + rotation = { x = 0.0, y = 0.0, z = 90.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "handtruck1", + label = "Hand Truck", + model = "prop_sacktruck_02a", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.4, z = -0.8, }, + rotation = { x = -35.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "handtruck2", + label = "Hand Truck (Boxes)", + model = "prop_sacktruck_02b", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.4, y = -1.4, z = -0.75, }, + rotation = { x = -35.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "trashbin", + label = "Trash Bin", + model = "prop_cs_bin_01_skinned", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushAndSitTargetOptions, { + offset = { x = -0.4, y = -1.62, z = -0.8, }, + rotation = { x = -15.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + }, { + offset = { x = 0.02, y = 0.15, z = 1.25, }, + rotation = { x = 0.0, y = 0.0, z = 175.0, }, + animationDict = "anim@model_kylie_insta", + animationName = "kylie_insta_clip", + } + ), + }, + { + item = "lawnmower", + label = "Lawn Mower", + model = "prop_lawnmower_01", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.43, y = -1.6, z = -0.83, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "toolchest", + label = "Tool Chest", + model = "prop_toolchest_03", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.35, y = -1.95, z = -0.83, }, + rotation = { x = 0.0, y = 0.0, z = 90.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "carjack", + label = "Car Jack", + model = "prop_carjack", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.35, y = -1.75, z = -0.83, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "hospitalbedtable", + label = "Hospital Bedside Table", + model = "v_med_bedtable", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.35, y = -1.7, z = -0.35, }, + rotation = { x = 0.0, y = 0.0, z = 180.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + { + item = "medtable", + label = "Medical Table", + model = "v_med_trolley2", + isFrozen = false, + customTargetOptions = setCustomTargetOptions( + pushTargetOptions, { + offset = { x = -0.35, y = -1.75, z = -0.83, }, + rotation = { x = 0.0, y = 0.0, z = 90.0, }, + animationDict = "missfinale_c2ig_11", + animationName = "pushcar_offcliff_f", + } + ), + }, + + -- ADDON ITEMS + + -- Yogamats + -- Uncomment this line if you are using wp-yogamats + -- {item = "yogamat_blue", label = "Yoga mat (Blue)", model = "prop_yoga_mat_01", isFrozen = true, customTargetOptions = yogaCustomTargetOptions}, + -- {item = "yogamat_black", label = "Yoga mat (Black)", model = "prop_yoga_mat_02", isFrozen = true, customTargetOptions = yogaCustomTargetOptions}, + -- {item = "yogamat_red", label = "Yoga mat (Red)", model = "prop_yoga_mat_03", isFrozen = true, customTargetOptions = yogaCustomTargetOptions}, + + -- Printers + -- Uncomment this line if you are using wp-printer + -- {item = "printer", label = "Printer", model = "prop_printer_01", isFrozen = true, customTargetOptions = printerCustomTargetOptions}, + -- {item = "printer2", label = "Printer", model = "prop_printer_02", isFrozen = true, customTargetOptions = printerCustomTargetOptions}, + -- {item = "printer3", label = "Printer", model = "v_res_printer", isFrozen = true, customTargetOptions = printerCustomTargetOptions}, + -- {item = "printer4", label = "Printer", model = "v_ret_gc_print", isFrozen = true, customTargetOptions = printerCustomTargetOptions}, + -- {item = "photocopier", label = "Photocopier", model = "v_med_cor_photocopy", isFrozen = true, customTargetOptions = printerCustomTargetOptions}, + + -- Fireworks + -- Uncomment this line if you are using wp-fireworks + -- {item = "finalefirework1", label = "Finale Firework (White)", model = "bzzz_prop_fireworks_a", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "finalefirework2", label = "Finale Firework (Colored)", model = "bzzz_prop_fireworks_a", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "finalefirework3", label = "Finale Firework (USA)", model = "bzzz_prop_fireworks_a", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "fountainfirework1", label = "Fountain Firework (White)", model = "ind_prop_firework_03", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "fountainfirework2", label = "Fountain Firework (Colored)", model = "ind_prop_firework_03", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "fountainfirework3", label = "Fountain Firework (USA)", model = "ind_prop_firework_03", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "missilefirework1", label = "Missile Firework (White)", model = "ind_prop_firework_04", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "missilefirework2", label = "Missile Firework (Colored)", model = "ind_prop_firework_04", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "missilefirework3", label = "Missile Firework (USA)", model = "ind_prop_firework_04", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + -- {item = "strobefirework", label = "Strobe Firework", model = "bzzz_prop_fireworks_b", isFrozen = true, customTargetOptions = fireworkCustomTargetOptions}, + + -- Traffic lights + -- Uncomment this line if you are using wp-trafficlights + -- {item = "trafficlight", label= "Traffic light", model = "prop_traffic_03a", isFrozen = true, customTargetOptions = trafficLightCustomTargetOptions, customPickupEvent = trafficLightCustomPickupEvent}, + + -- ADD YOUR CUSTOM PROPS HERE +} diff --git a/resources/wp-placeables/shared/framework.lua b/resources/wp-placeables/shared/framework.lua new file mode 100644 index 000000000..be9d2ecca --- /dev/null +++ b/resources/wp-placeables/shared/framework.lua @@ -0,0 +1,247 @@ +-- IsDuplicityVersion - is used to determine if the function is called by the server or the client (true == from server) + +--------------------- SHARED FUNCTIONS --------------------- +local Core = nil +--- @return table Core The core object of the framework +function GetCoreObject() + if not Core then + if Config.Framework == "esx" then + Core = exports["es_extended"]:getSharedObject() + elseif Config.Framework == "qb" or Config.Framework == "qbx" then + Core = exports["qb-core"]:GetCoreObject() + end + end + return Core +end + +Core = Config.Framework ~= "none" and GetCoreObject() or nil + +--- @param text string The text to show in the notification +--- @param notificationType string The type of notification to show ex: 'success', 'error', 'info' +--- @param src - number|nil The source of the player - only required when called from server side +function Notify(text, notificationType, src) + if IsDuplicityVersion() then + if Config.Notify == "esx" then + TriggerClientEvent("esx:showNotification", src, text) + elseif Config.Notify == "qb" then + TriggerClientEvent("QBCore:Notify", src, text, notificationType) + elseif Config.Notify == "ox" then + TriggerClientEvent("ox_lib:notify", src, { + description = text, + type = notificationType, + }) + end + else + if Config.Notify == "esx" then + Core.ShowNotification(text) + elseif Config.Notify == "qb" then + Core.Functions.Notify(text, notificationType) + elseif Config.Notify == "ox" then + lib.notify({ + description = text, + type = notificationType, + }) + end + end +end + +--- @param source number|nil The source of the player +--- @return table PlayerData The player data of the player +function GetPlayerData(source) + local Core = GetCoreObject() + if IsDuplicityVersion() then + if Config.Framework == "esx" then + -- TODO: does esx not use citizenId? need to find what it uses + return Core.GetPlayerFromId(source) + elseif Config.Framework == "qb" then + return Core.Functions.GetPlayer(source).PlayerData + elseif Config.Framework == "qbx" then + return exports.qbx_core:GetPlayer(source).PlayerData + end + else + if Config.Framework == "esx" then + return Core.GetPlayerData() + elseif Config.Framework == "qb" then + return Core.Functions.GetPlayerData() + elseif Config.Framework == "qbx" then + return exports.qbx_core:GetPlayerData() + end + end +end + +--------------------- CLIENT FUNCTIONS --------------------- + +-- Triggers a progressbar on the client +-- This uses the same method signature as QBCore Progressbar +--- @param name string The name of the progressbar +--- @param label string The label to show on the progressbar +--- @param duration number The duration of the progressbar +--- @param useWhileDead boolean Whether or not the progressbar should be used while dead +--- @param canCancel boolean Whether or not the progressbar can be cancelled +--- @param disableControls table Contains the controls to disable while the progressbar is active (disableMovement, disableCarMovement, disableMouse, disableCombat) +--- @param animation table Contains the animation to play while the progressbar is active (animDict, anim, flags) +--- @param prop table Contains the prop to show while the progressbar is active (model, bone, coords, rotation) +--- @param propTwo table Contains the prop to show while the progressbar is active (model, bone, coords, rotation) +--- @param onFinish function The callback function to call when the progressbar finishes +--- @param onCancel function The callback function to call when the progressbar is cancelled +function Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel) + if IsDuplicityVersion() then return end + if Config.ProgessBar == "none" then + onFinish() + elseif Config.ProgessBar == "qb" then + return Core.Functions.Progressbar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel) + elseif Config.ProgessBar == "ox" then + local props = {} + if prop then + props[1] = { + model = prop.model, + bone = prop.bone, + coords = prop.coords, + rotation = prop.rotation, + } + end + if propTwo then + props[2] = { + model = propTwo.model, + bone = propTwo.bone, + coords = propTwo.coords, + rotation = propTwo.rotation, + } + end + + if lib.progressBar({ + name = name, + label = label, + duration = duration, + useWhileDead = useWhileDead, + canCancel = canCancel, + disable = { + move = disableControls.disableMovement, + car = disableControls.disableCarMovement, + mouse = disableControls.disableMouse, + combat = disableControls.disableCombat, + }, + anim = { + dict = animation.animDict, + clip = animation.anim, + flag = animation.flags, + }, + prop = props, + }) then + onFinish() + else + onCancel() + end + else + warn("Invalid Config.ProgessBar: <" .. tostring(Config.ProgessBar) .. ">. Update Progressbar in framework.lua.") + end +end + +-- Takes a prop model and the targetOptions and adds it to the target script so that this prop model is targetable +--- @param model string The name of the prop model to target +--- @param targetOptions table The options to pass to the target script +--- ex: targetOptions = { distance = num, options: { offset = { x = 0.0, y = 0.0, z = 0.0 }, rotation = { x = 0.0, y = 0.0, z = 0.0 } , animationDict = "", animationName = "" } } +function AddTargetModel(modelName, targetOptions) + if IsDuplicityVersion() then return end + if Config.Target == "qb" then + exports["qb-target"]:AddTargetModel(modelName, targetOptions) + elseif Config.Target == "ox" then + -- ox target expects each option to have a distance on it, + -- Append the distance value to each option + for _, option in pairs(targetOptions.options) do + option.distance = targetOptions.distance + end + exports.ox_target:addModel(modelName, targetOptions.options) + else + warn("Invalid Config.Target: <" .. tostring(Config.Target) .. ">. Update AddTargetModel in framework.lua.") + end +end + +-- Creates a log entry when an item is placed or picked up +--- @param itemName string The name of the item that was placed or picked up +--- @param isItemPlaced boolean True if the item was placed, false if the item was picked up +function CreateLog(itemName, isItemPlaced) + if IsDuplicityVersion() or Config.Log == "none" then return end + + local playerId = PlayerId() + local playerName = GetPlayerName(playerId) + local PlayerData = GetPlayerData() + local color = isItemPlaced and "red" or "green" + local action = isItemPlaced and "Placed" or "Picked up" + local logMessage = "**" .. playerName .. "** (" .. PlayerData.charinfo.firstname .. " " .. PlayerData.charinfo.lastname .. ") | CitizenId: " .. PlayerData.citizenid .. "\n Item Name: " .. itemName + + if Config.Log == "none" then + return + elseif Config.Log == "qb" then + -- Be sure to add the 'itemplacement' entry to the qb-log config + TriggerServerEvent("qb-log:server:CreateLog", "itemplacement", "Item " .. action .. " By:", color, logMessage) + else + warn("Invalid Config.Log: <" .. tostring(Config.Log) .. ">. Update CreateLog in framework.lua.") + end +end + +--------------------- SERVER FUNCTIONS --------------------- + +-- Registers a useable item +--- @param itemName string The name of the item to register +--- @param callbackFn function The function to call when the item is used +function CreateUseableItem(itemName, callbackFn) + if not IsDuplicityVersion() then return end + if Config.Framework == "esx" then + -- ESX returns the itemName as the second parameter, itemdata as the third parameter when calling the callback function + -- We are interested in the itemData for our callback + local function ESXCallback(source, itemName, itemData) + callbackFn(source, itemData) + end + + return Core.RegisterUsableItem(itemName, ESXCallback) + elseif Config.Framework == "qb" then + return Core.Functions.CreateUseableItem(itemName, callbackFn) + elseif Config.Framework == "qbx" then + return exports.qbx_core:CreateUseableItem(itemName, callbackFn) + else + warn("Invalid Config.Framework: <" .. tostring(Config.Framework) .. ">. Update CreateUseableItem in framework.lua.") + end +end + +-- Adds item to the players inventory +--- @param source number The source of the player +--- @param itemName string The name of the item to add +--- @param amount number The amount of the item to add +--- @param info table Metadata to add to the item +function AddItem(source, itemName, amount, info) + if not IsDuplicityVersion() then return end + if Config.Inventory == "esx" then + local xPlayer = Core.GetPlayerFromId(source) + return xPlayer.addInventoryItem(itemName, amount) + elseif Config.Inventory == "qb" then + local Player = Core.Functions.GetPlayer(source) + TriggerClientEvent("inventory:client:ItemBox", source, Core.Shared.Items[itemName], "add") + return Player.Functions.AddItem(itemName, amount, nil, info) + elseif Config.Inventory == "ox" then + exports.ox_inventory:AddItem(source, itemName, amount, info) + else + warn("Invalid Config.Inventory: <" .. tostring(Config.Inventory) .. ">. Update AddItem in framework.lua.") + end +end + +-- Removes item from the players inventory +--- @param source number The source of the player +--- @param itemName string The name of the item to remove +--- @param amount number The number of items to remove +--- @param slot number The slot of the item to remove from +function RemoveItem(source, itemName, amount, slot) + if not IsDuplicityVersion() then return end + if Config.Inventory == "esx" then + local xPlayer = Core.GetPlayerFromId(source) + return xPlayer.removeInventoryItem(itemName, amount) + elseif Config.Inventory == "qb" then + local Player = Core.Functions.GetPlayer(source) + TriggerClientEvent("inventory:client:ItemBox", source, Core.Shared.Items[itemName], "remove") + return Player.Functions.RemoveItem(itemName, amount, slot) + elseif Config.Inventory == "ox" then + exports.ox_inventory:RemoveItem(source, itemName, amount, nil, slot) + else + warn("Invalid Config.Inventory: <" .. tostring(Config.Inventory) .. ">. Update RemoveItem in framework.lua.") + end +end diff --git a/resources/wp-tow-hauling/LICENSE b/resources/wp-tow-hauling/LICENSE new file mode 100644 index 000000000..e72bfddab --- /dev/null +++ b/resources/wp-tow-hauling/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/resources/wp-tow-hauling/README.md b/resources/wp-tow-hauling/README.md new file mode 100644 index 000000000..742532cdc --- /dev/null +++ b/resources/wp-tow-hauling/README.md @@ -0,0 +1,92 @@ +# Waypoint Tow / Hauling + +![wp-tow-hauling](https://github.com/WaypointRP/wp-tow-hauling/assets/18689469/b4babe29-9ebb-4923-ada5-38e7a054fcdb) + +This script provides an intuitive and user-friendly solution for towing and hauling vehicles and props. Unlike other scripts, it attaches vehicles and objects at their exact positions rather than teleporting it to a hardcoded spot. You can attach any number of vehicles/objects, the only limit is the physical space on your tow vehicle. Players can configure their towing/hauling load however they see fit and let their imagination run wild. By default, there is no limit to what vehicles or objects can be towed, allowing for maximum creativity and roleplay immersion. However, you can configure the script to limit the vehicles that can be used to tow if you wish. + + +Preview: https://youtu.be/oTn4ASd33R8 + +## Overview + +Some examples of what you can do with this script: +- haul multiple offroad / non street legal vehicles to your destination + - haul motorcycle(s) on the back of a pickup truck +- haul boats on a trailer +- haul multiple vehicles using the car carrier trailer (tr2) +- haul cargo on a trailer (crates, pallets, etc) +- create a mobile farmers market on the back of a pickup truck +- create a mobile firework show on a party bus (with [wp-fireworks](https://backsh00ter.tebex.io/package/5753511)) +- create immersive jobs where players can haul vehicles or props to a destination + +The scenarios that can be created with this script are limited only by your imagination. + +Best paired with a script that can be used for placing props in the world such as [Waypoint Placeables](https://github.com/WaypointRP/wp-placeables). + + +## Usage + +**Towing** +1. Enter tow selection mode by using the command `/tow` or by using the event `wp-hauling:client:startTowSelection` +2. Look at and select the vehicle you will be towing to +3. Look at and select the vehicle/object you want to tow/haul +4. Confirm or cancel the selection +5. If confirmed, the vehicle/object will be attached to the tow vehicle at its exact position + +Repeat steps 1-5 as many times as you like to attach more vehicles/objects. + +**Untowing** +1. Enter untow selection mode by using the command `/untow` or by using the event `wp-hauling:client:startUntowSelection` +2. Look at and select the vehicle/object you want to untow +3. Vehicle/object will be unattached and remain in the same position + +## Setup + +1. Enable the script in your server.cfg +2. Configure the script in the config.lua + - Choose the notification framework you are using with `Config.Notify`. + - Choose the keybinds you want to use for selecting and canceling select mode: `Config.ConfirmVehicleSelectionKey` / `Config.ExitVehicleSelectionKey` + - Decide whether you want to limit the vehicles that can be used to tow with `Config.AllowAllVehiclesToTow` and `Config.AllowedTowVehicles`. + - _Recommendation: For the best experience and enabling fullest potential of creativity, I do NOT recommend limiting the allowed vehicles._ + - Decide whether you want to allow attaching props with `Config.AllowHaulingProps`. +3. By default, the commands `/tow` and `/untow` are used to start the actions. You can use the provided events to hook these up in your own way (ex: Radial menu). + `wp-hauling:client:startTowSelection` and `wp-hauling:client:startUntowSelection` + +> Note: If you are using `ox` for any of the Framework options you need to uncomment `@ox_lib/init.lua` in the fxmanifest.lua. + +## Additional Notes + +For the best experience, it is recommended to have a script for placing/carrying/moving props in the world. +[Waypoint Placeables](https://github.com/WaypointRP/wp-placeables) is a great option for this and also provides ramp items that can be used to easily load vehicles onto trailers. + +This script is designed to be immersive and attach vehicles in place. As such it does not teleport vehicles onto your tow vehicle. To be able to tow broken down cars, it is recommended to have a script for pushing broken down cars. You can then place a ramp, and push the vehicle up the ramp onto your tow trailer. + + +## Performance + +This script was written with performance in mind. The only time the resource will run higher than 0.00ms is while in tow/untow select mode when we are running the raycast thread. Otherwise there are no other threads or loops running. + +Idle: 0.00ms +With vehicles attached: 0.00ms +Attachment mode active: 0.02ms - 0.08ms (drawing markers + using raycast to detect selection) + - After selection is confirmed resource returns to 0.00ms + + +## Dependencies + +This resource was designed to be **standalone** and does not require any other resources to function. + +If you want to use notifications, there is a built in framework wrapper around the `Notify()` function to hook into the notifications framework of your choice. + +## Gallery + +![image](https://github.com/WaypointRP/wp-tow-hauling/assets/18689469/05b46c96-651a-4c87-9f1e-0cafffd9b9c9) + +![image](https://github.com/WaypointRP/wp-tow-hauling/assets/18689469/deadcb9b-d983-41a2-a7e5-3dbb6245b56b) + +![image](https://github.com/WaypointRP/wp-tow-hauling/assets/18689469/62d2b874-ba74-4753-bbc4-caea9884806f) + +![image](https://github.com/WaypointRP/wp-tow-hauling/assets/18689469/4a00075f-19fa-4a54-9f71-90d2da4c8d46) + +## Credit +@DonHulieo for providing insipiration and examples for structuring the framework.lua file. diff --git a/resources/wp-tow-hauling/client.lua b/resources/wp-tow-hauling/client.lua new file mode 100644 index 000000000..5ffd3d6f6 --- /dev/null +++ b/resources/wp-tow-hauling/client.lua @@ -0,0 +1,301 @@ +if Config.EnableTowCommands then + CreateThread(function() + TriggerEvent("chat:addSuggestion", "/tow", "Start the process to tow/attach a vehicle.") + TriggerEvent("chat:addSuggestion", "/untow", "Start the process to untow a specific attached vehicle.") + end) +end + +-- Requests network control of an entity +local function RequestNetworkControlOfObject(netId, itemEntity) + if NetworkDoesNetworkIdExist(netId) then + NetworkRequestControlOfNetworkId(netId) + while not NetworkHasControlOfNetworkId(netId) do + Wait(100) + NetworkRequestControlOfNetworkId(netId) + end + end + + if DoesEntityExist(itemEntity) then + NetworkRequestControlOfEntity(itemEntity) + while not NetworkHasControlOfEntity(itemEntity) do + Wait(100) + NetworkRequestControlOfEntity(itemEntity) + end + end +end + +-- Checks if the vehicle is allowed to be used to tow +--- @param vehicle - The vehicle entity to check +--- @return boolean - True/false if the vehicle is allowed to be used to tow +local function isAllowedTowVehicle(vehicle) + if Config.AllowAllVehiclesToTow then return true end + + local isAllowed = false + for _, veh in pairs(Config.AllowedTowVehicles) do + if GetEntityModel(vehicle) == GetHashKey(veh) then + isAllowed = true + break + end + end + + return isAllowed +end + +-- Draws a marker above the target object that the player is looking at +-- If the object is hovered, it will draw a yellow marker, once selected it will draw a red marker +-- This needs to be called every frame to render correctly +--- @param targetVehicle - The vehicle entity to draw the marker on +--- @param isSelected boolean - Whether the vehicle had already been selected or is just hovered over +--- @param markerType number - The type of marker to draw +local function DrawMarkerOnTarget(targetVehicle, isSelected, markerType) + -- local markerType = 0 + local scale = 0.3 + local alpha = 255 + local bounce = true + local faceCam = false + local iUnk = 0 + local rotate = false + local textureDict = nil + local textureName = nil + local drawOnEnts = false + local pos = GetEntityCoords(targetVehicle, true) + local colorYellow = { red = 255, green = 255, blue = 0, } + local colorRed = { red = 255, green = 50, blue = 0, } + local color = colorYellow + -- If isSelected then use color red, else use color yellow + if isSelected then color = colorRed end + + DrawMarker(markerType, pos.x, pos.y, pos.z + 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, scale, scale, scale - 0.1, color.red, color.green, color.blue, alpha, bounce, faceCam, iUnk, rotate, textureDict, textureName, drawOnEnts) +end + +-- Used by the raycast functions to get the direction the camera is looking +local function RotationToDirection(rotation) + local adjustedRotation = { + x = (math.pi / 180) * rotation.x, + y = (math.pi / 180) * rotation.y, + z = (math.pi / 180) * rotation.z, + } + + local direction = { + x = -math.sin(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), + y = math.cos(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), + z = math.sin(adjustedRotation.x), + } + + return direction +end + +-- Uses a RayCast to get the entity, coords, and whether we "hit" something with the raycast +--- @param distance - The distance to cast the ray +--- @return hit, coords, entity - Whether the raycast hit something, the coords of the hit, and the entity that was hit +local function RayCastGamePlayCamera(distance) + local cameraRotation = GetGameplayCamRot() + local cameraCoord = GetGameplayCamCoord() + local direction = RotationToDirection(cameraRotation) + local destination = { + x = cameraCoord.x + direction.x * distance, + y = cameraCoord.y + direction.y * distance, + z = cameraCoord.z + direction.z * distance, + } + + local _, hit, coords, _, entity = GetShapeTestResult(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, -1, PlayerPedId(), 0)) + return hit, coords, entity +end + +-- Draws a line and marker at the end of the raycast where the player is looking +--- @param coords - The coords to draw the line and marker at +local function DrawRayCastLine(coords) + local color = { r = 37, g = 192, b = 192, a = 200, } + local position = GetEntityCoords(PlayerPedId()) + + if coords.x ~= 0.0 and coords.y ~= 0.0 then + DrawLine(position.x, position.y, position.z, coords.x, coords.y, coords.z, color.r, color.g, color.b, color.a) + DrawMarker(28, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 180.0, 0.0, 0.05, 0.05, 0.05, color.r, color.g, color.b, color.a, false, true, 2, nil, nil, false) + end +end + +-- Activates the ray cast mode to get the target object the player is looking at +-- Listens for keypress to detect when the player has selected the target +-- Checks if the vehicle is allowed to be used to tow and that the vehicle is not the same as the already selected vehicle +--- @param shouldCheckAllowedVehicles - boolean - Whether to check if the vehicle is allowed to be used to tow +--- @param otherSelectedVehicle - The vehicle entity that has already been selected +--- @param shouldDrawOutline - boolean - Whether to draw an outline on the selected vehicle/object +--- @return vehicle - The vehicle entity that the player has selected +local function rayCastGetSelectedVehicle(shouldCheckAllowedVehicles, otherSelectedVehicle, shouldDrawOutline) + local hit, coords, targetObj = RayCastGamePlayCamera(Config.TowDistance) + + -- Draw the line to the coords where the player is looking + DrawRayCastLine(coords) + + if hit and DoesEntityExist(targetObj) and targetObj ~= otherSelectedVehicle and (Config.AllowHaulingProps or IsEntityAVehicle(targetObj)) then + DrawMarkerOnTarget(targetObj, false, 0) + + -- Listen for keypress of ConfirmVehicleSelectionKey key + if (IsControlJustPressed(0, Config.ConfirmVehicleSelectionKey)) then + if not shouldCheckAllowedVehicles or isAllowedTowVehicle(targetObj) then + if shouldDrawOutline then + SetEntityDrawOutline(targetObj, true) + SetEntityDrawOutlineColor(0, 255, 255, 255) + SetEntityDrawOutlineShader(0) + end + + return targetObj + end + end + end +end + +-- Attaches the targetObject onto the towVehicle in its current position, +-- respecting both the targetObjects rotation and offset from the towVehicle +-- If the vehicle + object are not touching, it will not attach them +--- @param towVehicle - The vehicle entity that will be doing the towing +--- @param targetObject - The vehicle entity that will be towed +local function attachTargetObjectToTowVehicle(towVehicle, targetObject) + local towNetId = NetworkGetNetworkIdFromEntity(towVehicle) + local targetNetId = NetworkGetNetworkIdFromEntity(targetObject) + + -- Get control of the entities. This makes it so you dont need to sit in the vehicle first + RequestNetworkControlOfObject(targetNetId, targetObject) + RequestNetworkControlOfObject(towNetId, towVehicle) + + -- Necessary to make sure the player has control of both entities + Wait(500) + + local isTargetTouchingTowVehicle = IsEntityTouchingEntity(towVehicle, targetObject) + + if isTargetTouchingTowVehicle then + -- Calculate target object rotation relative to the tow vehicle + -- This ensures that the object maintains its current rotation when attached to the tow vehicle + local targetObjectRotation = GetEntityRotation(targetObject, 2) + local towVehicleRotation = GetEntityRotation(towVehicle, 2) + local newRotX = targetObjectRotation.x - towVehicleRotation.x + local newRotY = targetObjectRotation.y - towVehicleRotation.y + local newRotZ = targetObjectRotation.z - towVehicleRotation.z + + -- This ensures the target vehicle is attached to the tow vehicle at its current position + local offsetCoords = GetOffsetFromEntityGivenWorldCoords(towVehicle, GetEntityCoords(targetObject)) + + AttachEntityToEntity(targetObject, towVehicle, 0, offsetCoords.x, offsetCoords.y, offsetCoords.z, newRotX, newRotY, newRotZ, 0, true, true, false, 2, true) + + Notify("Object has been strapped down.", "success", 5000) + else + Notify("Target object must be touching the tow vehicle in order to be towed", "error", 7500) + end +end + +-- Run a thread to handle selecting the tow vehicle and target vehicle +local function startTowingSelectMode() + local towVehicle = nil + local targetObject = nil + + local hasNotifiedSelectTowTruck = false + local hasNotifiedSelectTarget = false + local hasNotifiedConfirm = false + + local isTowingSelectModeEnabled = true + + CreateThread(function() + local instructionalButtons = nil + + while isTowingSelectModeEnabled do + -- STEP 1: Runs a raycast to get the vehicle the player wants to tow to + if not towVehicle then + if not hasNotifiedSelectTowTruck then + hasNotifiedSelectTowTruck = true + instructionalButtons = DrawInstructionalButtons(Config.ConfirmVehicleSelectionKey, "Select tow vehicle", Config.ExitVehicleSelectionKey, "Cancel") + end + + towVehicle = rayCastGetSelectedVehicle(true, nil, true) + -- STEP 2: Runs a raycast to get the vehicle/object the player wants to be towed + elseif not targetObject then + if not hasNotifiedSelectTarget then + hasNotifiedSelectTarget = true + instructionalButtons = DrawInstructionalButtons(Config.ConfirmVehicleSelectionKey, "Select target to tow", Config.ExitVehicleSelectionKey, "Cancel") + end + + targetObject = rayCastGetSelectedVehicle(false, towVehicle, true) + -- STEP 3: Notify the player to press ConfirmVehicleSelectionKey to confirm the selections and complete the tow + else + if not hasNotifiedConfirm then + hasNotifiedConfirm = true + instructionalButtons = DrawInstructionalButtons(Config.ConfirmVehicleSelectionKey, "Confirm selection", Config.ExitVehicleSelectionKey, "Cancel") + end + + -- Listen for keypress of the selection key to attach the vehicles together + if (IsControlJustPressed(0, Config.ConfirmVehicleSelectionKey)) then + isTowingSelectModeEnabled = false + + -- Remove outlines on confirm + SetEntityDrawOutline(towVehicle, false) + SetEntityDrawOutline(targetObject, false) + + attachTargetObjectToTowVehicle(towVehicle, targetObject) + end + end + + -- Draw markers on selected tow vehicle + if towVehicle and isTowingSelectModeEnabled then + DrawMarkerOnTarget(towVehicle, true, 39) + end + + -- Listen for keypress of exit vehicle selection key to break out of the thread and cancel select mode + if (IsControlJustPressed(0, Config.ExitVehicleSelectionKey)) then + SetEntityDrawOutline(towVehicle, false) + SetEntityDrawOutline(targetObject, false) + isTowingSelectModeEnabled = false + end + + DrawScaleformMovieFullscreen(instructionalButtons, 255, 255, 255, 255, 0) + + Wait(1) + end + end) +end + +-- Run a thread to handle selecting the target vehicle that you want to untow +local function startUnTowSelectMode() + local targetObject = nil + + local isUnTowingSelectModeEnabled = true + + local instructionalButtons = DrawInstructionalButtons(Config.ConfirmVehicleSelectionKey, "Select target to untow", Config.ExitVehicleSelectionKey, "Cancel") + + CreateThread(function() + while isUnTowingSelectModeEnabled do + -- targetObject will be undefined until the player selects it from the raycast selection mode + targetObject = rayCastGetSelectedVehicle(false, nil, false) + + if targetObject and IsEntityAttachedToAnyVehicle(targetObject) then + -- Get control of the entities. This makes it so you dont need to sit in the vehicle first + local netId = NetworkGetNetworkIdFromEntity(targetObject) + RequestNetworkControlOfObject(netId, targetObject) + Wait(500) + + DetachEntity(targetObject, true, false) + isUnTowingSelectModeEnabled = false + + Notify("Vehicle detached", "success", 3000) + elseif targetObject then + Notify("Vehicle is not attached to anything", "error", 3000) + end + + -- Listen for keypress of exit vehicle selection key to exit out of the loop + if (IsControlJustPressed(0, Config.ExitVehicleSelectionKey)) then + -- Exit out of the thread and reset any variables + isUnTowingSelectModeEnabled = false + end + + DrawScaleformMovieFullscreen(instructionalButtons, 255, 255, 255, 255, 0) + + Wait(1) + end + end) +end + +RegisterNetEvent("wp-hauling:client:startTowSelection", function() + startTowingSelectMode() +end) + +RegisterNetEvent("wp-hauling:client:startUntowSelection", function() + startUnTowSelectMode() +end) diff --git a/resources/wp-tow-hauling/fxmanifest.lua b/resources/wp-tow-hauling/fxmanifest.lua new file mode 100644 index 000000000..e9bace848 --- /dev/null +++ b/resources/wp-tow-hauling/fxmanifest.lua @@ -0,0 +1,23 @@ +fx_version "cerulean" +game "gta5" + +description "Waypoint Tow / Hauling" +author "BackSH00TER - Waypoint RP" +version "1.0.1" + +shared_script { + -- '@ox_lib/init.lua', -- Uncomment this if you are planning to use any ox scripts (such as ox notify) + "shared/config.lua", + "shared/framework.lua", +} + +client_scripts { + "client.lua", + "instructional-buttons.lua", +} + +server_scripts { + "server.lua", +} + +lua54 "yes" diff --git a/resources/wp-tow-hauling/instructional-buttons.lua b/resources/wp-tow-hauling/instructional-buttons.lua new file mode 100644 index 000000000..f0a7d1963 --- /dev/null +++ b/resources/wp-tow-hauling/instructional-buttons.lua @@ -0,0 +1,52 @@ +-- Referenced from glitchdetector: https://github.com/glitchdetector/fivem-instructional-buttons + +local function ButtonMessage(text) + BeginTextCommandScaleformString("STRING") + AddTextComponentScaleform(text) + EndTextCommandScaleformString() +end + +local function Button(ControlButton) + N_0xe83a3e3557a56640(ControlButton) +end + +function DrawInstructionalButtons(primaryKey, primaryText, secondaryKey, secondaryText) + local scaleform = RequestScaleformMovie("instructional_buttons") + while not HasScaleformMovieLoaded(scaleform) do + Wait(0) + end + + -- draw it once to set up layout + DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 0, 0) + + PushScaleformMovieFunction(scaleform, "CLEAR_ALL") + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(scaleform, "SET_CLEAR_SPACE") + PushScaleformMovieFunctionParameterInt(200) + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT") + PushScaleformMovieFunctionParameterInt(0) + Button(GetControlInstructionalButton(2, secondaryKey, true)) -- The button to display + ButtonMessage(secondaryText) -- the message to display next to it + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT") + PushScaleformMovieFunctionParameterInt(1) + Button(GetControlInstructionalButton(2, primaryKey, true)) + ButtonMessage(primaryText) + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(scaleform, "DRAW_INSTRUCTIONAL_BUTTONS") + PopScaleformMovieFunctionVoid() + + PushScaleformMovieFunction(scaleform, "SET_BACKGROUND_COLOUR") + PushScaleformMovieFunctionParameterInt(0) + PushScaleformMovieFunctionParameterInt(0) + PushScaleformMovieFunctionParameterInt(0) + PushScaleformMovieFunctionParameterInt(80) + PopScaleformMovieFunctionVoid() + + return scaleform +end diff --git a/resources/wp-tow-hauling/server.lua b/resources/wp-tow-hauling/server.lua new file mode 100644 index 000000000..ebe4a084d --- /dev/null +++ b/resources/wp-tow-hauling/server.lua @@ -0,0 +1,9 @@ +if Config.EnableTowCommands then + RegisterCommand("tow", function(source, args) + TriggerClientEvent("wp-hauling:client:startTowSelection", source) + end) + + RegisterCommand("untow", function(source, args) + TriggerClientEvent("wp-hauling:client:startUntowSelection", source) + end) +end diff --git a/resources/wp-tow-hauling/shared/config.lua b/resources/wp-tow-hauling/shared/config.lua new file mode 100644 index 000000000..7d1ec2150 --- /dev/null +++ b/resources/wp-tow-hauling/shared/config.lua @@ -0,0 +1,47 @@ +Config = {} + +------------------------------------ +-- FRAMEWORK / SCRIPT CONFIGURATION +-- Adjust these settings to match the framework and scripts you are using +-- Note: If using ox for any option, enable @ox_lib/init.lua in the manifest! +------------------------------------ + +--- @type "qb" | "qbx" | "esx" +Config.Framework = "qb" + +-- The notification script you are using. +--- @type "qb" | "esx" | "ox" | "none" +Config.Notify = "qb" + +------------------------------------ +--- END FRAMEWORK / SCRIPT CONFIGURATION +------------------------------------ + +-- The key that the player needs to press to confirm the vehicle selection +-- See https://docs.fivem.net/docs/game-references/controls/#controls for a list of controls +Config.ConfirmVehicleSelectionKey = 38 -- E +Config.ExitVehicleSelectionKey = 214 -- DELETE + +-- If you wish to only allow certain vehicles to be used for towing add the vehicle name to Config.AllowedTowVehicles +-- and set Config.AllowAllVehiclesToTow to false. If you want to allow all vehicles to tow, set Config.AllowAllVehiclesToTow to true +Config.AllowAllVehiclesToTow = true +Config.AllowedTowVehicles = { + "armytrailer", + "boattrailer", + "freighttrailer", + "flatbed", + "flatbed3", + "trflat", + "tr2", + "trailerlarge", + "slamtruck", +} + +-- If true you can also tow/haul props. If false, you can only tow/haul vehicles +Config.AllowHaulingProps = true + +-- This enables the /tow and /untow commands. If you disable this, you can still use the client events to trigger tow/untow +Config.EnableTowCommands = true + +-- The distance the player must be within from the vehicle to tow it +Config.TowDistance = 15.0 diff --git a/resources/wp-tow-hauling/shared/framework.lua b/resources/wp-tow-hauling/shared/framework.lua new file mode 100644 index 000000000..2dc415d51 --- /dev/null +++ b/resources/wp-tow-hauling/shared/framework.lua @@ -0,0 +1,51 @@ +-- IsDuplicityVersion - is used to determine if the function is called by the server or the client (true == from server) + +--------------------- SHARED FUNCTIONS --------------------- +local Core = nil +--- @return table Core The core object of the framework +function GetCoreObject() + if not Core then + if Config.Framework == "esx" then + Core = exports["es_extended"]:getSharedObject() + elseif Config.Framework == "qb" or Config.Framework == "qbx" then + Core = exports["qb-core"]:GetCoreObject() + end + end + return Core +end + +Core = Config.Framework ~= "none" and GetCoreObject() or nil + +--- @param text string The text to show in the notification +--- @param notificationType string The type of notification to show ex: 'success', 'error', 'info' +--- @param src - number|nil The source of the player - only required when called from server side +function Notify(text, notificationType, src) + if IsDuplicityVersion() then + if Config.Notify == "esx" then + TriggerClientEvent("esx:showNotification", src, text) + elseif Config.Notify == "qb" then + TriggerClientEvent("QBCore:Notify", src, text, notificationType) + elseif Config.Notify == "ox" then + TriggerClientEvent("ox_lib:notify", src, { + description = text, + type = notificationType, + }) + end + else + if Config.Notify == "esx" then + Core.ShowNotification(text) + elseif Config.Notify == "qb" then + Core.Functions.Notify(text, notificationType) + elseif Config.Notify == "ox" then + lib.notify({ + description = text, + type = notificationType, + }) + end + end +end + +--------------------- CLIENT FUNCTIONS --------------------- + + +--------------------- SERVER FUNCTIONS --------------------- diff --git a/resources/xmenu/README.md b/resources/xmenu/README.md new file mode 100644 index 000000000..33a80fd67 --- /dev/null +++ b/resources/xmenu/README.md @@ -0,0 +1,3 @@ +# LICENSE + +Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. diff --git a/resources/xmenu/classes/menu.lua b/resources/xmenu/classes/menu.lua new file mode 100644 index 000000000..1c853bbb6 --- /dev/null +++ b/resources/xmenu/classes/menu.lua @@ -0,0 +1,47 @@ +xMenu = {} +xMenu.__index = xMenu + +function xMenu.New(name, color) + local newMenu = {} + setmetatable(newMenu, xMenu) + + newMenu.Name = name + newMenu.Resource = GetCurrentResourceName() + newMenu.Handle = exports["xmenu"]:AddMenu(name, newMenu.Resource) + newMenu.Color = color + + return newMenu +end + +function xMenu:IsAnyMenuOpen() + return exports["xmenu"]:IsAnyMenuOpen() +end + +function xMenu:OpenMenu() + exports["xmenu"]:OpenMenu(self.Handle, self.Color) +end + +function xMenu:CloseMenu() + exports["xmenu"]:CloseMenu() +end + +function xMenu:BindSubMenu(name) + local newHandle = exports["xmenu"]:AddSubMenu(name, self.Handle, self.Resource) + return xSubMenu.New(name, newHandle) +end + +function xMenu:BindButton(name, callback) + exports["xmenu"]:AddButton(name, self.Handle, callback, self.Resource) +end + +function xMenu:BindCheckbox(name, state, callback) + exports["xmenu"]:AddCheckbox(name, state, self.Handle, callback, self.Resource) +end + +function xMenu:BindList(name, list, callback) + exports["xmenu"]:AddList(name, self.Handle, list, callback, self.Resource) +end + +function xMenu:ClearMenu() + exports["xmenu"]:ClearMenu(self.Handle) +end \ No newline at end of file diff --git a/resources/xmenu/classes/submenu.lua b/resources/xmenu/classes/submenu.lua new file mode 100644 index 000000000..476f1a458 --- /dev/null +++ b/resources/xmenu/classes/submenu.lua @@ -0,0 +1,30 @@ +xSubMenu = {} +xSubMenu.__index = xMenu + +function xSubMenu.New(name, handle) + local newMenu = {} + setmetatable(newMenu, xMenu) + + newMenu.Name = name + newMenu.Handle = handle + newMenu.Resource = GetCurrentResourceName() + + return newMenu +end + +function xSubMenu:BindSubMenu(name) + local newHandle = exports["xmenu"]:AddSubMenu(name, self.Handle, self.Resource) + return xSubMenu.New(name, newHandle) +end + +function xMenu:BindButton(name, callback) + exports["xmenu"]:AddButton(name, self.Handle, callback, self.Resource) +end + +function xMenu:BindCheckbox(name, state, callback) + exports["xmenu"]:AddCheckbox(name, state, self.Handle, callback, self.Resource) +end + +function xMenu:BindList(name, list, callback) + exports["xmenu"]:AddList(name, self.Handle, list, callback, self.Resource) +end \ No newline at end of file diff --git a/resources/xmenu/client.lua b/resources/xmenu/client.lua new file mode 100644 index 000000000..5ee5b684b --- /dev/null +++ b/resources/xmenu/client.lua @@ -0,0 +1,347 @@ +-- All Data +local Menus = {} +local Components = {} +local Resources = {} + +-- Current Data +local OpenedMenu = nil +local HoveredIndex = 1 + +function IsResourceStarted(resource) + for _, v in pairs(Resources) do + if v == resource then + return true + end + end + return false +end + +function AddMenu(name, resource) + local index = Utils.GenerateUUID() + table.insert(Resources, resource) + + Menus[index] = { + name = name, + type = "base", + components = {}, + resource = resource + } + + return index +end + +function AddSubMenu(name, menu, resource) + local index = Utils.GenerateUUID() + + Menus[index] = { + name = name, + type = "submenu", + components = {}, + parent = menu, + resource = resource + } + + table.insert(Menus[menu].components, { + index = index, + name = name, + parent = menu, + type = "submenu", + resource = resource + }) + + return index +end + +function AddButton(name, menu, callback, resource) + local index = Utils.GenerateUUID() + + Components[index] = { + name = name, + type = "button", + action = callback, + resource = resource + } + + table.insert(Menus[menu].components, { + index = index, + name = name, + type = "button" + }) +end + +function AddCheckbox(name, state, menu, callback, resource) + local index = Utils.GenerateUUID() + + Components[index] = { + name = name, + type = "checkbox", + action = callback, + state = state, + resource = resource + } + + table.insert(Menus[menu].components, { + index = index, + name = name, + type = "checkbox", + state = state + }) +end + +function AddList(name, menu, list, callback, resource) + local index = Utils.GenerateUUID() + + Components[index] = { + name = name, + type = "list", + action = callback, + list = list, + listIndex = 1, + resource = resource + } + + table.insert(Menus[menu].components, { + index = index, + name = name, + type = "list", + list = list, + listIndex = 1 + }) +end + +function OpenMenu(menu, color) + local menuToOpen = Menus[menu] + if menuToOpen then + SendNUIMessage({ + type = "open_menu", + data = { + name = menuToOpen.name, + components = menuToOpen.components, + option = 1, + color = color + } + }) + OpenedMenu = menuToOpen + HoveredIndex = 1 + end +end + +function CloseMenu() + if OpenedMenu then + SendNUIMessage({ type = "close_menu" }) + OpenedMenu = nil + HoveredIndex = 1 + end +end + +function IsAnyMenuOpen() + if OpenedMenu then + return true + end + return false +end + +function IsMenuOpened(menu) + if OpenedMenu.index == menu then + return true + end + return false +end + +function GetOpenedMenu() + if OpenedMenu then + return OpenedMenu.index + end + return nil +end + +function ClearMenu(menu) + for k, v in pairs(Menus[menu].components) do + local index = v.index + for a = 1, #Components do + table.remove(Components, index, 1) + end + table.remove(Menus[menu].components, k, 1) + end +end + +-- EXPORTS +exports("AddMenu", AddMenu) +exports("AddSubMenu", AddSubMenu) +exports("AddButton", AddButton) +exports("OpenMenu", OpenMenu) +exports("AddCheckbox", AddCheckbox) +exports("AddList", AddList) +exports("CloseMenu", CloseMenu) +exports("IsAnyMenuOpen", IsAnyMenuOpen) +exports("IsMenuOpen", IsMenuOpened) +exports("GetOpenedMenu", GetOpenedMenu) +exports("ClearMenu", ClearMenu) + +-- EVENTS +AddEventHandler("onResourceStop", function(resource) + if resource == GetCurrentResourceName() then return end + if not IsResourceStarted(resource) then return end + + for k, v in pairs(Menus) do + if v.resource == resource then + Menus[k] = nil + end + end + + for k, v in pairs(Components) do + if v.resource == resource then + Components[k] = nil + end + end + + for k, v in pairs(Resources) do + if v == resource then + Resources[k] = nil + end + end + +end) + +-- CONTROLS +function GoUp() + local prev = HoveredIndex - 1 + + if prev < 1 then + prev = #OpenedMenu.components + end + + HoveredIndex = prev + SendNUIMessage({ + type = "set_menu_option", + data = { + option = HoveredIndex + } + }) +end + +function GoDown() + local next = HoveredIndex + 1 + + if next > #OpenedMenu.components then + next = 1 + end + + HoveredIndex = next + SendNUIMessage({ + type = "set_menu_option", + data = { + option = HoveredIndex + } + }) +end + +function GoLeft() + local selected = OpenedMenu.components[HoveredIndex] + if selected then + if selected.type == "list" then + local comp = Components[selected.index] + local next = selected.listIndex - 1 + + if next < 1 then + next = #selected.list + end + + selected.listIndex = next + comp.listIndex = next + SendNUIMessage({ + type = "set_list_item", + data = { + index = selected.index, + listIndex = next + } + }) + end + end +end + +function GoRight() + local selected = OpenedMenu.components[HoveredIndex] + if selected then + if selected.type == "list" then + local comp = Components[selected.index] + local next = selected.listIndex + 1 + + if next > #selected.list then + next = 1 + end + + selected.listIndex = next + comp.listIndex = next + SendNUIMessage({ + type = "set_list_item", + data = { + index = selected.index, + listIndex = next + } + }) + end + end +end + +function Enter() + local selected = OpenedMenu.components[HoveredIndex] + if selected then + if selected.type == "submenu" then + OpenMenu(selected.index) + else + local component = Components[selected.index] + if selected.type == "checkbox" then + local newState = not component.state + component.state = newState + selected.state = newState + component.action(newState) + SendNUIMessage({ + type = "set_checkbox_state", + data = { + id = selected.index, + state = newState + } + }) + elseif selected.type == "list" then + local comp = Components[selected.index] + comp.action(comp.list[comp.listIndex]) + elseif selected.type == "button" then + Components[selected.index].action() + end + end + end +end + +function Backspace() + if OpenedMenu then + if not OpenedMenu.parent then + CloseMenu() + else + OpenMenu(OpenedMenu.parent) + end + end +end + +Citizen.CreateThread(function() + while true do + Citizen.Wait(0) + if OpenedMenu then + + if IsControlJustPressed(0, 172) then + GoUp() + elseif IsControlJustPressed(0, 173) then + GoDown() + elseif IsControlJustPressed(0, 174) then + GoLeft() + elseif IsControlJustPressed(0, 175) then + GoRight() + elseif IsControlJustPressed(0, 176) then + Enter() + elseif IsControlJustPressed(0, 177) then + Backspace() + end + + end + end +end) \ No newline at end of file diff --git a/resources/xmenu/example.lua b/resources/xmenu/example.lua new file mode 100644 index 000000000..6569024aa --- /dev/null +++ b/resources/xmenu/example.lua @@ -0,0 +1,30 @@ +-- local menu = xMenu.New("MyMenuName") + +-- local submenu = menu:BindSubMenu("SubMenuName") + +-- menu:BindButton("ButtonName", function() +-- print("TRIGGERED!") +-- end) + +-- menu:BindCheckbox("Checkbox", function(state) +-- print("STATE: " .. tostring(state)) +-- end) + +-- submenu:BindButton("ButtonName", function() +-- print("TRIGGERED!") +-- end) + +-- submenu:BindList("ListHere", { "1", "2" }, function() +-- print("LIST CALLED!") +-- end) + +-- Citizen.CreateThread(function() +-- while true do +-- Citizen.Wait(0) +-- if IsControlJustPressed(0, 121) then +-- if not menu:IsAnyMenuOpen() then +-- menu:OpenMenu() +-- end +-- end +-- end +-- end) \ No newline at end of file diff --git a/resources/xmenu/fxmanifest.lua b/resources/xmenu/fxmanifest.lua new file mode 100644 index 000000000..0e1de467e --- /dev/null +++ b/resources/xmenu/fxmanifest.lua @@ -0,0 +1,21 @@ +fx_version 'adamant' +game 'gta5' + +name 'FiveM NUI Menu Manager' +description 'An NUI menu manager for FiveM' +author 'Xander1998' +url 'https://github.com/xander1998/xmenu' + +ui_page("html/index.html") +files { + "html/index.html", + "html/events.js", + "html/script.js", + "html/style.css" +} + +client_script "classes/*.lua" +client_script "utils.lua" +client_script "menu.lua" +client_script "client.lua" +client_script "example.lua" \ No newline at end of file diff --git a/resources/xmenu/html/events.js b/resources/xmenu/html/events.js new file mode 100644 index 000000000..a4977781f --- /dev/null +++ b/resources/xmenu/html/events.js @@ -0,0 +1,17 @@ +const EVENTS = [] + +document.onreadystatechange = () => { + if (document.readyState == "complete") { + window.addEventListener("message", (event) => { + EVENTS.forEach(e => { + if (e.event == event.data.type) { + e.callback(event.data.data); + } + }); + }) + } +} + +function RegisterEvent(event, callback) { + EVENTS.push({ event, callback }); +} \ No newline at end of file diff --git a/resources/xmenu/html/index.html b/resources/xmenu/html/index.html new file mode 100644 index 000000000..d1ca54ed5 --- /dev/null +++ b/resources/xmenu/html/index.html @@ -0,0 +1,51 @@ + + + + + + XMenu + + + + +
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/resources/xmenu/html/script.js b/resources/xmenu/html/script.js new file mode 100644 index 000000000..99164f797 --- /dev/null +++ b/resources/xmenu/html/script.js @@ -0,0 +1,65 @@ +const app = new Vue({ + el: "#app", + data: { + resource: "xmenu", + visible: false, + + // Menu + MenuName: "Default", + MenuComponents: {}, + MenuOption: 0, + HeaderColor: "#0984e3" + }, + methods: { + SetResourceData(data) { + this.resource = data.resource; + }, + OpenMenu(data) { + this.MenuName = data.name; + this.MenuComponents = data.components; + this.MenuOption = data.option - 1; + this.HeaderColor = data.color || "#0984e3"; + this.visible = true; + }, + CloseMenu() { + this.MenuName = ""; + this.MenuComponents = {}; + this.MenuOption = 0; + this.visible = false; + }, + SetMenuOption(data) { + this.MenuOption = data.option - 1; + const element = document.getElementById(`${this.MenuOption}`); + element.scrollIntoView(); + }, + SetCheckboxState(data) { + const comp = this.GetMenuIndexById(data.id) + if (comp != null) { + this.MenuComponents[comp].state = data.state + } + }, + SetListItem(data) { + this.MenuComponents.forEach(comp => { + if (comp.index == data.index) { + comp.listIndex = data.listIndex + } + }); + }, + GetMenuIndexById(id) { + for (let a = 0; a < this.MenuComponents.length; a++) { + if (this.MenuComponents[a].index == id) { + return a + } + } + return null; + } + }, + mounted() { + RegisterEvent("set_resource_data", this.SetResourceData); + RegisterEvent("open_menu", this.OpenMenu); + RegisterEvent("close_menu", this.CloseMenu); + RegisterEvent("set_menu_option", this.SetMenuOption); + RegisterEvent("set_checkbox_state", this.SetCheckboxState); + RegisterEvent("set_list_item", this.SetListItem); + } +}) \ No newline at end of file diff --git a/resources/xmenu/html/style.css b/resources/xmenu/html/style.css new file mode 100644 index 000000000..b96a027f2 --- /dev/null +++ b/resources/xmenu/html/style.css @@ -0,0 +1,131 @@ +:root { + /* Vars */ + --header-font-size: 20px; + + /* Colors */ + --blue: #0984e3; + --white: white; + --midgray: #636e72; + --darkgray: #2d3436; + --red: red; + --black: #000000; +} + +html { + overflow: hidden; +} + +body { + margin: 0; +} + +#app { + width: 100%; + height: 100%; +} + +#menu_base { + position: absolute; + width: 20%; + position: absolute; + font-family: Verdana, Geneva, Tahoma, sans-serif; + background-color: var(--darkgray); +} + +#menu_header { + font-size: var(--menu-header-font-size); + padding: 15px; + text-align: center; + color: white; +} + +#menu_body { + position: relative; + margin: 1px; + max-height: 500px; + overflow-y: auto; +} + +/* BUTTON CLASSES */ +.menu_button { + padding: 12px; + text-align: center; + background-color: var(--black); + color: white; + border-style: solid; + border-width: 1px; + border-color: var(--white); + margin: 5px; +} + +.menu_button_hovered { + background-color: var(--white) !important; + border-style: solid; + border-width: 1px; + border-color: var(--black); + color: var(--black); +} + +/* CHECKBOX CLASSES */ +.menu_checkbox { + padding: 12px; + text-align: center; + background-color: var(--black); + color: white; + border-style: solid; + border-width: 1px; + border-color: var(--white); + margin: 5px; +} +.menu_checkbox_hovered { + background-color: var(--white) !important; + border-style: solid; + border-width: 1px; + border-color: var(--black); + color: var(--black); +} +.menu_checkbox_icon { + position: absolute; + right: 25px; + margin-top: -6px; +} + +/* LIST CLASSES */ +.menu_list_icon_left { + position: absolute; + left: 25px; + margin-top: -6px; +} +.menu_list_icon_right { + position: absolute; + right: 25px; + margin-top: -6px; +} + +/* POSITION CLASSES */ +.top-left { + top: 5px; + left: 5px; +} +.top-right { + top: 5px; + right: 5px; +} +.middle-left { + top: 50%; + left: 5px; + transform: translateY(-50%); +} +.middle-right { + top: 50%; + right: 5px; + transform: translateY(-50%); +} +.bottom-left { + bottom: 5px; + left: 5px; +} +.bottom-right { + bottom: 5px; + right: 5px; +} \ No newline at end of file diff --git a/resources/xmenu/utils.lua b/resources/xmenu/utils.lua new file mode 100644 index 000000000..38a541316 --- /dev/null +++ b/resources/xmenu/utils.lua @@ -0,0 +1,9 @@ +Utils = {} + +function Utils.GenerateUUID() + local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + return string.gsub(template, '[xy]', function (c) + local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb) + return string.format('%x', v) + end) +end \ No newline at end of file