diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/client/client.lua b/resources/[qb]/[qb_casino]/DLCiplLoader/client/client.lua
new file mode 100644
index 0000000..5a5f69d
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/DLCiplLoader/client/client.lua
@@ -0,0 +1,474 @@
+ local function getInteriorByType(x, y, z, name, iplName)
+ local id = 0
+
+ if not IsIplActive(iplName) then
+ RequestIpl(iplName)
+
+ while not IsIplActive(iplName) do
+ RequestIpl(iplName)
+ Wait(20)
+ end
+ end
+
+ while id == 0 do
+ id = GetInteriorAtCoordsWithType(x, y, z, name)
+ Wait(20)
+ end
+
+ return id
+end
+
+
+CreateThread(function()
+ RequestIpl("h4_mph4_terrain_occ_09")
+ RequestIpl("h4_mph4_terrain_occ_06")
+ RequestIpl("h4_mph4_terrain_occ_05")
+ RequestIpl("h4_mph4_terrain_occ_01")
+ RequestIpl("h4_mph4_terrain_occ_00")
+ RequestIpl("h4_mph4_terrain_occ_08")
+ RequestIpl("h4_mph4_terrain_occ_04")
+ RequestIpl("h4_mph4_terrain_occ_07")
+ RequestIpl("h4_mph4_terrain_occ_03")
+ RequestIpl("h4_mph4_terrain_occ_02")
+ RequestIpl("h4_islandx_terrain_04")
+ RequestIpl("h4_islandx_terrain_05_slod")
+ RequestIpl("h4_islandx_terrain_props_05_d_slod")
+ RequestIpl("h4_islandx_terrain_02")
+ RequestIpl("h4_islandx_terrain_props_05_a_lod")
+ RequestIpl("h4_islandx_terrain_props_05_c_lod")
+ RequestIpl("h4_islandx_terrain_01")
+ RequestIpl("h4_mph4_terrain_04")
+ RequestIpl("h4_mph4_terrain_06")
+ RequestIpl("h4_islandx_terrain_04_lod")
+ RequestIpl("h4_islandx_terrain_03_lod")
+ RequestIpl("h4_islandx_terrain_props_06_a")
+ RequestIpl("h4_islandx_terrain_props_06_a_slod")
+ RequestIpl("h4_islandx_terrain_props_05_f_lod")
+ RequestIpl("h4_islandx_terrain_props_06_b")
+ RequestIpl("h4_islandx_terrain_props_05_b_lod")
+ RequestIpl("h4_mph4_terrain_lod")
+ RequestIpl("h4_islandx_terrain_props_05_e_lod")
+ RequestIpl("h4_islandx_terrain_05_lod")
+ RequestIpl("h4_mph4_terrain_02")
+ RequestIpl("h4_islandx_terrain_props_05_a")
+ RequestIpl("h4_mph4_terrain_01_long_0")
+ RequestIpl("h4_islandx_terrain_03")
+ RequestIpl("h4_islandx_terrain_props_06_b_slod")
+ RequestIpl("h4_islandx_terrain_01_slod")
+ RequestIpl("h4_islandx_terrain_04_slod")
+ RequestIpl("h4_islandx_terrain_props_05_d_lod")
+ RequestIpl("h4_islandx_terrain_props_05_f_slod")
+ RequestIpl("h4_islandx_terrain_props_05_c")
+ RequestIpl("h4_islandx_terrain_02_lod")
+ RequestIpl("h4_islandx_terrain_06_slod")
+ RequestIpl("h4_islandx_terrain_props_06_c_slod")
+ RequestIpl("h4_islandx_terrain_props_06_c")
+ RequestIpl("h4_islandx_terrain_01_lod")
+ RequestIpl("h4_mph4_terrain_06_strm_0")
+ RequestIpl("h4_islandx_terrain_05")
+ RequestIpl("h4_islandx_terrain_props_05_e_slod")
+ RequestIpl("h4_islandx_terrain_props_06_c_lod")
+ RequestIpl("h4_mph4_terrain_03")
+ RequestIpl("h4_islandx_terrain_props_05_f")
+ RequestIpl("h4_islandx_terrain_06_lod")
+ RequestIpl("h4_mph4_terrain_01")
+ RequestIpl("h4_islandx_terrain_06")
+ RequestIpl("h4_islandx_terrain_props_06_a_lod")
+ RequestIpl("h4_islandx_terrain_props_06_b_lod")
+ RequestIpl("h4_islandx_terrain_props_05_b")
+ RequestIpl("h4_islandx_terrain_02_slod")
+ RequestIpl("h4_islandx_terrain_props_05_e")
+ RequestIpl("h4_islandx_terrain_props_05_d")
+ RequestIpl("h4_mph4_terrain_05")
+ RequestIpl("h4_mph4_terrain_02_grass_2")
+ RequestIpl("h4_mph4_terrain_01_grass_1")
+ RequestIpl("h4_mph4_terrain_05_grass_0")
+ RequestIpl("h4_mph4_terrain_01_grass_0")
+ RequestIpl("h4_mph4_terrain_02_grass_1")
+ RequestIpl("h4_mph4_terrain_02_grass_0")
+ RequestIpl("h4_mph4_terrain_02_grass_3")
+ RequestIpl("h4_mph4_terrain_04_grass_0")
+ RequestIpl("h4_mph4_terrain_06_grass_0")
+ RequestIpl("h4_mph4_terrain_04_grass_1")
+ RequestIpl("island_distantlights")
+ RequestIpl("island_lodlights")
+ RequestIpl("h4_yacht_strm_0")
+ RequestIpl("h4_yacht")
+ RequestIpl("h4_yacht_long_0")
+ RequestIpl("h4_islandx_yacht_01_lod")
+ RequestIpl("h4_clubposter_palmstraxx")
+ RequestIpl("h4_islandx_yacht_02_int")
+ RequestIpl("h4_islandx_yacht_02")
+ RequestIpl("h4_clubposter_moodymann")
+ RequestIpl("h4_islandx_yacht_01")
+ RequestIpl("h4_clubposter_keinemusik")
+ RequestIpl("h4_islandx_yacht_03")
+ RequestIpl("h4_ch2_mansion_final")
+ RequestIpl("h4_islandx_yacht_03_int")
+ RequestIpl("h4_yacht_critical_0")
+ RequestIpl("h4_islandx_yacht_01_int")
+ RequestIpl("h4_mph4_island_placement")
+ RequestIpl("h4_islandx_mansion_vault")
+ RequestIpl("h4_islandx_checkpoint_props")
+ RequestIpl("h4_islandairstrip_hangar_props_slod")
+ RequestIpl("h4_se_ipl_01_lod")
+ RequestIpl("h4_ne_ipl_00_slod")
+ RequestIpl("h4_se_ipl_06_slod")
+ RequestIpl("h4_ne_ipl_00")
+ RequestIpl("h4_se_ipl_02")
+ RequestIpl("h4_islandx_barrack_props_lod")
+ RequestIpl("h4_se_ipl_09_lod")
+ RequestIpl("h4_ne_ipl_05")
+ RequestIpl("h4_mph4_island_se_placement")
+ RequestIpl("h4_ne_ipl_09")
+ RequestIpl("h4_islandx_mansion_props_slod")
+ RequestIpl("h4_se_ipl_09")
+ RequestIpl("h4_mph4_mansion_b")
+ RequestIpl("h4_islandairstrip_hangar_props_lod")
+ RequestIpl("h4_islandx_mansion_entrance_fence")
+ RequestIpl("h4_nw_ipl_09")
+ RequestIpl("h4_nw_ipl_02_lod")
+ RequestIpl("h4_ne_ipl_09_slod")
+ RequestIpl("h4_sw_ipl_02")
+ RequestIpl("h4_islandx_checkpoint")
+ RequestIpl("h4_islandxdock_water_hatch")
+ RequestIpl("h4_nw_ipl_04_lod")
+ RequestIpl("h4_islandx_maindock_props")
+ RequestIpl("h4_beach")
+ RequestIpl("h4_islandx_mansion_lockup_03_lod")
+ RequestIpl("h4_ne_ipl_04_slod")
+ RequestIpl("h4_mph4_island_nw_placement")
+ RequestIpl("h4_ne_ipl_08_slod")
+ RequestIpl("h4_nw_ipl_09_lod")
+ RequestIpl("h4_se_ipl_08_lod")
+ RequestIpl("h4_islandx_maindock_props_lod")
+ RequestIpl("h4_se_ipl_03")
+ RequestIpl("h4_sw_ipl_02_slod")
+ RequestIpl("h4_nw_ipl_00")
+ RequestIpl("h4_islandx_mansion_b_side_fence")
+ RequestIpl("h4_ne_ipl_01_lod")
+ RequestIpl("h4_se_ipl_06_lod")
+ RequestIpl("h4_ne_ipl_03")
+ RequestIpl("h4_islandx_maindock")
+ RequestIpl("h4_se_ipl_01")
+ RequestIpl("h4_sw_ipl_07")
+ RequestIpl("h4_islandx_maindock_props_2")
+ RequestIpl("h4_islandxtower_veg")
+ RequestIpl("h4_mph4_island_sw_placement")
+ RequestIpl("h4_se_ipl_01_slod")
+ RequestIpl("h4_mph4_wtowers")
+ RequestIpl("h4_se_ipl_02_lod")
+ RequestIpl("h4_islandx_mansion")
+ RequestIpl("h4_nw_ipl_04")
+ RequestIpl("h4_mph4_airstrip_interior_0_airstrip_hanger")
+ RequestIpl("h4_islandx_mansion_lockup_01")
+ RequestIpl("h4_islandx_barrack_props")
+ RequestIpl("h4_nw_ipl_07_lod")
+ RequestIpl("h4_nw_ipl_00_slod")
+ RequestIpl("h4_sw_ipl_08_lod")
+ RequestIpl("h4_islandxdock_props_slod")
+ RequestIpl("h4_islandx_mansion_lockup_02")
+ RequestIpl("h4_islandx_mansion_slod")
+ RequestIpl("h4_sw_ipl_07_lod")
+ RequestIpl("h4_sw_ipl_02_lod")
+ RequestIpl("h4_se_ipl_04_slod")
+ RequestIpl("h4_islandx_checkpoint_props_lod")
+ RequestIpl("h4_se_ipl_04")
+ RequestIpl("h4_se_ipl_07")
+ RequestIpl("h4_mph4_mansion_b_strm_0")
+ RequestIpl("h4_nw_ipl_09_slod")
+ RequestIpl("h4_se_ipl_07_lod")
+ RequestIpl("h4_islandx_maindock_slod")
+ RequestIpl("h4_islandx_mansion_lod")
+ RequestIpl("h4_sw_ipl_05_lod")
+ RequestIpl("h4_nw_ipl_08")
+ RequestIpl("h4_islandairstrip_slod")
+ RequestIpl("h4_nw_ipl_07")
+ RequestIpl("h4_islandairstrip_propsb_lod")
+ RequestIpl("h4_islandx_checkpoint_props_slod")
+ RequestIpl("h4_aa_guns_lod")
+ RequestIpl("h4_sw_ipl_06")
+ RequestIpl("h4_islandx_maindock_props_2_slod")
+ RequestIpl("h4_islandx_mansion_office")
+ RequestIpl("h4_islandx_maindock_lod")
+ RequestIpl("h4_mph4_dock")
+ RequestIpl("h4_islandairstrip_propsb")
+ RequestIpl("h4_islandx_mansion_lockup_03")
+ RequestIpl("h4_nw_ipl_01_lod")
+ RequestIpl("h4_se_ipl_05_slod")
+ RequestIpl("h4_sw_ipl_01_lod")
+ RequestIpl("h4_nw_ipl_05")
+ RequestIpl("h4_islandxdock_props_2_lod")
+ RequestIpl("h4_ne_ipl_04_lod")
+ RequestIpl("h4_ne_ipl_01")
+ RequestIpl("h4_beach_party_lod")
+ RequestIpl("h4_islandx_mansion_lights")
+ RequestIpl("h4_sw_ipl_00_lod")
+ RequestIpl("h4_islandx_mansion_guardfence")
+ RequestIpl("h4_beach_props_party")
+ RequestIpl("h4_ne_ipl_03_lod")
+ RequestIpl("h4_islandx_mansion_b")
+ RequestIpl("h4_beach_bar_props")
+ RequestIpl("h4_ne_ipl_04")
+ RequestIpl("h4_sw_ipl_08_slod")
+ RequestIpl("h4_islandxtower")
+ RequestIpl("h4_se_ipl_00_slod")
+ RequestIpl("h4_islandx_barrack_hatch")
+ RequestIpl("h4_ne_ipl_06_slod")
+ RequestIpl("h4_ne_ipl_03_slod")
+ RequestIpl("h4_sw_ipl_09_slod")
+ RequestIpl("h4_ne_ipl_02_slod")
+ RequestIpl("h4_nw_ipl_04_slod")
+ RequestIpl("h4_ne_ipl_05_lod")
+ RequestIpl("h4_nw_ipl_08_slod")
+ RequestIpl("h4_sw_ipl_05_slod")
+ RequestIpl("h4_islandx_mansion_b_lod")
+ RequestIpl("h4_ne_ipl_08")
+ RequestIpl("h4_islandxdock_props")
+ RequestIpl("h4_islandairstrip_doorsopen_lod")
+ RequestIpl("h4_se_ipl_05_lod")
+ RequestIpl("h4_islandxcanal_props_slod")
+ RequestIpl("h4_se_ipl_02_slod")
+ RequestIpl("h4_nw_ipl_02")
+ RequestIpl("h4_ne_ipl_08_lod")
+ RequestIpl("h4_sw_ipl_08")
+ RequestIpl("h4_islandairstrip")
+ RequestIpl("h4_islandairstrip_props_lod")
+ RequestIpl("h4_se_ipl_05")
+ RequestIpl("h4_ne_ipl_02_lod")
+ RequestIpl("h4_islandx_maindock_props_2_lod")
+ RequestIpl("h4_sw_ipl_03_slod")
+ RequestIpl("h4_ne_ipl_01_slod")
+ RequestIpl("h4_beach_props_slod")
+ RequestIpl("h4_underwater_gate_closed")
+ RequestIpl("h4_ne_ipl_00_lod")
+ RequestIpl("h4_islandairstrip_doorsopen")
+ RequestIpl("h4_sw_ipl_01_slod")
+ RequestIpl("h4_se_ipl_00")
+ RequestIpl("h4_se_ipl_06")
+ RequestIpl("h4_islandx_mansion_lockup_02_lod")
+ RequestIpl("h4_islandxtower_veg_lod")
+ RequestIpl("h4_sw_ipl_00")
+ RequestIpl("h4_se_ipl_04_lod")
+ RequestIpl("h4_nw_ipl_07_slod")
+ RequestIpl("h4_islandx_mansion_props_lod")
+ RequestIpl("h4_islandairstrip_hangar_props")
+ RequestIpl("h4_nw_ipl_06_lod")
+ RequestIpl("h4_islandxtower_lod")
+ RequestIpl("h4_islandxdock_lod")
+ RequestIpl("h4_islandxdock_props_lod")
+ RequestIpl("h4_beach_party")
+ RequestIpl("h4_nw_ipl_06_slod")
+ RequestIpl("h4_nw_ipl_00_lod")
+ RequestIpl("h4_ne_ipl_02")
+ RequestIpl("h4_islandxdock_slod")
+ RequestIpl("h4_se_ipl_07_slod")
+ RequestIpl("h4_islandxdock")
+ RequestIpl("h4_islandxdock_props_2_slod")
+ RequestIpl("h4_islandairstrip_props")
+ RequestIpl("h4_sw_ipl_09")
+ RequestIpl("h4_ne_ipl_06")
+ RequestIpl("h4_se_ipl_03_lod")
+ RequestIpl("h4_nw_ipl_03")
+ RequestIpl("h4_islandx_mansion_lockup_01_lod")
+ RequestIpl("h4_beach_lod")
+ RequestIpl("h4_ne_ipl_07_lod")
+ RequestIpl("h4_nw_ipl_01")
+ RequestIpl("h4_mph4_island_lod")
+ RequestIpl("h4_islandx_mansion_office_lod")
+ RequestIpl("h4_islandairstrip_lod")
+ RequestIpl("h4_beach_props_lod")
+ RequestIpl("h4_nw_ipl_05_slod")
+ RequestIpl("h4_islandx_checkpoint_lod")
+ RequestIpl("h4_nw_ipl_05_lod")
+ RequestIpl("h4_nw_ipl_03_slod")
+ RequestIpl("h4_nw_ipl_03_lod")
+ RequestIpl("h4_sw_ipl_05")
+ RequestIpl("h4_mph4_mansion")
+ RequestIpl("h4_sw_ipl_03")
+ RequestIpl("h4_se_ipl_08_slod")
+ RequestIpl("h4_mph4_island_ne_placement")
+ RequestIpl("h4_aa_guns")
+ RequestIpl("h4_islandairstrip_propsb_slod")
+ RequestIpl("h4_sw_ipl_01")
+ RequestIpl("h4_mansion_remains_cage")
+ RequestIpl("h4_nw_ipl_01_slod")
+ RequestIpl("h4_ne_ipl_06_lod")
+ RequestIpl("h4_se_ipl_08")
+ RequestIpl("h4_sw_ipl_04_slod")
+ RequestIpl("h4_sw_ipl_04_lod")
+ RequestIpl("h4_mph4_beach")
+ RequestIpl("h4_sw_ipl_06_lod")
+ RequestIpl("h4_sw_ipl_06_slod")
+ RequestIpl("h4_se_ipl_00_lod")
+ RequestIpl("h4_ne_ipl_07_slod")
+ RequestIpl("h4_mph4_mansion_strm_0")
+ RequestIpl("h4_nw_ipl_02_slod")
+ RequestIpl("h4_mph4_airstrip")
+ RequestIpl("h4_island_padlock_props")
+ RequestIpl("h4_islandairstrip_props_slod")
+ RequestIpl("h4_nw_ipl_06")
+ RequestIpl("h4_sw_ipl_09_lod")
+ RequestIpl("h4_islandxcanal_props_lod")
+ RequestIpl("h4_ne_ipl_05_slod")
+ RequestIpl("h4_se_ipl_09_slod")
+ RequestIpl("h4_islandx_mansion_vault_lod")
+ RequestIpl("h4_se_ipl_03_slod")
+ RequestIpl("h4_nw_ipl_08_lod")
+ RequestIpl("h4_islandx_barrack_props_slod")
+ RequestIpl("h4_islandxtower_veg_slod")
+ RequestIpl("h4_sw_ipl_04")
+ RequestIpl("h4_islandx_mansion_props")
+ RequestIpl("h4_islandxtower_slod")
+ RequestIpl("h4_beach_props")
+ RequestIpl("h4_islandx_mansion_b_slod")
+ RequestIpl("h4_islandx_maindock_props_slod")
+ RequestIpl("h4_sw_ipl_07_slod")
+ RequestIpl("h4_ne_ipl_07")
+ RequestIpl("h4_islandxdock_props_2")
+ RequestIpl("h4_ne_ipl_09_lod")
+ RequestIpl("h4_islandxcanal_props")
+ RequestIpl("h4_beach_slod")
+ RequestIpl("h4_sw_ipl_00_slod")
+ RequestIpl("h4_sw_ipl_03_lod")
+ RequestIpl("h4_islandx_disc_strandedshark")
+ RequestIpl("h4_islandx_disc_strandedshark_lod")
+ RequestIpl("h4_islandx")
+ RequestIpl("h4_islandx_props_lod")
+ RequestIpl("h4_mph4_island_strm_0")
+ RequestIpl("h4_islandx_sea_mines")
+ RequestIpl("h4_mph4_island")
+ RequestIpl("h4_boatblockers")
+ RequestIpl("h4_mph4_island_long_0")
+ RequestIpl("h4_islandx_disc_strandedwhale")
+ RequestIpl("h4_islandx_disc_strandedwhale_lod")
+ RequestIpl("h4_islandx_props")
+ RequestIpl("h4_int_placement_h4_interior_1_dlc_int_02_h4_milo_")
+ RequestIpl("h4_int_placement_h4_interior_0_int_sub_h4_milo_")
+ RequestIpl("h4_int_placement_h4")
+ RequestIpl("vw_casino_penthouse")
+ RequestIpl("hei_dlc_windows_casino")
+
+ local penthouse = getInteriorByType(976.6364,70.2947,115.1641,"vw_dlc_casino_apart", "vw_casino_penthouse")
+ local ks_casino_vault = getInteriorByType(946.251,43.2715,58.9172,"ks_casino_vault", "ks_casino_vault_milo_")
+ local ks_casino_main = getInteriorByType(935.1050,42.5656,71.2737,"ks_casino_main", "ks_casino_main_milo_")
+ local ks_casino_back = getInteriorByType(974.5600,22.5161,70.8396,"ks_casino_back", "ks_casino_back_milo_")
+ local ks_casino_tunnel = getInteriorByType(930.1539,-0.2010,59.1323,"ks_casino_tunnel", "ks_casino_tunnel_milo_")
+
+EnableInteriorProp(penthouse, "set_pent_tint_shell")
+ DisableInteriorProp(penthouse, "set_pent_bar_party_1")
+ EnableInteriorProp(penthouse, "set_pent_media_bar_open")
+ EnableInteriorProp(penthouse, "set_pent_spa_bar_open")
+ EnableInteriorProp(penthouse, "set_pent_dealer")
+ DisableInteriorProp(penthouse, "set_pent_nodealer")
+ DisableInteriorProp(penthouse, "set_pent_media_bar_closed")
+ DisableInteriorProp(penthouse, "set_pent_spa_bar_closed")
+ DisableInteriorProp(penthouse, "set_pent_pattern_01")
+ DisableInteriorProp(penthouse, "set_pent_pattern_03")
+ DisableInteriorProp(penthouse, "set_pent_pattern_02")
+ DisableInteriorProp(penthouse, "set_pent_pattern_04")
+ DisableInteriorProp(penthouse, "set_pent_pattern_05")
+ DisableInteriorProp(penthouse, "set_pent_pattern_06")
+ DisableInteriorProp(penthouse, "set_pent_pattern_07")
+ DisableInteriorProp(penthouse, "set_pent_pattern_08")
+ EnableInteriorProp(penthouse, "set_pent_pattern_09")
+ DisableInteriorProp(penthouse, "set_pent_arcade_modern")
+ EnableInteriorProp(penthouse, "set_pent_arcade_retro")
+ EnableInteriorProp(penthouse, "set_pent_clutter_03")
+ EnableInteriorProp(penthouse, "set_pent_clutter_02")
+ EnableInteriorProp(penthouse, "set_pent_clutter_01")
+ DisableInteriorProp(penthouse, "set_pent_lounge_blocker")
+ DisableInteriorProp(penthouse, "set_pent_guest_blocker")
+ DisableInteriorProp(penthouse, "set_pent_office_blocker")
+ DisableInteriorProp(penthouse, "set_pent_cine_blocker")
+ DisableInteriorProp(penthouse, "set_pent_spa_blocker")
+ DisableInteriorProp(penthouse, "set_pent_bar_blocker")
+ DisableInteriorProp(penthouse, "set_pent_bar_party_after")
+ DisableInteriorProp(penthouse, "set_pent_bar_clutter")
+ EnableInteriorProp(penthouse, "set_pent_bar_party_2")
+ DisableInteriorProp(penthouse, "set_pent_bar_light_0")
+ DisableInteriorProp(penthouse, "set_pent_bar_light_01")
+ DisableInteriorProp(penthouse, "set_pent_bar_light_02")
+ DisableInteriorProp(penthouse, "set_pent_bar_party_0")
+ DisableInteriorProp(penthouse, "set_pent_bar_party_1")
+
+ SetInteriorEntitySetColor(penthouse,"set_pent_tint_shell","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_party_1","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_tint_shell","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_media_bar_open","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_spa_bar_open","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_dealer","0") -- Дверцы
+ SetInteriorEntitySetColor(penthouse, "set_pent_nodealer","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_media_bar_closed","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_spa_bar_closed","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_01","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_03","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_02","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_04","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_05","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_06","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_07","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_08","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_pattern_09","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_arcade_modern","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_arcade_retro","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_clutter_03","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_clutter_02","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_clutter_01","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_lounge_blocker","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_guest_blocker","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_office_blocker","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_cine_blocker","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_spa_blocker","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_blocker","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_party_after","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_clutter","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_party_2","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_light_0","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_light_01","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_light_02","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_party_0","0")
+ SetInteriorEntitySetColor(penthouse, "set_pent_bar_party_1","0")
+ RefreshInterior(penthouse)
+
+ EnableInteriorProp(ks_casino_vault, "set_vault_diamonds_02")
+ EnableInteriorProp(ks_casino_vault, "set_vault_diamonds_01")
+ EnableInteriorProp(ks_casino_vault, "set_vault_gold_02")
+ EnableInteriorProp(ks_casino_vault, "set_vault_gold_01")
+ EnableInteriorProp(ks_casino_vault, "set_vault_art_02")
+ EnableInteriorProp(ks_casino_vault, "set_vault_art_01")
+ EnableInteriorProp(ks_casino_vault, "set_vault_cash_02")
+ EnableInteriorProp(ks_casino_vault, "set_vault_cash_01")
+ EnableInteriorProp(ks_casino_vault, "set_vault_dressing")
+ EnableInteriorProp(ks_casino_vault, "set_spawn_group2")
+ EnableInteriorProp(ks_casino_vault, "set_spawn_group1")
+ DisableInteriorProp(ks_casino_vault, "set_vault_door_broken")
+ EnableInteriorProp(ks_casino_vault, "set_vault_door")
+ DisableInteriorProp(ks_casino_vault, "set_vault_door_closed")
+ RefreshInterior(ks_casino_vault)
+
+ EnableInteriorProp(ks_casino_main, "casino_manager_default")
+ EnableInteriorProp(ks_casino_main, "casino_manager_workout")
+ RefreshInterior(ks_casino_main)
+
+ EnableInteriorProp(ks_casino_back, "casino_back_laundry_damage")
+ RefreshInterior(ks_casino_back)
+
+ EnableInteriorProp(ks_casino_tunnel, "set_tunnel_collapse")
+ RefreshInterior(ks_casino_tunnel)
+end)
+
+
+
+CreateThread(function()
+
+while true do
+
+ SetRadarAsExteriorThisFrame()
+
+ SetRadarAsInteriorThisFrame(`h4_fake_islandx`, vec(4700.0, -5145.0), 0, 0)
+
+ Wait(0)
+
+end
+end)
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/client/mph4_gtxd.meta b/resources/[qb]/[qb_casino]/DLCiplLoader/client/mph4_gtxd.meta
new file mode 100644
index 0000000..4a5411e
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/DLCiplLoader/client/mph4_gtxd.meta
@@ -0,0 +1,185 @@
+
+
+
+
+ gdIslXTerrain
+ gdIslXTerTracks
+
+
+ gdIslXTerTracks
+ h4_mph4_ter02_dirttracks
+
+
+ gdIslXTerTracks
+ h4_mph4_ter06_islandx_tracks
+
+
+ gdIslXTerTracks
+ h4_mph4_ter04_islandx_tracks
+
+
+ gdIslXTerrain
+ gdIslXTerWest
+
+
+ gdIslXTerWest
+ h4_mph4_ter01_islandx_terrain_01
+
+
+ gdIslXTerWest
+ h4_mph4_ter04_islandx_terrain_04
+
+
+ gdIslXTerrain
+ gdIslXTerEast
+
+
+ gdIslXTerEast
+ h4_mph4_ter02_terr
+
+
+ gdIslXTerEast
+ h4_mph4_ter02_airstrip
+
+
+ gdIslXTerEast
+ h4_mph4_ter05
+
+
+ gdIslXTerrain
+ h4_mph4_ter05_cropfield_large
+
+
+ gdIslXTerrain
+ h4_mph4_ter05_cropfield_small
+
+
+ gdIslXTerrain
+ h4_mph4_ter05_crops
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_structures_02
+
+
+ gdIslXTerrain
+ h4_mph4_bch_structures
+
+
+ gdIslXTerrain
+ h4_mph4_bch_structures_party
+
+
+ gdIslXTerrain
+ h4_mph4_bch_structures_dock
+
+
+ gdIslXTerrain
+ h4_mph4_bch_gates
+
+
+ gdIslXTerrain
+ h4_mph4_bch_dock_ground
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_structures_04
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_structures_03
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_lighthouse
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_islandx_terrainplugs
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_detail
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_barriers
+
+
+ gdIslXTerrain
+ h4_mph4_wtowers_checkpoint_01
+
+
+ gdIslXTerrain
+ gdIslXMansion
+
+
+ gdIslXMansion
+ gdIslXMansionBuildings
+
+
+ gdIslXMansionBuildings
+ h4_mph4_manb_islandx_mansion_b
+
+
+ gdIslXMansionBuildings
+ h4_mph4_man_islandx_mansion
+
+
+ gdIslXMansion
+ h4_mph4_wtowers_mansionwalls
+
+
+ gdIslXTerrain
+ h4_mph4_air_islandairstrip_tower
+
+
+ gdIslXTerrain
+ h4_mph4_air_islandairstrip_structures
+
+
+ gdIslXTerrain
+ h4_mph4_air_islandairstrip_hanger
+
+
+ gdIslXTerrain
+ h4_mph4_air_islandairstrip_compound
+
+
+ gdIslXTerrain
+ h4_mph4_air_hanger_doors_open
+
+
+ gdIslXTerrain
+ h4_mph4_air_hanger_doors_closed
+
+
+ gdIslXTerrain
+ h4_mph4_air_islandairstrip_abandoned
+
+
+ gdIslXTerrain
+ h4_mph4_air_islandairstrip_ruins
+
+
+ gdIslXTerrain
+ gdIslXDockBuildings
+
+
+ gdIslXDockBuildings
+ gdIslXDockWarehouses
+
+
+ gdIslXDockWarehouses
+ h4_mph4_dock_warehouses
+
+
+ gdIslXDockWarehouses
+ h4_mph4_dock_islandx_maindocks
+
+
+ gdIslXDockBuildings
+ h4_mph4_dock_barracks
+
+
+
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/client/water.lua b/resources/[qb]/[qb_casino]/DLCiplLoader/client/water.lua
new file mode 100644
index 0000000..87f497c
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/DLCiplLoader/client/water.lua
@@ -0,0 +1,8 @@
+Citizen.CreateThread(function()
+ while true do
+ Wait(0)
+ Citizen.InvokeNative(0xC54A08C85AE4D410, 0.5)
+ end
+end)
+
+--0xB96B00E976BE977F
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/fxmanifest.lua b/resources/[qb]/[qb_casino]/DLCiplLoader/fxmanifest.lua
new file mode 100644
index 0000000..3f2fb94
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/DLCiplLoader/fxmanifest.lua
@@ -0,0 +1,22 @@
+fx_version 'cerulean'
+
+description 'Casino and Cayo Perico IPL loader by Kromstar Gaming#8228'
+
+version '1.0'
+
+game 'gta5'
+
+this_is_a_map 'yes'
+
+
+
+client_scripts {
+ 'client/client.lua',
+ 'client/mph4_gtxd.meta',
+ 'client/water.lua',
+}
+
+data_file 'GTXD_PARENTING_DATA' 'client/mph4_gtxd.meta'
+
+
+--IMPORTANT For this DLC Loader to render correctly please ensure your game build is set to the latest version in your server.cfg. sv_enforceGameBuild 2189 and ensure that you are running Canary on all clients connecting--
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/_manifest.ymf b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/_manifest.ymf
new file mode 100644
index 0000000..9cc8721
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/_manifest.ymf differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ch_cutscene_casino.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ch_cutscene_casino.ymap
new file mode 100644
index 0000000..5542328
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ch_cutscene_casino.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_11.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_11.ybn
new file mode 100644
index 0000000..3112ced
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_11.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_3.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_3.ybn
new file mode 100644
index 0000000..e3995e6
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_3.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_4.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_4.ybn
new file mode 100644
index 0000000..80ebe81
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_4.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_5.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_5.ybn
new file mode 100644
index 0000000..733c680
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_5.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_6.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_6.ybn
new file mode 100644
index 0000000..585bdcf
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_6.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_8.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_8.ybn
new file mode 100644
index 0000000..4d335b8
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_8.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casino_decals.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casino_decals.ydr
new file mode 100644
index 0000000..0ea1d1b
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casino_decals.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casinonew_bottom.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casinonew_bottom.ydr
new file mode 100644
index 0000000..5dd642f
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casinonew_bottom.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casinonew_penthouse.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casinonew_penthouse.ydr
new file mode 100644
index 0000000..dc0521f
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_casinonew_penthouse.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_strm_2.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_strm_2.ymap
new file mode 100644
index 0000000..469ac13
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_ch3_12_strm_2.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_casino_door.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_casino_door.ymap
new file mode 100644
index 0000000..c1922ba
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_casino_door.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_casino_door_broken.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_casino_door_broken.ymap
new file mode 100644
index 0000000..31c2312
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_casino_door_broken.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_windows_casino.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_windows_casino.ymap
new file mode 100644
index 0000000..bd37d84
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_dlc_windows_casino.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_vw_dlc_casino_door_replay.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_vw_dlc_casino_door_replay.ymap
new file mode 100644
index 0000000..54fe995
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hei_vw_dlc_casino_door_replay.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_back.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_back.ybn
new file mode 100644
index 0000000..49aa78e
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_back.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_heist.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_heist.ybn
new file mode 100644
index 0000000..5a119cb
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_heist.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_hotel.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_hotel.ybn
new file mode 100644
index 0000000..972b2fb
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_hotel.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_utility.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_utility.ybn
new file mode 100644
index 0000000..81bbbc8
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_utility.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_vault.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_vault.ybn
new file mode 100644
index 0000000..055260f
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/hi@ks_casino_vault.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back.ybn
new file mode 100644
index 0000000..99a9718
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back.ytyp
new file mode 100644
index 0000000..e7582a1
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back_milo_.ymap
new file mode 100644
index 0000000..5c7ed5c
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_back_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage.ybn
new file mode 100644
index 0000000..796d1a4
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage.ytyp
new file mode 100644
index 0000000..d598848
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage_milo_.ymap
new file mode 100644
index 0000000..77c87be
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_garage_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist.ybn
new file mode 100644
index 0000000..dc57ccf
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist.ytyp
new file mode 100644
index 0000000..229d39f
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist_milo_.ymap
new file mode 100644
index 0000000..3410b68
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_heist_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel.ybn
new file mode 100644
index 0000000..ee69a34
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel.ytyp
new file mode 100644
index 0000000..86b8214
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel_milo_.ymap
new file mode 100644
index 0000000..1623653
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_hotel_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading.ybn
new file mode 100644
index 0000000..e899bb1
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading.ytyp
new file mode 100644
index 0000000..fd1bfa5
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading_milo_.ymap
new file mode 100644
index 0000000..80f6df7
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_loading_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main.ybn
new file mode 100644
index 0000000..434e99a
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main.ytyp
new file mode 100644
index 0000000..3def184
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main_milo_.ymap
new file mode 100644
index 0000000..cf2d5b2
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_main_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft.ybn
new file mode 100644
index 0000000..f0a3cf0
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft.ytyp
new file mode 100644
index 0000000..cf35ba0
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft_milo_.ymap
new file mode 100644
index 0000000..fdcbb52
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_shaft_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel.ybn
new file mode 100644
index 0000000..8b4037e
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel.ytyp
new file mode 100644
index 0000000..17ef287
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel_milo_.ymap
new file mode 100644
index 0000000..869f2d0
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_tunnel_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility.ybn
new file mode 100644
index 0000000..8f2ff08
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility.ytyp
new file mode 100644
index 0000000..30ffdd9
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility_milo_.ymap
new file mode 100644
index 0000000..3e7d375
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_utility_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault.ybn
new file mode 100644
index 0000000..1ccd862
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault.ytyp
new file mode 100644
index 0000000..5723e3e
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault_milo_.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault_milo_.ymap
new file mode 100644
index 0000000..f09a04a
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_casino_vault_milo_.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_ch3_12_casino_new_door.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_ch3_12_casino_new_door.ydr
new file mode 100644
index 0000000..1a3ccfe
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_ch3_12_casino_new_door.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_dlc_casino_main.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_dlc_casino_main.ybn
new file mode 100644
index 0000000..bcb0b16
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_dlc_casino_main.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_garage_door.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_garage_door.ydr
new file mode 100644
index 0000000..a2fdb2e
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_garage_door.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_casino_shell_01.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_casino_shell_01.ydr
new file mode 100644
index 0000000..d205073
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_casino_shell_01.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_decals.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_decals.ydr
new file mode 100644
index 0000000..6c28d9c
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_decals.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_details.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_details.ydr
new file mode 100644
index 0000000..4d29a8a
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_details.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_entry.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_entry.ydr
new file mode 100644
index 0000000..4a7c432
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_entry.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_lamps.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_lamps.ydr
new file mode 100644
index 0000000..959a857
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_lamps.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_signage1.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_signage1.ydr
new file mode 100644
index 0000000..4c3198b
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_gamingr1_signage1.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_reception_desk.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_reception_desk.ydr
new file mode 100644
index 0000000..979d6d8
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_reception_desk.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_reception_details.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_reception_details.ydr
new file mode 100644
index 0000000..e1f1a3d
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint01_reception_details.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_beams.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_beams.ydr
new file mode 100644
index 0000000..e399bc6
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_beams.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_extras2.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_extras2.ydr
new file mode 100644
index 0000000..b4defa4
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_extras2.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell.ydr
new file mode 100644
index 0000000..b079103
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell_doors01.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell_doors01.ydr
new file mode 100644
index 0000000..ce6d06a
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell_doors01.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell_edgeblend.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell_edgeblend.ydr
new file mode 100644
index 0000000..aa2103c
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garage_shell_edgeblend.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garagedecal.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garagedecal.ydr
new file mode 100644
index 0000000..7292798
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_garagedecal.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_pipes2.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_pipes2.ydr
new file mode 100644
index 0000000..cf621e8
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_pipes2.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_vents01.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_vents01.ydr
new file mode 100644
index 0000000..ff238f9
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_vents01.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_vents02.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_vents02.ydr
new file mode 100644
index 0000000..02c66d6
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/ks_vwint03_vents02.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_casino_penthouse.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_casino_penthouse.ymap
new file mode 100644
index 0000000..754673a
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_casino_penthouse.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_2.ybn b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_2.ybn
new file mode 100644
index 0000000..3b5a1e0
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_2.ybn differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_long_0.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_long_0.ymap
new file mode 100644
index 0000000..0b1dee3
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_long_0.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_strm_0.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_strm_0.ymap
new file mode 100644
index 0000000..8835812
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_ch3_additions_strm_0.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_dlc_casino_door.ymap b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_dlc_casino_door.ymap
new file mode 100644
index 0000000..6c4015b
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_dlc_casino_door.ymap differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwdlc_int_02.ytyp b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwdlc_int_02.ytyp
new file mode 100644
index 0000000..0e18cf9
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwdlc_int_02.ytyp differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint01_casino_shell_02.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint01_casino_shell_02.ydr
new file mode 100644
index 0000000..17c73d0
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint01_casino_shell_02.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint01_elevator_02_details.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint01_elevator_02_details.ydr
new file mode 100644
index 0000000..a0bd9a5
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint01_elevator_02_details.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_01_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_01_lobby.ydr
new file mode 100644
index 0000000..72068fc
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_01_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_02_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_02_lobby.ydr
new file mode 100644
index 0000000..61ecb4e
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_02_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_03_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_03_lobby.ydr
new file mode 100644
index 0000000..0955d54
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_03_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_04_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_04_lobby.ydr
new file mode 100644
index 0000000..2f78a97
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_04_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_05_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_05_lobby.ydr
new file mode 100644
index 0000000..91b665d
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_05_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_06_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_06_lobby.ydr
new file mode 100644
index 0000000..2d9d5e0
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_06_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_07_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_07_lobby.ydr
new file mode 100644
index 0000000..dfe93a3
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_07_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_08_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_08_lobby.ydr
new file mode 100644
index 0000000..60e5ed7
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_08_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_09_lobby.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_09_lobby.ydr
new file mode 100644
index 0000000..823966b
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pattern_09_lobby.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_hal_nontint.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_hal_nontint.ydr
new file mode 100644
index 0000000..f2b5e64
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_hal_nontint.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_hal_shell.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_hal_shell.ydr
new file mode 100644
index 0000000..ff6c75f
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_hal_shell.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_signs.ydr b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_signs.ydr
new file mode 100644
index 0000000..f98071e
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/casinointerior/vw_vwint02_pent_signs.ydr differ
diff --git a/resources/[qb]/[qb_casino]/DLCiplLoader/stream/cpminimap/int3232302352.gfx b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/cpminimap/int3232302352.gfx
new file mode 100644
index 0000000..f3f7300
Binary files /dev/null and b/resources/[qb]/[qb_casino]/DLCiplLoader/stream/cpminimap/int3232302352.gfx differ
diff --git a/resources/[qb]/[qb_casino]/LICENSE b/resources/[qb]/[qb_casino]/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/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/[qb]/[qb_casino]/README.md b/resources/[qb]/[qb_casino]/README.md
new file mode 100644
index 0000000..0eafe07
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/README.md
@@ -0,0 +1,84 @@
+# doj-casino
+
+Edited Casino Pack for QBus Framework
+
+
+# Updated 7/9/23
+- Added **[KGV](https://github.com/Xinerki/kgv-blackjack)** & **[Rubbertoe98](https://github.com/rubbertoe98)** Blackjack
+# Updated 7/7/23
+- Fixed most of the casino & added & removed a few things
+
+
+
+
+# Dependencies
+**[PolyZone](https://github.com/mkafrin/PolyZone)**
+
+**[qb-menu](https://github.com/qbcore-framework/qb-menu)**
+
+**[qb-target](https://github.com/BerkieBb/qb-target)**
+
+**[casinoUi](https://github.com/dojwun/casinoUi)**
+
+# Images
+
+
+
+
+
+
+## casino-walls
+
+**[preview](https://streamable.com/jem98k)** OLD VIDEO
+
+**[source](https://forum.cfx.re/t/cayo-perico-casino-dlc-ipl-loader/2099391)**
+
+## casino-blackjackKGV
+
+**[preview](https://streamable.com/jpabhl)** OLD VIDEO
+
+**[source](https://github.com/Xinerki/kgv-blackjack)**
+
+## casino-blackjackRT98
+
+**[preview](https://streamable.com/rfjiol)** OLD VIDEO
+
+**[source](https://github.com/rubbertoe98/DiamondBlackjack)**
+
+
+## casino-luckywheel
+
+**[preview](https://streamable.com/ucv48w)** OLD VIDEO
+
+**[source](https://github.com/Sn0wBiT/esx_tpnrp_luckywheel)**
+
+## casino-insidetrack
+
+**[preview](https://streamable.com/m5eyk)** OLD VIDEO
+
+**[source](https://github.com/MRV6/mp_insidetrack)**
+
+## casino-slots
+
+**[preview](https://streamable.com/5xwkki)** OLD VIDEO
+
+**[source](https://github.com/ChatDisabled/dc-casino/tree/nice)**
+
+## casino-roulette
+
+**[preview](https://streamable.com/85vjqc)** OLD VIDEO
+
+**[source](https://forum.cfx.re/t/standalone-paid-aquiver-casino-roulette/2925508)**
+
+## casino-poker
+
+**[preview](NONE)** Coming soon
+
+**[source](https://forum.cfx.re/t/standalone-paid-aquiver-three-card-poker/3378769)**
+
+# qb-core/shared.lua info
+```
+ ["casino_goldchip"] = {["name"] = "casino_goldchip", ["label"] = "Casino Chip", ["weight"] = 0, ["type"] = "item", ["image"] = "casino_goldchip.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "Diamond Casino Chip"},
+ ["casino_member"] = {["name"] = "casino_member", ["label"] = "Casino Membership", ["weight"] = 500, ["type"] = "item", ["image"] = "casino_member.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "Diamond Casino Member Card"},
+ ["casino_vip"] = {["name"] = "casino_vip", ["label"] = "V.I.P Membership", ["weight"] = 500, ["type"] = "item", ["image"] = "casino_vip.png", ["unique"] = true, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "Diamond Casino V.I.P Card"},
+```
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackKGV/client/client.lua b/resources/[qb]/[qb_casino]/casino-blackjackKGV/client/client.lua
new file mode 100644
index 0000000..051b1e8
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackKGV/client/client.lua
@@ -0,0 +1,1080 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+local seatSideAngle = 30
+local bet = 0
+local hand = {}
+local splitHand = {}
+local timeLeft = 0
+local satDownCallback = nil
+local standUpCallback = nil
+local leaveCheckCallback = nil
+local _lambo = nil
+local canSitDownCallback = nil
+
+-- isEscorted = false
+-- isHandcuffed = false
+-- isDead = false
+
+CreateThread(function()
+ while true do
+ sleep = 1000
+ local playerCoords = GetEntityCoords(PlayerPedId())
+ local closestChairDist = #(playerCoords - vector3(948.54760742188, 32.051155090332, 76.101249084473))
+ if closestChairDist < 55.0 then
+ sleep = 10
+ DisableControlAction(0, 140, true)
+ DisableControlAction(0, 135, true)
+ DisableControlAction(0, 122, true)
+ DisableControlAction(0, 92, true)
+ DisableControlAction(0, 24, true)
+ DisableControlAction(0, 69, true)
+ DisableControlAction(0, 142, true)
+ DisableControlAction(0, 135, true)
+ DisableControlAction(0, 19, true)
+ FreezeEntityPosition(_lambo, true)
+ end
+ Wait(sleep)
+ end
+end)
+
+function SetSatDownCallback(cb)
+ satDownCallback = cb
+end
+
+function SetStandUpCallback(cb)
+ standUpCallback = cb
+end
+
+function SetLeaveCheckCallback(cb)
+ leaveCheckCallback = cb
+end
+
+function SetCanSitDownCallback(cb)
+ canSitDownCallback = cb
+end
+
+function findRotation( x1, y1, x2, y2 )
+ local t = -math.deg( math.atan2( x2 - x1, y2 - y1 ) )
+ return t < -180 and t + 180 or t
+end
+
+function cardValue(card)
+ local rank = 10
+ for i=2,11 do
+ if string.find(card, tostring(i)) then
+ rank = i
+ end
+ end
+ if string.find(card, 'ACE') then
+ rank = 11
+ end
+
+ return rank
+end
+
+function handValue(hand)
+ local tmpValue = 0
+ local numAces = 0
+
+ for i,v in pairs(hand) do
+ tmpValue = tmpValue + cardValue(v)
+ end
+
+ for i,v in pairs(hand) do
+ if string.find(v, 'ACE') then numAces = numAces + 1 end
+ end
+
+ repeat
+ if tmpValue > 21 and numAces > 0 then
+ tmpValue = tmpValue - 10
+ numAces = numAces - 1
+ else
+ break
+ end
+ until numAces == 0
+
+ return tmpValue
+end
+
+function CanSplitHand(hand)
+ if hand[1] and hand[2] then
+ if hand[1]:sub(-3) == hand[2]:sub(-3) and #hand == 2 then
+ if cardValue(hand[1]) == cardValue(hand[2]) then
+ return true
+ end
+ end
+ end
+ return _DEBUG
+end
+
+--[[
+ vw_prop_vw_chips_pile_01a.ydr -- $511,000
+ vw_prop_vw_chips_pile_02a.ydr -- $3,250,000
+ vw_prop_vw_chips_pile_03a.ydr -- $1,990,000
+--]]
+
+function getChips(amount)
+ if amount < 500000 then
+ local props = {}
+ local propTypes = {}
+
+ local d = #chipValues
+
+ for i = 1, #chipValues do
+ local iter = #props + 1
+ while amount >= chipValues[d] do
+ local model = chipModels[chipValues[d]]
+
+ if not props[iter] then
+ local propType = string.sub(model, 0, string.len(model) - 3)
+
+ if propTypes[propType] then
+ iter = propTypes[propType]
+ else
+ props[iter] = {}
+ propTypes[propType] = iter
+ end
+ end
+
+ props[iter][#props[iter] + 1] = model
+ amount = amount - chipValues[d]
+ end
+
+ d = d - 1
+ end
+
+ return false, props
+ elseif amount <= 500000 then
+ return true, "vw_prop_vw_chips_pile_01a"
+ elseif amount <= 5000000 then
+ return true, "vw_prop_vw_chips_pile_03a"
+ else
+ return true, "vw_prop_vw_chips_pile_02a"
+ end
+end
+
+function leaveBlackjack()
+ leavingBlackjack = true
+ selectedBet = 1
+ hand = {}
+ splitHand = {}
+end
+
+RegisterNetEvent("BLACKJACK:client:stop", function()
+ leaveBlackjack()
+end)
+
+
+
+-- RegisterCommand("bet", function(source, args, rawCommand)
+-- if args[1] and _DEBUG == true then
+-- TriggerServerEvent("BLACKJACK:SetPlayerBet", g_seat, closestChair, args[1])
+-- end
+-- end, false)
+
+
+spawnedPeds = {}
+spawnedObjects = {}
+AddEventHandler("onResourceStop", function(r)
+ if r == GetCurrentResourceName() then
+
+ for i,v in ipairs(spawnedPeds) do
+ DeleteEntity(v)
+ end
+ for i,v in ipairs(spawnedObjects) do
+ DeleteEntity(v)
+ end
+ end
+end)
+
+
+
+
+
+function CheckGender(dealerPed)
+ local models = {
+ [`s_f_y_casino_01`] = "",
+ [`s_m_y_casino_01`] = "female_"
+ }
+ return models[GetEntityModel(dealerPed)]
+end
+
+function IsSeatOccupied(coords, radius)
+ local players = GetActivePlayers()
+ local playerId = PlayerId()
+ for i = 1, #players do
+ if players[i] ~= playerId then
+ local ped = GetPlayerPed(players[i])
+ if IsEntityAtCoord(ped, coords, radius, radius, radius, 0, 0, 0) then
+ return true
+ end
+ end
+ end
+
+ return false
+end
+
+dealerHand = {}
+dealerValue = {}
+dealerHandObjs = {}
+handObjs = {}
+
+function CreatePeds()
+ if not HasAnimDictLoaded("anim_casino_b@amb@casino@games@blackjack@dealer") then
+ RequestAnimDict("anim_casino_b@amb@casino@games@blackjack@dealer")
+ repeat Wait(0) until HasAnimDictLoaded("anim_casino_b@amb@casino@games@blackjack@dealer")
+ end
+
+ if not HasAnimDictLoaded("anim_casino_b@amb@casino@games@shared@dealer@") then
+ RequestAnimDict("anim_casino_b@amb@casino@games@shared@dealer@")
+ repeat Wait(0) until HasAnimDictLoaded("anim_casino_b@amb@casino@games@shared@dealer@")
+ end
+
+ if not HasAnimDictLoaded("anim_casino_b@amb@casino@games@blackjack@player") then
+ RequestAnimDict("anim_casino_b@amb@casino@games@blackjack@player")
+ repeat Wait(0) until HasAnimDictLoaded("anim_casino_b@amb@casino@games@blackjack@player")
+ end
+
+ for i,v in pairs(customTables) do
+ -- local model = {
+ -- `vw_prop_casino_3cardpoker_01`,
+ -- `vw_prop_casino_3cardpoker_01b`,
+ -- `vw_prop_casino_blckjack_01`,
+ -- `vw_prop_casino_blckjack_01b`
+ -- }
+ local model = `vw_prop_casino_3cardpoker_01b`
+ if v.highStakes == true then
+ model = `vw_prop_casino_blckjack_01b`
+ end
+ if not HasModelLoaded(model) then
+ RequestModel(model)
+ repeat Wait(0) until HasModelLoaded(model)
+ end
+ local tableObj = CreateObjectNoOffset(model, v.coords.x, v.coords.y, v.coords.z, false, false, false)
+ SetEntityRotation(tableObj, 0.0, 0.0, v.coords.w, 2, 1)
+ SetObjectTextureVariant(tableObj, v.color or 3)
+ table.insert(spawnedObjects, tableObj)
+ end
+ chips = {}
+ hand = {}
+ splitHand = {}
+ handObjs = {}
+ for i,v in pairs(tables) do
+ dealerHand[i] = {}
+ dealerValue[i] = {}
+ dealerHandObjs[i] = {}
+ local models = {
+ `s_f_y_casino_01`,
+ `s_m_y_casino_01`
+ }
+ local model = models[1]
+ if ((i+6) % 13) < 7 then
+ model = models[2]
+ end
+
+ chips[i] = {}
+
+ for x=1,4 do
+ chips[i][x] = {}
+ end
+ handObjs[i] = {}
+
+ for x=1,4 do
+ handObjs[i][x] = {}
+ end
+
+ if not HasModelLoaded(model) then
+ RequestModel(model)
+ repeat Wait(0) until HasModelLoaded(model)
+ end
+
+ local dealer = CreatePed(4, model, v.coords.x, v.coords.y, v.coords.z, v.coords.w, false, true)
+ SetEntityCanBeDamaged(dealer, false)
+ SetBlockingOfNonTemporaryEvents(dealer, true)
+ SetPedCanRagdollFromPlayerImpact(dealer, false)
+ SetPedResetFlag(dealer, 249, true)
+ SetPedConfigFlag(dealer, 185, true)
+ SetPedConfigFlag(dealer, 108, true)
+ SetPedConfigFlag(dealer, 208, true)
+ SetDealerOutfit(dealer, i+6)
+
+ local scene = CreateSynchronizedScene(v.coords.x, v.coords.y, v.coords.z, 0.0, 0.0, v.coords.w, 2)
+ TaskSynchronizedScene(dealer, scene, "anim_casino_b@amb@casino@games@shared@dealer@", "idle", 1000.0, -8.0, 4, 1, 1148846080, 0)
+
+ spawnedPeds[i] = dealer
+ end
+end
+
+RegisterNetEvent("BLACKJACK:SyncTimer", function(_timeLeft)
+ timeLeft = _timeLeft
+end)
+
+RegisterNetEvent("BLACKJACK:PlayDealerAnim", function(i, animDict, anim)
+ CreateThread(function()
+ local Gender = CheckGender(spawnedPeds[i])
+ if Gender ~= "" then anim = string.gsub(anim, Gender,"") end
+
+ local v = tables[i]
+
+ if not HasAnimDictLoaded(animDict) then
+ RequestAnimDict(animDict)
+ repeat Wait(0) until HasAnimDictLoaded(animDict)
+ end
+ DebugPrint("PLAYING "..anim:upper().." ON DEALER "..i)
+ local scene = CreateSynchronizedScene(v.coords.x, v.coords.y, v.coords.z, 0.0, 0.0, v.coords.w, 2)
+ TaskSynchronizedScene(spawnedPeds[i], scene, animDict, anim, 8.0, 8.0, 4, 1, 1148846080, 0)
+ end)
+end)
+
+RegisterNetEvent("BLACKJACK:PlayDealerSpeech", function(i, speech)
+ CreateThread(function()
+ DebugPrint("PLAYING SPEECH "..speech:upper().." ON DEALER "..i)
+ StopCurrentPlayingAmbientSpeech(spawnedPeds[i])
+ PlayPedAmbientSpeechNative(spawnedPeds[i], speech, "SPEECH_PARAMS_FORCE_NORMAL_CLEAR")
+ end)
+end)
+
+RegisterNetEvent("BLACKJACK:DealerTurnOverCard", function(i)
+ hideUiOnStart()
+ local cardX,cardY,cardZ = GetEntityCoords(dealerHandObjs[i][1])
+ AttachEntityToEntity(dealerHandObjs[i][1], spawnedPeds[i], GetPedBoneIndex(spawnedPeds[i],28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ while not HasAnimEventFired(spawnedPeds[i],585557868) do
+ Wait(0)
+ end
+ DetachEntity(dealerHandObjs[i][1],false,true)
+ SetEntityCoordsNoOffset(dealerHandObjs[i][1], cardX,cardY,cardZ)
+ SetEntityRotation(dealerHandObjs[i][1], 0.0, 0.0, tables[i].coords.w + cardRotationOffsetsDealer[1].z)
+end)
+
+RegisterNetEvent("BLACKJACK:DealerCheckCard", function(i)
+ local cardX,cardY,cardZ = GetEntityCoords(dealerHandObjs[i][1])
+ AttachEntityToEntity(dealerHandObjs[i][1], spawnedPeds[i], GetPedBoneIndex(spawnedPeds[i],28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ while not HasAnimEventFired(spawnedPeds[i],585557868) do
+ Wait(0)
+ end
+ Wait(100)
+ DetachEntity(dealerHandObjs[i][1],false,true)
+ SetEntityCoordsNoOffset(dealerHandObjs[i][1], cardX,cardY,cardZ)
+end)
+
+RegisterNetEvent("BLACKJACK:SplitHand", function(index, seat, splitHandSize, _hand, _splitHand)
+ hand = _hand
+ splitHand = _splitHand
+
+ DebugPrint("splitHandSize = "..splitHandSize)
+ DebugPrint("split card coord = "..tostring(GetObjectOffsetFromCoords(tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, tables[index].coords.w, cardSplitOffsets[seat][1])))
+
+ SetEntityCoordsNoOffset(handObjs[index][seat][#handObjs[index][seat]], GetObjectOffsetFromCoords(tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, tables[index].coords.w, cardSplitOffsets[5-seat][1]))
+ SetEntityRotation(handObjs[index][seat][#handObjs[index][seat]], 0.0, 0.0, cardSplitRotationOffsets[seat][splitHandSize])
+end)
+
+selectedBet = 1
+
+
+RegisterNetEvent("BLACKJACK:PlaceBetChip", function(index, seat, bet, double, split)
+ CreateThread(function()
+ local chipPile, props = getChips(bet)
+ if chipPile then
+ local model = GetHashKey(props)
+ DebugPrint(bet)
+ DebugPrint(seat)
+ DebugPrint(tostring(props))
+ DebugPrint(tostring(pileOffsets[seat]))
+ RequestModel(model)
+ repeat Wait(0) until HasModelLoaded(model)
+ local location = 1
+ if double == true then location = 2 end
+ local chip = CreateObjectNoOffset(model, tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, false, false, false)
+ table.insert(spawnedObjects, chip)
+ table.insert(chips[index][seat], chip)
+ if split == false then
+ SetEntityCoordsNoOffset(chip, GetObjectOffsetFromCoords(tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, tables[index].coords.w, pileOffsets[seat][location].x, pileOffsets[seat][location].y, chipHeights[1]))
+ SetEntityRotation(chip, 0.0, 0.0, tables[index].coords.w + pileRotationOffsets[seat][3 - location].z)
+ else
+ SetEntityCoordsNoOffset(chip, GetObjectOffsetFromCoords(tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, tables[index].coords.w, pileOffsets[seat][2].x, pileOffsets[seat][2].y, chipHeights[1]))
+ SetEntityRotation(chip, 0.0, 0.0, tables[index].coords.w + pileRotationOffsets[seat][3 - location].z)
+ end
+ else
+ local chipXOffset = 0.0
+ local chipYOffset = 0.0
+ if split or double then
+ if seat == 1 then
+ chipXOffset = chipXOffset + 0.03
+ chipYOffset = chipYOffset + 0.05
+ elseif seat == 2 then
+ chipXOffset = chipXOffset + 0.05
+ chipYOffset = chipYOffset + 0.02
+ elseif seat == 3 then
+ chipXOffset = chipXOffset + 0.05
+ chipYOffset = chipYOffset - 0.02
+ elseif seat == 4 then
+ chipXOffset = chipXOffset + 0.02
+ chipYOffset = chipYOffset - 0.05
+ end
+ end
+ for i = 1, #props do
+ local chipGap = 0.0
+ for j = 1, #props[i] do
+ local model = GetHashKey(props[i][j])
+ DebugPrint(bet)
+ DebugPrint(seat)
+ DebugPrint(tostring(props[i][j]))
+ DebugPrint(tostring(chipOffsets[seat]))
+ RequestModel(model)
+ repeat Wait(0) until HasModelLoaded(model)
+ local location = i
+ local chip = CreateObjectNoOffset(model, tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, false, false, false)
+ table.insert(spawnedObjects, chip)
+ table.insert(chips[index][seat], chip)
+ SetEntityCoordsNoOffset(chip, GetObjectOffsetFromCoords(tables[index].coords.x, tables[index].coords.y, tables[index].coords.z, tables[index].coords.w, chipOffsets[seat][location].x + chipXOffset, chipOffsets[seat][location].y + chipYOffset, chipHeights[1] + chipGap))
+ SetEntityRotation(chip, 0.0, 0.0, tables[index].coords.w + chipRotationOffsets[seat][location].z)
+ chipGap = chipGap + ((chipThickness[model] ~= nil) and chipThickness[model] or 0.0)
+ end
+ end
+ end
+ end)
+end)
+
+function hideUi()
+ exports["qb-core"]:HideText()
+ exports['casinoUi']:HideCasinoUi('hide')
+end
+
+function hideUiOnStart()
+ exports["qb-core"]:HideText()
+ exports['casinoUi']:HideCasinoUi('hide')
+ exports['qb-menu']:closeMenu()
+end
+
+RegisterNetEvent("BLACKJACK:BetReceived")
+
+local upPressed = false
+local downPressed = false
+
+
+RegisterNetEvent("BLACKJACK:RequestBets", function(index)
+ -- timeLeft = _timeLeft
+ if leavingBlackjack == true then leaveBlackjack() return end
+ QBCore.Functions.TriggerCallback('BLACKJACKKGV:server:blackChipsAmount', function(result)
+ retval = result
+ CreateThread(function()
+ scrollerIndex = index
+ exports["qb-core"]:DrawText("Place Bet: ↵
Adjust Bet: ↑/↓Exit: ←", "top")
+ while true do
+ Wait(0)
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino BlackjackTime Left: 0:"..timeLeft.."Current Bet: "..bet.." Availble chips: "..math.floor(retval))
+ local tableLimit = (tables[scrollerIndex].highStakes == true) and #bettingNums or lowTableLimit
+ if IsControlJustPressed(1, 205) then -- Q / Y
+ selectedBet = tableLimit
+ elseif IsControlJustPressed(1, 202) then -- ESC / B
+ leaveBlackjack()
+ return
+ end
+ if not upPressed then
+ if IsControlJustPressed(1, 172) then -- UP ARROW
+ upPressed = true
+ CreateThread(function()
+ selectedBet = selectedBet + 1
+ if selectedBet > tableLimit then selectedBet = 1 end
+ Wait(175)
+ while IsControlPressed(1, 172) do
+ selectedBet = selectedBet + 1
+ if selectedBet > tableLimit then selectedBet = 1 end
+ Wait(125)
+ end
+
+ upPressed = false
+ end)
+ end
+ end
+ if not downPressed then
+ if IsControlJustPressed(1, 173) then -- DOWN ARROW
+ downPressed = true
+ CreateThread(function()
+ selectedBet = selectedBet - 1
+ if selectedBet < 1 then selectedBet = tableLimit end
+ Wait(175)
+ while IsControlPressed(1, 173) do
+ selectedBet = selectedBet - 1
+ if selectedBet < 1 then selectedBet = tableLimit end
+ Wait(125)
+ end
+
+ downPressed = false
+ end)
+ end
+ end
+ bet = bettingNums[selectedBet] or 10000
+ if #bettingNums < lowTableLimit and tables[scrollerIndex].highStakes == true then
+ bet = bet * 10
+ end
+ if IsControlJustPressed(1, 201) then -- ENTER / A
+ TriggerServerEvent("BLACKJACK:CheckPlayerBet", g_seat, bet)
+ local betCheckRecieved = false
+ local canBet = false
+ local eventHandler = AddEventHandler("BLACKJACK:BetReceived", function(_canBet)
+ betCheckRecieved = true
+ canBet = _canBet
+ end)
+ repeat Wait(0) until betCheckRecieved == true
+ RemoveEventHandler(eventHandler)
+ if canBet then
+ hideUi()
+ if selectedBet < 27 then
+ if leavingBlackjack == true then leaveBlackjack() return end
+ local ped = PlayerPedId()
+ local anim = "place_bet_small"
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@blackjack@player", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:SetPlayerBet", g_seat, closestChair, bet, selectedBet, false)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ local idleVar = "idle_var_0"..math.random(1,5)
+ DebugPrint("IDLING POsh-BUSY: "..idleVar)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ else
+ if leavingBlackjack == true then leaveBlackjack() return end
+ local ped = PlayerPedId()
+ local anim = "place_bet_large"
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@blackjack@player", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:SetPlayerBet", g_seat, closestChair, bet, selectedBet, false)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ local idleVar = "idle_var_0"..math.random(1,5)
+ DebugPrint("IDLING POsh-BUSY: "..idleVar)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ end
+ return
+ else
+ QBCore.Functions.Notify('You dont have any casino chips...', 'error', 3500)
+ end
+ end
+ end
+ end)
+ end)
+end)
+
+RegisterNetEvent("doj:client:blackjackMenu", function(args)
+ local ped = PlayerPedId()
+ local args = tonumber(args)
+ hideUi()
+ if args == 1 then
+ -- print('casino hit')
+ if leavingBlackjack == true then DebugPrint("returning") return end
+ TriggerServerEvent("BLACKJACK:ReceivedMove", "hit")
+ local anim = requestCardAnims[math.random(1,#requestCardAnims)]
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@blackjack@player", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*990))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ local idleVar = "idle_var_0"..math.random(1,5)
+ DebugPrint("IDLING POsh-BUSY: "..idleVar)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ return
+ elseif args == 2 then
+ -- print('casino stand')
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:ReceivedMove", "stand")
+ local anim = declineCardAnims[math.random(1,#declineCardAnims)]
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@blackjack@player", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*990))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ local idleVar = "idle_var_0"..math.random(1,5)
+ DebugPrint("IDLING POsh-BUSY: "..idleVar)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ return
+ elseif args == 3 then
+ -- print('casino double')
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:CheckPlayerBet", g_seat, bet)
+ local betCheckRecieved = false
+ local canBet = false
+ local eventHandler = AddEventHandler("BLACKJACK:BetReceived", function(_canBet)
+ betCheckRecieved = true
+ canBet = _canBet
+ end)
+ repeat Wait(0) until betCheckRecieved == true
+ RemoveEventHandler(eventHandler)
+ if canBet then
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:ReceivedMove", "double")
+ local anim = "place_bet_double_down"
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@blackjack@player", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:SetPlayerBet", g_seat, closestChair, bet, selectedBet, true)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ local idleVar = "idle_var_0"..math.random(1,5)
+ DebugPrint("IDLING POsh-BUSY: "..idleVar)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ return
+ else
+ QBCore.Functions.Notify("You don't have enough casino chips to double down.", "error")
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino BlackjackDealer: "..dealerValue[g_seat].."Hand: "..handValue(hand))
+ TriggerEvent("casino:context:hit&stand")
+ end
+ else
+ -- print('casino split')
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:CheckPlayerBet", g_seat, bet)
+ local betCheckRecieved = false
+ local canBet = false
+ local eventHandler = AddEventHandler("BLACKJACK:BetReceived", function(_canBet)
+ betCheckRecieved = true
+ canBet = _canBet
+ end)
+ repeat Wait(0) until betCheckRecieved == true
+ RemoveEventHandler(eventHandler)
+ if canBet then
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:ReceivedMove", "split")
+ local anim = "place_bet_small_split"
+ if selectedBet > 27 then
+ anim = "place_bet_large_split"
+ end
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@blackjack@player", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ TriggerServerEvent("BLACKJACK:SetPlayerBet", g_seat, closestChair, bet, selectedBet, false, true)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@blackjack@player", anim)*500))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ local idleVar = "idle_var_0"..math.random(1,5)
+ DebugPrint("IDLING POsh-BUSY: "..idleVar)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ return
+ else
+ QBCore.Functions.Notify("You don't have enough casino chips to split.", "error")
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino BlackjackDealer: "..dealerValue[g_seat].."Hand: "..handValue(hand))
+ TriggerEvent("casino:context:hit&stand")
+ end
+ end
+end)
+
+RegisterNetEvent("BLACKJACK:RequestMove", function()
+ exports["qb-core"]:DrawText("Bets closing in 30 seconds...", "top")
+ if leavingBlackjack == true then
+ leaveBlackjack()
+ return
+ elseif #hand < 3 and #splitHand == 0 then
+ TriggerEvent("casino:context:hit&doubledown")
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino BlackjackDealer: "..dealerValue[g_seat].."Hand: "..handValue(hand))
+ elseif CanSplitHand(hand) == true then
+ TriggerEvent("casino:context:hit&split")
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino BlackjackDealer: "..dealerValue[g_seat].."Hand: "..handValue(hand).."[Split Hand: "..handValue(splitHand).."]")
+ elseif leavingBlackjack == false then
+ TriggerEvent("casino:context:hit&stand")
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino BlackjackDealer: "..dealerValue[g_seat].."Hand: "..handValue(hand))
+ end
+end)
+
+RegisterNetEvent("BLACKJACK:GameEndReaction", function(result)
+ CreateThread(function()
+ if #hand == 2 and handValue(hand) == 21 and result == "good" then
+ QBCore.Functions.Notify("You have BLACKJACK!", "success")
+ PlaySoundFrontend(-1, "TENNIS_MATCH_POINT", "HUD_AWARDS", 1)
+ elseif handValue(hand) > 21 and result ~= "good" then
+ QBCore.Functions.Notify("You BUST", "error", 3500)
+ PlaySoundFrontend(-1, "ERROR", "HUD_AMMO_SHOP_SOUNDSET", 1)
+ else
+ PlaySoundFrontend(-1, "CHALLENGE_UNLOCKED", "HUD_AWARDS", 1)
+ QBCore.Functions.Notify("You "..resultNames[result].." with the hand: "..handValue(hand))
+ end
+
+ hand = {}
+ splitHand = {}
+ if leavingBlackjack == true then leaveBlackjack() return end
+ local anim = "reaction_"..result.."_var_0"..math.random(1,4)
+ DebugPrint("Reacting: "..anim)
+ playerBusy = true
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, false, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, "anim_casino_b@amb@casino@games@shared@player@", anim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@shared@player@", anim)*990))
+ if leavingBlackjack == true then leaveBlackjack() return end
+ playerBusy = false
+ idleVar = "idle_var_0"..math.random(1,5)
+ local scene = NetworkCreateSynchronisedScene(g_coords, g_rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ end)
+end)
+
+RegisterNetEvent("BLACKJACK:RetrieveCards", function(i, seat)
+ DebugPrint("TABLE "..i..": DELETE SEAT ".. seat .." CARDS")
+ if seat == 0 then
+ for x,v in pairs(dealerHandObjs[i]) do
+ DeleteEntity(v)
+ dealerHandObjs[i][x] = nil
+ end
+ else
+ for x,v in pairs(handObjs[i][seat]) do
+ DeleteEntity(v)
+ end
+ for x,v in pairs(chips[i][5-seat]) do
+ DeleteEntity(v)
+ end
+ end
+end)
+
+RegisterNetEvent("BLACKJACK:UpdateDealerHand", function(i, v)
+ dealerValue[i] = v
+end)
+
+RegisterNetEvent("BLACKJACK:RetrieveCardsWithAnim", function(i, seat)
+ DebugPrint("TABLE "..i..": DELETE SEAT ".. seat .." CARDS")
+ if seat == 0 then
+ for x,v in pairs(dealerHandObjs[i]) do
+ AttachEntityToEntity(v, spawnedPeds[i], GetPedBoneIndex(spawnedPeds[i],28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ end
+ while not HasAnimEventFired(spawnedPeds[i],585557868) do
+ Wait(0)
+ end
+ for x,v in pairs(dealerHandObjs[i]) do
+ DeleteEntity(v)
+ dealerHandObjs[i][x] = nil
+ end
+ else
+ for x,v in pairs(handObjs[i][seat]) do
+ AttachEntityToEntity(v, spawnedPeds[i], GetPedBoneIndex(spawnedPeds[i],28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ end
+ while not HasAnimEventFired(spawnedPeds[i],585557868) do
+ Wait(0)
+ end
+ for x,v in pairs(handObjs[i][seat]) do
+ DeleteEntity(v)
+ end
+ for x,v in pairs(chips[i][5-seat]) do
+ DeleteEntity(v)
+ end
+ end
+end)
+
+RegisterNetEvent("BLACKJACK:GiveCard", function(i, seat, handSize, card, flipped, split)
+ flipped = flipped or false
+ split = split or false
+ if i == g_seat and seat == closestChair then
+ if split == true then
+ table.insert(splitHand, card)
+ else
+ table.insert(hand, card)
+ end
+ DebugPrint("GOT CARD "..card.." ("..cardValue(card)..")")
+ DebugPrint("HAND VALUE "..handValue(hand))
+ elseif seat == 0 then
+ table.insert(dealerHand[i], card)
+ end
+ local model = GetHashKey("vw_prop_cas_card_"..card)
+ RequestModel(model)
+ repeat Wait(0) until HasModelLoaded(model)
+ local card = CreateObjectNoOffset(model, tables[i].coords.x, tables[i].coords.y, tables[i].coords.z, false, false, false)
+ table.insert(spawnedObjects, card)
+ if seat > 0 then
+ table.insert(handObjs[i][seat], card)
+ end
+ AttachEntityToEntity(card, spawnedPeds[i], GetPedBoneIndex(spawnedPeds[i], 28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ Wait(1300)
+ DetachEntity(card, 0, true)
+ if seat == 0 then
+ table.insert(dealerHandObjs[i], card)
+ SetEntityCoordsNoOffset(card, GetObjectOffsetFromCoords(tables[i].coords.x, tables[i].coords.y, tables[i].coords.z, tables[i].coords.w, cardOffsetsDealer[handSize]))
+ if flipped == true then
+ SetEntityRotation(card, 180.0, 0.0, tables[i].coords.w + cardRotationOffsetsDealer[handSize].z)
+ else
+ SetEntityRotation(card, 0.0, 0.0, tables[i].coords.w + cardRotationOffsetsDealer[handSize].z)
+ end
+ else
+ if split == true then
+ SetEntityCoordsNoOffset(card, GetObjectOffsetFromCoords(tables[i].coords.x, tables[i].coords.y, tables[i].coords.z, tables[i].coords.w, cardSplitOffsets[5-seat][handSize]))
+ SetEntityRotation(card, 0.0, 0.0, tables[i].coords.w + cardSplitRotationOffsets[5-seat][handSize])
+ else
+ SetEntityCoordsNoOffset(card, GetObjectOffsetFromCoords(tables[i].coords.x, tables[i].coords.y, tables[i].coords.z, tables[i].coords.w, cardOffsets[5-seat][handSize]))
+ SetEntityRotation(card, 0.0, 0.0, tables[i].coords.w + cardRotationOffsets[5-seat][handSize])
+ textCoords = GetObjectOffsetFromCoords(tables[i].coords.x, tables[i].coords.y, tables[i].coords.z, tables[i].coords.w, cardOffsets[5-seat][handSize])
+ end
+ end
+end)
+
+function ProcessTables()
+ RequestAnimDict("anim_casino_b@amb@casino@games@shared@player@")
+ local alreadyEnteredZone = false
+ while true do
+ local sleep = 5
+ local inZone = false
+ if not IsEntityDead(PlayerPedId()) then
+ for i,v in pairs(tables) do
+ local cord = v.coords
+ local highStakes = v.highStakes
+ if #(GetEntityCoords(PlayerPedId()) - vector3(cord.x, cord.y, cord.z)) < 3.0 then
+ local pCoords = GetEntityCoords(PlayerPedId())
+
+ -- local tableObj = GetClosestObjectOfType(pCoords, 1.0, `vw_prop_casino_3cardpoker_01`, false, false, false)
+ -- if GetEntityCoords(tableObj) == vector3(0.0, 0.0, 0.0) then
+ -- tableObj = GetClosestObjectOfType(pCoords, 1.0, `vw_prop_casino_3cardpoker_01`, false, false, false)
+ -- end
+
+ local tableObj = 0
+ local TableModels = {
+ `vw_prop_casino_3cardpoker_01`,
+ `vw_prop_casino_3cardpoker_01b`,
+ `vw_prop_casino_blckjack_01`,
+ `vw_prop_casino_blckjack_01b`
+ }
+ for i = 1 , #TableModels do
+ local model = TableModels[i]
+ tableObj = GetClosestObjectOfType(pCoords, 1.0, model, false, false, false)
+ if GetEntityCoords(tableObj) ~= vector3(0.0, 0.0, 0.0) then
+ break
+ end
+ end
+
+ if GetEntityCoords(tableObj) ~= vector3(0.0, 0.0, 0.0) then
+ closestChair = 1
+ local coords = GetWorldPositionOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, "Chair_Base_0"..closestChair))
+ local rot = GetWorldRotationOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, "Chair_Base_0"..closestChair))
+ dist = #(pCoords - coords)
+ for i=1,4 do
+ local coords = GetWorldPositionOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, "Chair_Base_0"..i))
+ if #(pCoords - coords) < dist then
+ dist = dist
+ closestChair = i
+ end
+ end
+ local coords = GetWorldPositionOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, "Chair_Base_0"..closestChair))
+ local rot = GetWorldRotationOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, "Chair_Base_0"..closestChair))
+ g_coords = coords
+ g_rot = rot
+ local angle = rot.z-findRotation(coords.x, coords.y, pCoords.x, pCoords.y)+90.0
+ local seatAnim = "sit_enter_"
+ if angle > 0 then seatAnim = "sit_enter_left" end
+ if angle < 0 then seatAnim = "sit_enter_right" end
+ if angle > seatSideAngle or angle < -seatSideAngle then seatAnim = seatAnim .. "_side" end
+ local canSit = true
+ if canSitDownCallback ~= nil then
+ canSit = canSitDownCallback()
+ end
+
+
+ if #(pCoords - coords) < 1.7 and not IsSeatOccupied(coords, 0.5) and canSit then
+ wait = 5
+ inZone = true
+
+ if highStakes then
+ text = "The Diamond Casino & ResortBlackjack KGV(High-Limit)Press E to sit"
+ else
+ text = "The Diamond Casino & ResortBlackjack KGVPress E to sit"
+ end
+
+
+ if IsControlJustPressed(1, 51) then
+ -- QBCore.Functions.TriggerCallback('QBCore.Functions.HasItem', function(HasItem)
+ -- if HasItem then
+ if satDownCallback ~= nil then
+ satDownCallback()
+ end
+ local ped = PlayerPedId()
+ local initPos = GetAnimInitialOffsetPosition("anim_casino_b@amb@casino@games@shared@player@", seatAnim, coords, rot, 0.01, 2)
+ local initRot = GetAnimInitialOffsetRotation("anim_casino_b@amb@casino@games@shared@player@", seatAnim, coords, rot, 0.01, 2)
+ TaskGoStraightToCoord(ped, initPos, 1.0, 5000, initRot.z, 0.01)
+ repeat Wait(0) until GetScriptTaskStatus(ped, 2106541073) == 7
+ Wait(50)
+ SetPedCurrentWeaponVisible(ped, 0, true, 0, 0)
+ local scene = NetworkCreateSynchronisedScene(coords, rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", seatAnim, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ local scene = NetworkConvertSynchronisedSceneToSynchronizedScene(scene)
+ repeat Wait(0) until GetSynchronizedScenePhase(scene) >= 0.99 or HasAnimEventFired(ped, 2038294702) or HasAnimEventFired(ped, -1424880317)
+ Wait(1000)
+ idleVar = "idle_cardgames"
+ scene = NetworkCreateSynchronisedScene(coords, rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(ped, scene, "anim_casino_b@amb@casino@games@shared@player@", "idle_cardgames", 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ repeat Wait(0) until IsEntityPlayingAnim(ped, "anim_casino_b@amb@casino@games@shared@player@", "idle_cardgames", 3) == 1
+ g_seat = i
+ leavingBlackjack = false
+ TriggerServerEvent("BLACKJACK:PlayerSatDown", i, closestChair)
+ local endTime = GetGameTimer() + math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@shared@player@", idleVar)*990)
+
+ CreateThread(function()
+ local startCount = false
+ local count = 0
+ while true do
+ Wait(0)
+ SetPauseMenuActive(false)
+ if leavingBlackjack == true then
+ startCount = true
+ end
+ if startCount == true then
+ count = count + 1
+ end
+ if count > 100 then
+ break
+ end
+ end
+ end)
+
+ while true do
+ Wait(0)
+ if GetGameTimer() >= endTime then
+ if playerBusy == true then
+ while playerBusy == true do
+ Wait(0)
+ local playerPed = PlayerPedId()
+ if IsEntityDead(playerPed) then
+ TriggerServerEvent("BLACKJACK:PlayerRemove", i)
+ ClearPedTasks(playerPed)
+ leaveBlackjack()
+ break
+ elseif leaveCheckCallback ~= nil then
+ if leaveCheckCallback() then
+ TriggerServerEvent("BLACKJACK:PlayerRemove", i)
+ ClearPedTasks(playerPed)
+ leaveBlackjack()
+ break
+ end
+ end
+ end
+ end
+ if leavingBlackjack == false then
+ idleVar = "idle_var_0"..math.random(1,5)
+ local scene = NetworkCreateSynchronisedScene(coords, rot, 2, true, true, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, "anim_casino_b@amb@casino@games@shared@player@", idleVar, 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ endTime = GetGameTimer() + math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@shared@player@", idleVar)*990)
+ end
+ end
+ if leavingBlackjack == true then
+ if standUpCallback ~= nil then
+ standUpCallback()
+ end
+ local scene = NetworkCreateSynchronisedScene(coords, rot, 2, false, false, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, "anim_casino_b@amb@casino@games@shared@player@", "sit_exit_left", 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(scene)
+ TriggerServerEvent("BLACKJACK:PlayerSatUp", i)
+ Wait(math.floor(GetAnimDuration("anim_casino_b@amb@casino@games@shared@player@", "sit_exit_left")*800))
+ ClearPedTasks(PlayerPedId())
+ break
+ else
+ local playerPed = PlayerPedId()
+ if IsEntityDead(playerPed) then
+ TriggerServerEvent("BLACKJACK:PlayerRemove", i)
+ ClearPedTasks(playerPed)
+ leaveBlackjack()
+ if standUpCallback ~= nil then
+ standUpCallback()
+ end
+ break
+ elseif leaveCheckCallback ~= nil then
+ if leaveCheckCallback() then
+ TriggerServerEvent("BLACKJACK:PlayerRemove", i)
+ ClearPedTasks(playerPed)
+ leaveBlackjack()
+ if standUpCallback ~= nil then
+ standUpCallback()
+ end
+ break
+ end
+ end
+ end
+ end
+ -- else
+ -- QBCore.Functions.Notify('You are not a member of the casino', 'error', 3500)
+ -- end
+ -- end, 'casino_member')
+ end
+ end
+ end
+ if inZone and not alreadyEnteredZone then
+ alreadyEnteredZone = true
+ exports["qb-core"]:DrawText(text, "top")
+ end
+ if not inZone and alreadyEnteredZone then
+ alreadyEnteredZone = false
+ hideUi()
+ end
+ end
+ end
+ end
+ Wait(sleep)
+ end
+end
+
+
+
+CreateThread(function()
+ if IsModelInCdimage(`vw_prop_casino_3cardpoker_01`) and IsModelInCdimage(`s_f_y_casino_01`) then
+ CreateThread(ProcessTables)
+ CreateThread(CreatePeds)
+ else
+ ThefeedSetAnimpostfxColor(255, 0, 0, 255)
+ print("ERROR: This server is missing objects required for casino-blackjack!")
+ end
+end)
+
+exports("SetSatDownCallback", SetSatDownCallback)
+exports("SetStandUpCallback", SetStandUpCallback)
+exports("SetLeaveCheckCallback", SetLeaveCheckCallback)
+exports("SetCanSitDownCallback", SetCanSitDownCallback)
+
+
+exports["casino-blackjackKGV"]:SetSatDownCallback(function()
+ exports["qb-core"]:HideText()
+end)
+
+exports["casino-blackjackKGV"]:SetStandUpCallback(function()
+ hideUi()
+end)
+
+-- exports["casino-blackjack"]:SetLeaveCheckCallback(function()
+-- if isDead or isHandcuffed or isEscorted then
+-- return true
+-- else
+-- return false
+-- end
+-- end)
+
+-- exports["casino-blackjack"]:SetCanSitDownCallback(function()
+-- if not isDead and not isHandcuffed and not isEscorted then
+-- return true
+-- else
+-- return false
+-- end
+-- end)
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackKGV/client/context-menu.lua b/resources/[qb]/[qb_casino]/casino-blackjackKGV/client/context-menu.lua
new file mode 100644
index 0000000..a138a3f
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackKGV/client/context-menu.lua
@@ -0,0 +1,90 @@
+RegisterNetEvent('casino:context:hit&stand', function()
+ exports['qb-menu']:openMenu({
+ {
+ header = "Diamond Casino Blackjack",
+ isMenuHeader = true,
+ },
+ {
+ header = "Hit",
+ txt = "Draw another card",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 1
+ }
+ },
+ {
+ header = "Stand",
+ txt = "Be a pussy",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 2
+ }
+ },
+ })
+end)
+
+RegisterNetEvent('casino:context:hit&doubledown', function()
+ exports['qb-menu']:openMenu({
+ {
+ header = "Diamond Casino Blackjack",
+ isMenuHeader = true,
+ },
+ {
+ header = "Hit",
+ txt = "Draw another card",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 1
+ }
+ },
+ {
+ header = "Stand",
+ txt = "Be a pussy",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 2
+ }
+ },
+ {
+ header = "Double Down",
+ txt = "Double your initial bet",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 3
+ }
+ },
+ })
+end)
+
+RegisterNetEvent('casino:context:hit&split', function()
+ exports['qb-menu']:openMenu({
+ {
+ header = "Diamond Casino Blackjack",
+ isMenuHeader = true,
+ },
+ {
+ header = "Hit",
+ txt = "Draw another card",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 1
+ }
+ },
+ {
+ header = "Stand",
+ txt = "Be a pussy",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 2
+ }
+ },
+ {
+ header = "Split",
+ txt = "Split",
+ params = {
+ event = "doj:client:blackjackMenu",
+ args = 4
+ }
+ },
+ })
+end)
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackKGV/coords.lua b/resources/[qb]/[qb_casino]/casino-blackjackKGV/coords.lua
new file mode 100644
index 0000000..0b4e967
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackKGV/coords.lua
@@ -0,0 +1,880 @@
+
+_DEBUG = false
+
+function DebugPrint(str)
+ if _DEBUG == true and str then
+ return print("BLACKJACK: "..tostring(str))
+ end
+end
+
+ChackCardPropAnim = true
+
+tables = { -- Spawns Ped Only -- Setup Currently For This https://forum.cfx.re/t/cayo-perico-casino-dlc-ipl-loader/2099391
+ -- {
+ -- coords = vector4(996.17, 51.69, 68.45, 318.91), --Table 1 -- poker
+ -- highStakes = false
+ -- },
+ -- {
+ -- coords = vector4(1000.66, 50.88, 68.45, 6.73), --Table 2 -- poker
+ -- highStakes = false
+ -- },
+ {
+ coords = vector4(1004.09, 53.11, 68.45, 55.30), --Table 3
+ highStakes = false
+ },
+ {
+ coords = vector4(1002.36, 60.52, 68.45, 142.53), --Table 4
+ highStakes = false
+ },
+ -- {
+ -- coords = vector4(998.44, 60.99, 68.45, 191.77), --Table 5 -- poker
+ -- highStakes = false
+ -- },
+ -- {
+ -- coords = vector4(994.89, 58.29, 68.45, 237.13), --Table 6 -- poker
+ -- highStakes = false
+ -- },
+ -- {
+ -- coords = vector4(985.95, 60.56, 69.25, 187.91), --Table 7 --USED BY Rubbertoe98 Blackjack
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(982.50, 62.85, 69.25, 101.44), --Table 8 -USED BY Rubbertoe98 Blackjack
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(984.97, 66.64, 69.25, 3.39), --Table 9 -- poker
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(988.45, 64.38, 69.25, 278.52), --Table 10 -- poker
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(989.05, 45.69, 69.25, 22.31), --Table 11 -USED BY Rubbertoe98 Blackjack
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(987.30, 42.19, 69.25, 102.30), --Table 12 -USED BY Rubbertoe98 Blackjack
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(991.56, 40.10, 69.25, 200.84), --Table 13 -- poker
+ -- highStakes = true
+ -- },
+ -- {
+ -- coords = vector4(993.20, 43.70, 69.25, 279.25), --Table 14 -- poker
+ -- highStakes = true
+ -- },
+}
+
+--[[
+ Table colors
+ 0: Green
+ 1: Red
+ 2: Blue
+ 3: Purple
+--]]
+
+customTables = { -- Spawns ped with table, example below
+{
+ coords = vector4(967.33, 32.0191, 115.1742, -122.0),
+ highStakes = false,
+ color = 1,
+},
+ -- {
+ -- coords = vector4(996.77, 52.43, 68.43, 318.91),
+ -- highStakes = false,
+ -- color = 0
+ -- },
+}
+
+for i,v in pairs(customTables) do
+ table.insert(tables, v)
+end
+
+resultNames = {
+ ["good"] = "WON",
+ ["bad"] = "BUST",
+ ["impartial"] = "Got a PUSH",
+}
+
+requestCardAnims = {
+ "request_card",
+ "request_card_alt1",
+ "request_card_alt2",
+}
+declineCardAnims = {
+ "decline_card_001",
+ "decline_card_alt1",
+ "decline_card_alt2",
+}
+
+cardOffsets = {
+ [1] = {
+ vector3(0.5737, 0.2376, 0.948025),
+ vector3(0.562975, 0.2523, 0.94875),
+ vector3(0.553875, 0.266325, 0.94955),
+ vector3(0.5459, 0.282075, 0.9501),
+ vector3(0.536125, 0.29645, 0.95085),
+ vector3(0.524975, 0.30975, 0.9516),
+ vector3(0.515775, 0.325325, 0.95235),
+ },
+
+ [2] = {
+ vector3(0.2325, -0.1082, 0.94805),
+ vector3(0.23645, -0.0918, 0.949),
+ vector3(0.2401, -0.074475, 0.950225),
+ vector3(0.244625, -0.057675, 0.951125),
+ vector3(0.249675, -0.041475, 0.95205),
+ vector3(0.257575, -0.0256, 0.9532),
+ vector3(0.2601, -0.008175, 0.954375),
+ },
+
+ [3] = {
+ vector3(-0.2359, -0.1091, 0.9483),
+ vector3(-0.221025, -0.100675, 0.949),
+ vector3(-0.20625, -0.092875, 0.949725),
+ vector3(-0.193225, -0.07985, 0.950325),
+ vector3(-0.1776, -0.072, 0.951025),
+ vector3(-0.165, -0.060025, 0.951825),
+ vector3(-0.14895, -0.05155, 0.95255),
+ },
+
+ [4] = {
+ vector3(-0.5765, 0.2229, 0.9482),
+ vector3(-0.558925, 0.2197, 0.949175),
+ vector3(-0.5425, 0.213025, 0.9499),
+ vector3(-0.525925, 0.21105, 0.95095),
+ vector3(-0.509475, 0.20535, 0.9519),
+ vector3(-0.491775, 0.204075, 0.952825),
+ vector3(-0.4752, 0.197525, 0.9543),
+ }
+}
+
+cardRotationOffsets = {
+ [1] = {
+ 69.12,
+ 67.8,
+ 66.6,
+ 70.44,
+ 70.84,
+ 67.88,
+ 69.56,
+ },
+
+ [2] = {
+ 22.11,
+ 22.32,
+ 20.8,
+ 19.8,
+ 19.44,
+ 26.28,
+ 22.68,
+ },
+
+ [3] = {
+ -21.43,
+ -20.16,
+ -16.92,
+ -23.4,
+ -21.24,
+ -23.76,
+ -19.44,
+ },
+
+ [4] = {
+ -67.03,
+ -69.12,
+ -64.44,
+ -67.68,
+ -63.72,
+ -68.4,
+ -64.44,
+ },
+}
+
+cardSplitOffsets = {
+
+ [1] = {
+ vector3(0.6083, 0.3523, 0.94795),
+ vector3(0.598475, 0.366475, 0.948925),
+ vector3(0.589525, 0.3807, 0.94975),
+ vector3(0.58045, 0.39435, 0.950375),
+ vector3(0.571975, 0.4092, 0.951075),
+ vector3(0.5614, 0.4237, 0.951775),
+ vector3(0.554325, 0.4402, 0.952525),
+ },
+
+ [2] = {
+ vector3(0.3431, -0.0527, 0.94855),
+ vector3(0.348575, -0.0348, 0.949425),
+ vector3(0.35465, -0.018825, 0.9502),
+ vector3(0.3581, -0.001625, 0.95115),
+ vector3(0.36515, 0.015275, 0.952075),
+ vector3(0.368525, 0.032475, 0.95335),
+ vector3(0.373275, 0.0506, 0.9543),
+ },
+
+ [3] = {
+ vector3(-0.116, -0.1501, 0.947875),
+ vector3(-0.102725, -0.13795, 0.948525),
+ vector3(-0.08975, -0.12665, 0.949175),
+ vector3(-0.075025, -0.1159, 0.949875),
+ vector3(-0.0614, -0.104775, 0.9507),
+ vector3(-0.046275, -0.095025, 0.9516),
+ vector3(-0.031425, -0.0846, 0.952675),
+ },
+
+ [4] = {
+ vector3(-0.5205, 0.1122, 0.9478),
+ vector3(-0.503175, 0.108525, 0.94865),
+ vector3(-0.485125, 0.10475, 0.949175),
+ vector3(-0.468275, 0.099175, 0.94995),
+ vector3(-0.45155, 0.09435, 0.95085),
+ vector3(-0.434475, 0.089725, 0.95145),
+ vector3(-0.415875, 0.0846, 0.9523),
+ }
+}
+
+cardSplitRotationOffsets = {
+ [1] = {
+ 68.57,
+ 67.52,
+ 67.76,
+ 67.04,
+ 68.84,
+ 65.96,
+ 67.76,
+ },
+
+ [2] = {
+ 22.11,
+ 22.0,
+ 24.44,
+ 21.08,
+ 25.96,
+ 26.16,
+ 28.76,
+ },
+
+ [3] = {
+ -14.04,
+ -15.48,
+ -16.56,
+ -15.84,
+ -16.92,
+ -14.4,
+ -14.28,
+ },
+
+ [4] = {
+ -67.03,
+ -67.6,
+ -69.4,
+ -69.04,
+ -68.68,
+ -66.16,
+ -63.28,
+ },
+}
+
+cardOffsetsDealer = {
+ vector3(0.0436, 0.21205, 0.948875),
+ vector3(-0.0636, 0.213825, 0.9496),
+ vector3(-0.0806, 0.2137, 0.950225),
+ vector3(-0.1006, 0.21125, 0.950875),
+ vector3(-0.1256, 0.21505, 0.951875),
+ vector3(-0.1416, 0.21305, 0.953),
+ vector3(-0.1656, 0.21205, 0.954025),
+ vector3(-0.1836, 0.21255, 0.95495),
+ vector3(-0.2076, 0.21105, 0.956025),
+ vector3(-0.2246, 0.21305, 0.957),
+}
+
+cardRotationOffsetsDealer = { -- doesnt have to be vector3
+ vector3(0.0, 0.0, 178.92),
+ vector3(0.0, 0.0, -180.0),
+ vector3(0.0, 0.0, -178.92),
+ vector3(0.0, 0.0, -177.12),
+ vector3(0.0, 0.0, 180.0),
+ vector3(0.0, 0.0, 178.56),
+ vector3(0.0, 0.0, 180.0),
+ vector3(0.0, 0.0, 178.2),
+ vector3(0.0, 0.0, -177.12),
+ vector3(0.0, 0.0, 180.0),
+ vector3(0.0, 0.0, 178.56),
+}
+
+chipSplitOffsets = {
+ [1] = {
+ vector3(0.6931, 0.1952, 0.0),
+ vector3(0.724925, 0.26955, 0.0),
+ vector3(0.7374, 0.349625, 0.0),
+ vector3(0.76415, 0.419225, 0.0),
+ },
+
+ [2] = {
+ vector3(0.2827, -0.227825, 0.0),
+ vector3(0.3605, -0.1898, 0.0),
+ vector3(0.4309, -0.16365, 0.0),
+ vector3(0.49275, -0.111575, 0.0),
+ },
+
+ [3] = {
+ vector3(-0.279425, -0.2238, 0.0),
+ vector3(-0.200775, -0.25855, 0.0),
+ vector3(-0.125775, -0.26815, 0.0),
+ vector3(-0.05615, -0.29435, 0.0),
+ },
+
+ [4] = {
+ vector3(-0.685925, 0.173275, 0.0),
+ vector3(-0.6568, 0.092525, 0.0),
+ vector3(-0.612875, 0.033025, 0.0),
+ vector3(-0.58465, -0.0374, 0.0),
+ }
+}
+
+
+chipSplitRotationOffsets = { -- doesnt have to be vector3
+ [1] = {
+ vector3(0, 0, -16.56),
+ vector3(0, 0, -22.32),
+ vector3(0, 0, -10.8),
+ vector3(0, 0, -9.72),
+ },
+
+ [2] = {
+ vector3(0, 0, -69.12),
+ vector3(0, 0, -64.8),
+ vector3(0, 0, -58.68),
+ vector3(0, 0, -51.12),
+ },
+
+ [3] = {
+ vector3(0, 0, -112.32),
+ vector3(0, 0, -108.36),
+ vector3(0, 0, -99.72),
+ vector3(0, 0, -102.6),
+ },
+
+ [4] = {
+ vector3(0, 0, -155.88),
+ vector3(0, 0, -151.92),
+ vector3(0, 0, -147.24),
+ vector3(0, 0, -146.52),
+ }
+}
+
+chipOffsets = {
+ [1] = {
+ vector3(0.712625, 0.170625, 0.0),
+ vector3(0.6658, 0.218375, 0.0),
+ vector3(0.756775, 0.292775, 0.0),
+ vector3(0.701875, 0.3439, 0.0),
+ },
+
+ [2] = {
+ vector3(0.278125, -0.2571, 0.0),
+ vector3(0.280375, -0.190375, 0.0),
+ vector3(0.397775, -0.208525, 0.0),
+ vector3(0.39715, -0.1354, 0.0),
+ },
+
+ [3] = {
+ vector3(-0.30305, -0.2464, 0.0),
+ vector3(-0.257975, -0.19715, 0.0),
+ vector3(-0.186575, -0.2861, 0.0),
+ vector3(-0.141675, -0.237925, 0.0),
+ },
+
+ [4] = {
+ vector3(-0.72855, 0.17345, 0.0),
+ vector3(-0.652825, 0.177525, 0.0),
+ vector3(-0.6783, 0.0744, 0.0),
+ vector3(-0.604425, 0.082575, 0.0),
+ }
+}
+
+pileOffsets = {
+ [1] = {
+ vector3(0.61, -0.02, 0.0),
+ vector3(0.73, 0.47, 0.0),
+ vector3(0.756775, 0.292775, 0.0),
+ vector3(0.701875, 0.3439, 0.0),
+ },
+
+ [2] = {
+ vector3(0.03, -0.29, 0.0),
+ vector3(0.05, -0.06, 0.0),
+ vector3(0.397775, -0.208525, 0.0),
+ vector3(0.39715, -0.1354, 0.0),
+ },
+
+ [3] = {
+ vector3(-0.48, -0.13, 0.0),
+ vector3(-0.35, 0.07, 0.0),
+ vector3(-0.186575, -0.2861, 0.0),
+ vector3(-0.141675, -0.237925, 0.0),
+ },
+
+ [4] = {
+ vector3(-0.7, 0.32, 0.0),
+ vector3(-0.7, 0.53, 0.0),
+ vector3(-0.6783, 0.0744, 0.0),
+ vector3(-0.604425, 0.082575, 0.0),
+ }
+}
+
+chipRotationOffsets = { -- doesnt have to be vector3
+ [1] = {
+ vector3(0, 0, 72.0),
+ vector3(0, 0, 64.8),
+ vector3(0, 0, 74.52),
+ vector3(0, 0, 72.0),
+ },
+
+ [2] = {
+ vector3(0, 0, 12.96),
+ vector3(0, 0, 29.16),
+ vector3(0, 0, 32.04),
+ vector3(0, 0, 32.04),
+ },
+
+ [3] = {
+ vector3(0, 0, -18.36),
+ vector3(0, 0, -18.72),
+ vector3(0, 0, -15.48),
+ vector3(0, 0, -18.0),
+ },
+
+ [4] = {
+ vector3(0, 0, -79.2),
+ vector3(0, 0, -68.76),
+ vector3(0, 0, -57.6),
+ vector3(0, 0, -64.8),
+ }
+}
+
+pileRotationOffsets = { -- doesnt have to be vector3
+ [1] = {
+ vector3(0, 0, 8.1),
+ vector3(0, 0, 229.49),
+ vector3(0, 0, 74.52),
+ vector3(0, 0, 72.0),
+ },
+
+ [2] = {
+ vector3(0, 0, 78.7),
+ vector3(0, 0, 4.6),
+ vector3(0, 0, 32.04),
+ vector3(0, 0, 32.04),
+ },
+
+ [3] = {
+ vector3(0, 0, 44.89),
+ vector3(0, 0, 144.49),
+ vector3(0, 0, -15.48),
+ vector3(0, 0, -18.0),
+ },
+
+ [4] = {
+ vector3(0, 0, 15.6),
+ vector3(0, 0, 15.6),
+ vector3(0, 0, -57.6),
+ vector3(0, 0, -64.8),
+ }
+}
+
+lowTableLimit = 40
+bettingNums = {
+ 10,
+ 20,
+ 30,
+ 40,
+ 50,
+ 60,
+ 70,
+ 80,
+ 90,
+ 100,
+ 150,
+ 200,
+ 250,
+ 300,
+ 350,
+ 400,
+ 450,
+ 500,
+ 1000,
+ 1500,
+ 2000,
+ 2500,
+ 3000,
+ 3500,
+ 4000,
+ 4500,
+ 5000,
+ 6000,
+ 7000,
+ 8000,
+ 9000,
+ 10000,
+ 15000,
+ 20000,
+ 25000,
+ 30000,
+ 35000,
+ 40000,
+ 45000,
+ 50000, -- 40 Low table limit, betting numbers added after this will be high stakes only
+ 55000,
+ 60000,
+ 65000,
+ 70000,
+ 75000,
+ 80000,
+ 85000,
+ 90000,
+ 95000,
+ 100000,
+ 150000,
+ 200000,
+ 250000,
+ 300000,
+ 350000,
+ 400000,
+ 450000,
+ 500000,
+ 550000,
+ 600000,
+ 650000,
+ 700000,
+ 750000,
+ 800000,
+ 850000,
+ 900000,
+ 950000,
+ 1000000,
+ 1500000,
+ 2000000,
+ 2500000,
+ 3000000,
+ 3500000,
+ 4000000,
+ 4500000,
+ 5000000,
+ 5500000,
+ 6000000,
+ 6500000,
+ 7000000,
+ 7500000,
+ 8000000,
+ 8500000,
+ 9000000,
+ 9500000,
+ 10000000,
+}
+
+bettingTime = 50
+moveTime = 30
+--[[
+ case 10:
+ return joaat("vw_prop_chip_10dollar_x1");
+ case 50:
+ return joaat("vw_prop_chip_50dollar_x1");
+ case 100:
+ return joaat("vw_prop_chip_100dollar_x1");
+ case 500:
+ return joaat("vw_prop_chip_500dollar_x1");
+ case 1000:
+ return joaat("vw_prop_chip_1kdollar_x1");
+ case 5000:
+ return joaat("vw_prop_plaq_5kdollar_x1");
+ case 10000:
+ return joaat("vw_prop_plaq_10kdollar_x1");
+
+ vw_prop_chip_10kdollar_x1.ydr
+ vw_prop_chip_5kdollar_x1.ydr
+ vw_prop_chip_10kdollar_st.ydr -- $120,000
+ vw_prop_chip_5kdollar_st.ydr -- $60,000
+ vw_prop_vw_chips_pile_01a.ydr -- $511,000
+ vw_prop_vw_chips_pile_02a.ydr -- $3,250,000
+ vw_prop_vw_chips_pile_03a.ydr -- $1,990,000
+
+--]]
+
+chipModels = {
+ [10] = "vw_prop_chip_10dollar_x1",
+ [50] = "vw_prop_chip_50dollar_x1",
+ [100] = "vw_prop_chip_100dollar_x1",
+ [120] = "vw_prop_chip_10dollar_st",
+ [500] = "vw_prop_chip_500dollar_x1",
+ [600] = "vw_prop_chip_50dollar_st",
+ [1000] = "vw_prop_chip_1kdollar_x1",
+ [1200] = "vw_prop_chip_100dollar_st",
+ [5000] = "vw_prop_chip_5kdollar_x1",
+ [6000] = "vw_prop_chip_500dollar_st",
+ [10000] = "vw_prop_chip_10kdollar_x1",
+ [60000] = "vw_prop_chip_5kdollar_st",
+ [120000] = "vw_prop_chip_10kdollar_st",
+}
+
+chipValues = {
+ 10,
+ 50,
+ 100,
+ 120,
+ 500,
+ 600,
+ 1000,
+ 1200,
+ 5000,
+ 6000,
+ 10000,
+ 60000,
+ 120000,
+}
+
+chipThickness = {
+ [`vw_prop_chip_10dollar_x1`] = 0.0054170000366867,
+ [`vw_prop_chip_50dollar_x1`] = 0.0056730001233518,
+ [`vw_prop_chip_100dollar_x1`] = 0.0056900000199676,
+ [`vw_prop_chip_10dollar_st`] = 0.061421997845173,
+ [`vw_prop_chip_500dollar_x1`] = 0.0057030003517866,
+ [`vw_prop_chip_50dollar_st`] = 0.061151999980211,
+ [`vw_prop_chip_1kdollar_x1`] = 0.0056910002604127,
+ [`vw_prop_chip_100dollar_st`] = 0.060908999294043,
+ [`vw_prop_chip_500dollar_st`] = 0.060989998281002,
+
+ [`vw_prop_chip_5kdollar_x1`] = 0.005538,
+ [`vw_prop_chip_10kdollar_x1`] = 0.005562,
+ [`vw_prop_chip_5kdollar_st`] = 0.061049,
+ [`vw_prop_chip_10kdollar_st`] = 0.06095,
+ [`vw_prop_plaq_5kdollar_x1`] = 0.006891000084579,
+ [`vw_prop_plaq_10kdollar_x1`] = 0.0057889996096492,
+ [`vw_prop_plaq_5kdollar_st`] = 0.060949999839067,
+ [`vw_prop_plaq_10kdollar_st`] = 0.060749001801014,
+}
+
+chipHeights = { -- whatever the fuck this even means
+ 0.95,
+ 0.896,
+ 0.901,
+ 0.907,
+ 0.95,
+ 0.917,
+ 0.922,
+ 0.927,
+ 0.932,
+ 0.95,
+ 0.904,
+ 0.899,
+ 0.914,
+ 0.904,
+ 0.924,
+ 0.91,
+ 0.935,
+ 0.95,
+ 0.95,
+ 0.904,
+ 0.899,
+ 0.915,
+ 0.904,
+ 0.925,
+ 0.91,
+ 0.935,
+ 0.95,
+ 0.919,
+ 0.924,
+ 0.93,
+ 0.935,
+ 0.95,
+ 0.902,
+ 0.897,
+ 0.912,
+ 0.902,
+ 0.922,
+ 0.907,
+ 0.932,
+ 0.912,
+}
+
+function SetDealerOutfit(ped, outfit)
+ local outfit = (outfit % 13) or math.random(0, 13)
+
+ SetPedDefaultComponentVariation(ped)
+
+ if outfit == 0 then
+ SetPedComponentVariation(ped, 0, 3, 0, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 1, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 1 then
+ SetPedComponentVariation(ped, 0, 2, 2, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 2 then
+ SetPedComponentVariation(ped, 0, 2, 1, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 3 then
+ SetPedComponentVariation(ped, 0, 2, 0, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 1, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 4 then
+ SetPedComponentVariation(ped, 0, 4, 2, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 5 then
+ SetPedComponentVariation(ped, 0, 4, 0, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 0, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 6 then
+ SetPedComponentVariation(ped, 0, 4, 1, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 1, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ return
+ elseif outfit == 7 then
+ SetPedComponentVariation(ped, 0, 1, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 1, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 0, 0, 0)
+ SetPedComponentVariation(ped, 7, 0, 0, 0)
+ SetPedComponentVariation(ped, 8, 0, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ return
+ elseif outfit == 8 then
+ SetPedComponentVariation(ped, 0, 1, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 1, 1, 0)
+ SetPedComponentVariation(ped, 3, 1, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 0, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ return
+ elseif outfit == 9 then
+ SetPedComponentVariation(ped, 0, 2, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 0, 0)
+ SetPedComponentVariation(ped, 3, 2, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 0, 0, 0)
+ SetPedComponentVariation(ped, 7, 0, 0, 0)
+ SetPedComponentVariation(ped, 8, 2, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ return
+ elseif outfit == 10 then
+ SetPedComponentVariation(ped, 0, 2, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 1, 0)
+ SetPedComponentVariation(ped, 3, 3, 3, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ return
+ elseif outfit == 11 then
+ SetPedComponentVariation(ped, 0, 3, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 1, 0, 0)
+ SetPedComponentVariation(ped, 8, 0, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ SetPedPropIndex(ped, 1, 0, 0, false)
+ return
+ elseif outfit == 12 then
+ SetPedComponentVariation(ped, 0, 3, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 1, 0)
+ SetPedComponentVariation(ped, 3, 1, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ return
+ elseif outfit == 13 then
+ SetPedComponentVariation(ped, 0, 4, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 2, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 1, 0, 0)
+ SetPedComponentVariation(ped, 8, 2, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ SetPedPropIndex(ped, 1, 0, 0, false)
+ return
+ end
+end
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackKGV/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-blackjackKGV/fxmanifest.lua
new file mode 100644
index 0000000..67df964
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackKGV/fxmanifest.lua
@@ -0,0 +1,20 @@
+fx_version 'cerulean'
+game "gta5"
+
+name 'kgv-blackjack'
+description 'Playable Blackjack at the casino, similar to GTAOnline.'
+author 'Xinerki - https://github.com/Xinerki/'
+url 'https://github.com/Xinerki/kgv-blackjack'
+
+shared_scripts {
+ 'coords.lua',
+}
+
+client_scripts{
+ 'client/*.lua'
+}
+
+server_scripts{
+ 'server/*.lua'
+}
+
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackKGV/server/server.lua b/resources/[qb]/[qb_casino]/casino-blackjackKGV/server/server.lua
new file mode 100644
index 0000000..77ee443
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackKGV/server/server.lua
@@ -0,0 +1,965 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+-- ===========================================
+
+ranks = {'02', '03', '04', '05', '06', '07', '08', '09', '10', --[['11',]] 'JACK', 'QUEEN', 'KING', 'ACE'}
+suits = {'SPD', 'HRT', 'DIA', 'CLUB'}
+
+function shuffle(tbl)
+ for i = #tbl, 2, -1 do
+ local j = math.random(i)
+ tbl[i], tbl[j] = tbl[j], tbl[i]
+ end
+ return tbl
+end
+
+function getDeck()
+ local tDeck = {}
+ for _,rank in pairs(ranks) do
+ for _,suit in pairs(suits) do
+ table.insert(tDeck, suit .. "_" .. rank)
+ end
+ end
+ return shuffle(tDeck)
+end
+
+function takeCard(tDeck)
+ return table.remove(tDeck, math.random(1,#tDeck))
+end
+
+function cardValue(card)
+ local rank = 10
+ for i=2,11 do
+ if string.find(card, tostring(i)) then
+ rank = i
+ end
+ end
+ if string.find(card, 'ACE') then
+ rank = 11
+ end
+
+ return rank
+end
+
+function handValue(hand)
+ local tmpValue = 0
+ local numAces = 0
+
+ for i,v in pairs(hand) do
+ tmpValue = tmpValue + cardValue(v)
+ end
+
+ for i,v in pairs(hand) do
+ if string.find(v, 'ACE') then numAces = numAces + 1 end
+ end
+
+ repeat
+ if tmpValue > 21 and numAces > 0 then
+ tmpValue = tmpValue - 10
+ numAces = numAces - 1
+ else
+ break
+ end
+ until numAces == 0
+
+ return tmpValue
+end
+
+players = {}
+timeTracker = {}
+tableTracker = {}
+
+
+getChipsCallback = nil
+takeChipsCallback = nil
+giveChipsCallback = nil
+
+function FindPlayerIdx(tbl, src)
+
+ for i = 1, #tbl do
+ if tbl[i].player == src then
+ return i
+ end
+ end
+
+ return nil
+end
+
+function SetGetChipsCallback(cb)
+ getChipsCallback = cb
+end
+
+function SetTakeChipsCallback(cb)
+ takeChipsCallback = cb
+end
+
+function SetGiveChipsCallback(cb)
+ giveChipsCallback = cb
+end
+
+function GiveMoney(player, money)
+ if giveChipsCallback ~= nil then
+ giveChipsCallback(player, tonumber(money))
+ end
+end
+
+function TakeMoney(player, money)
+ if takeChipsCallback ~= nil then
+ takeChipsCallback(player, tonumber(money))
+ end
+end
+
+function HaveAllPlayersBetted(table)
+ for i,v in pairs(table) do
+ if v.bet < 1 then
+ return false
+ end
+ end
+ return true
+end
+
+function ArePlayersStillIn(table)
+ for i,v in pairs(table) do
+ if v.player_in == true then
+ return true
+ end
+ end
+ return false
+end
+
+function PlayDealerAnim(dealer, animDict, anim)
+ TriggerClientEvent("BLACKJACK:PlayDealerAnim", -1, dealer, animDict, anim)
+end
+
+function PlayDealerSpeech(dealer, speech)
+ TriggerClientEvent("BLACKJACK:PlayDealerSpeech", -1, dealer, speech)
+end
+
+function SetPlayerBet(i, seat, bet, betId, double, split)
+ split = split or false
+ double = double or false
+
+
+ local num = FindPlayerIdx(players[i], source)
+
+ if num ~= nil then
+ if double == false and split == false then
+ TakeMoney(source, bet)
+
+ players[i][num].bet = tonumber(bet)
+ end
+
+ TriggerClientEvent("BLACKJACK:PlaceBetChip", -1, i, 5-seat, bet, double, split)
+ else
+ DebugPrint("TABLE "..i..": PLAYER "..source.." ATTEMPTED BET BUT NO LONGER TRACKED?")
+ end
+end
+
+RegisterServerEvent("BLACKJACK:SetPlayerBet")
+AddEventHandler('BLACKJACK:SetPlayerBet', SetPlayerBet)
+
+function CheckPlayerBet(i, bet)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local ItemList = {
+ ["casino_redchip"] = 1,
+ }
+ local playerChips = Player.Functions.GetItemByName("casino_redchip")
+ local canBet = false
+ if Player.PlayerData.items ~= nil and next(Player.PlayerData.items) ~= nil then
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ if playerChips.amount >= bet then
+ canBet = true
+ end
+ end
+ end
+ end
+ end
+ TriggerClientEvent("BLACKJACK:BetReceived", source, canBet)
+end
+
+RegisterServerEvent("BLACKJACK:CheckPlayerBet")
+AddEventHandler("BLACKJACK:CheckPlayerBet", CheckPlayerBet)
+
+function SortPlayers(pTable)
+ local temp
+ for i=1,#pTable-1 do
+ for j=i+1,#pTable do
+ if pTable[i].seat < pTable[j].seat then
+ temp = pTable[i]
+ pTable[i] = pTable[j]
+ pTable[j] = temp
+ end
+ end
+ end
+ return pTable
+end
+
+RegisterServerEvent("BLACKJACK:ReceivedMove")
+
+function StartTableThread(i)
+ Citizen.CreateThread(function()
+ local index = i
+ -- DebugPrint(index)
+ while true do Wait(0)
+ if players[index] and #players[index] ~= 0 then
+ DebugPrint("WAITING FOR ALL PLAYERS AT TABLE "..index.." TO PLACE THEIR BETS.")
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_place_bet_request")
+ PlayDealerSpeech(index, "MINIGAME_DEALER_PLACE_CHIPS")
+
+ repeat
+ for i,v in pairs(players[index]) do
+ TriggerClientEvent("BLACKJACK:SyncTimer", v.player, bettingTime - timeTracker[index])
+ end -- Remove players from round who didn't bet in time
+ Wait(1000)
+ timeTracker[index] = timeTracker[index] + 1
+ until HaveAllPlayersBetted(players[index]) or #players[index] == 0 or timeTracker[index] >= bettingTime
+
+ if #players[index] == 0 then
+ DebugPrint("BETTING ENDED AT TABLE "..index..", NO MORE PLAYERS")
+ -- break
+ else
+ for i,v in pairs(players[index]) do
+ if v.bet < 1 then
+ v.player_in = false
+ end
+ end -- Remove players from round who didn't bet in time
+
+ if ArePlayersStillIn(players[index]) then -- did everyone just not bet?
+ DebugPrint("BETS PLACED AT TABLE "..index..", STARTING GAME")
+
+ PlayDealerSpeech(index, "MINIGAME_DEALER_CLOSED_BETS")
+
+
+ local currentPlayers = {table.unpack(players[i])}
+ local deck = getDeck()
+ local dealerHand = {}
+ local dealerVisibleHand = {}
+ TriggerClientEvent("BLACKJACK:UpdateDealerHand", -1, index, handValue(dealerVisibleHand))
+
+ currentPlayers = SortPlayers(currentPlayers)
+
+ local gameRunning = true
+
+ Wait(1500)
+
+ for x=1,2 do
+ local card = takeCard(deck)
+ table.insert(dealerHand, card)
+
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, 0, #dealerHand, card, #dealerHand == 1)
+
+ if #dealerHand == 1 then
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_deal_card_self")
+ DebugPrint("TABLE "..index..": DEALT DEALER [HIDDEN]")
+ else
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_deal_card_self_second_card")
+ DebugPrint("TABLE "..index..": DEALT DEALER "..card)
+ table.insert(dealerVisibleHand, card)
+
+ end
+ Wait(2000)
+ TriggerClientEvent("BLACKJACK:UpdateDealerHand", -1, index, handValue(dealerVisibleHand))
+
+ if #dealerHand > 1 then
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..cardValue(dealerHand[2]))
+ end
+
+ for i,v in pairs(currentPlayers) do
+ if v.player_in then
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.hand+1, card)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_deal_card_player_0" .. 5-v.seat)
+ table.insert(v.hand, card)
+
+ Wait(2000)
+
+
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.hand) == 21 then
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "good")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS BLACKJACK")
+ GiveMoney(v.player, v.bet*2.5)
+ v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_BLACKJACK")
+ else
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ end
+ end
+ end
+ end
+
+ -- female_dealer_focus_player_01_idle
+
+ if handValue(dealerHand) == 21 then
+ DebugPrint("TABLE "..index..": DEALER HAS BLACKJACK")
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_check_and_turn_card")
+ dealerVisibleHand = dealerHand
+ TriggerClientEvent("BLACKJACK:DealerTurnOverCard", -1, index)
+
+ Wait(2000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_BLACKJACK")
+ TriggerClientEvent("BLACKJACK:UpdateDealerHand", -1, index, handValue(dealerVisibleHand))
+
+ for i,v in pairs(currentPlayers) do
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ end
+
+ gameRunning = false
+ elseif cardValue(dealerHand[2]) == 10 or cardValue(dealerHand[2]) == 11 then
+ DebugPrint("TABLE "..index..": DEALER HAS A 10, CHECKING..")
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_check_card")
+ if ChackCardPropAnim then
+ TriggerClientEvent("BLACKJACK:DealerCheckCard", -1, index)
+ end
+ Wait(2000)
+ end
+
+ if gameRunning == true then
+ for i,v in pairs(currentPlayers) do
+ if v.player_in then
+ if tableTracker[tostring(v.player)] == nil then
+ DebugPrint("TABLE "..index..": "..v.player.." WAS PUT OUT DUE TO LEAVING")
+ v.player_in = false
+ TriggerClientEvent("BLACKJACK:RetrieveCards", -1, index, v.seat)
+ else
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_intro")
+ Wait(1500)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_ANOTHER_CARD")
+ while v.player_in == true and #v.hand < 5 do
+ timeTracker[index] = 0
+ Wait(0)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle")
+ DebugPrint("TABLE "..index..": AWAITING MOVE FROM "..GetPlayerName(v.player):upper())
+ TriggerClientEvent("BLACKJACK:RequestMove", v.player, moveTime - timeTracker[index])
+ local receivedMove = false
+ local move = "stand"
+ local eventHandler = AddEventHandler("BLACKJACK:ReceivedMove", function(m)
+ if source ~= v.player then return end
+ move = m
+ receivedMove = true
+ end)
+
+ while receivedMove == false and tableTracker[tostring(v.player)] ~= nil and timeTracker[index] < moveTime do
+ for i,v in pairs(currentPlayers) do
+ TriggerClientEvent("BLACKJACK:SyncTimer", v.player, moveTime - timeTracker[index])
+ end
+ Wait(1000)
+ timeTracker[index] = timeTracker[index] + 1
+ end
+ --repeat Wait(0) until receivedMove == true
+ RemoveEventHandler(eventHandler)
+
+ if tableTracker[tostring(v.player)] == nil then
+ DebugPrint("TABLE "..index..": "..v.player.." WAS PUT OUT DUE TO LEAVING")
+ v.player_in = false
+ TriggerClientEvent("BLACKJACK:RetrieveCards", -1, index, v.seat)
+ else
+ if move == "hit" then
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.hand+1, card)
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_hit_card_player_0" .. 5-v.seat)
+ table.insert(v.hand, card)
+ Wait(1500)
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.hand) == 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS 21")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ break
+ elseif handValue(v.hand) > 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WENT BUST")
+ v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_PLAYER_BUST")
+ else
+ -- Wait(1000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ end
+ elseif move == "double" then
+ TakeMoney(v.player, v.bet)
+ v.bet = v.bet*2
+
+ -- TriggerClientEvent("BLACKJACK:PlaceBetChip", -1, i, 5-v.seat, betId)
+
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.hand+1, card)
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_hit_card_player_0" .. 5-v.seat)
+ table.insert(v.hand, card)
+ Wait(1500)
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.hand) == 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS 21")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ break
+ elseif handValue(v.hand) > 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WENT BUST")
+ v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_PLAYER_BUST")
+ else
+ -- Wait(2000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ end
+
+ break
+ elseif move == "split" then
+ TakeMoney(v.player, v.bet)
+ v.bet = v.bet*2
+
+ -- TriggerClientEvent("BLACKJACK:PlaceBetChip", -1, i, 5-v.seat, betId)
+
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_split_card_player_0" .. 5-v.seat)
+
+ v.splitHand = {}
+
+ local splitCard = table.remove(v.hand, 2)
+ table.insert(v.splitHand, splitCard)
+
+ Wait(500)
+
+ TriggerClientEvent("BLACKJACK:SplitHand", -1, index, v.seat, #v.splitHand, v.hand, v.splitHand)
+
+ Wait(1000)
+
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.hand+1, card, false, false)
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_hit_card_player_0" .. 5-v.seat)
+
+ -- female_dealer_focus_player_01_idle_split
+
+ table.insert(v.hand, card)
+ Wait(1500)
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.hand) == 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS 21")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_BLACKJACK")
+ break
+ elseif handValue(v.hand) > 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WENT BUST")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_PLAYER_BUST")
+ else
+ -- Wait(2000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ end
+
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.splitHand+1, card, false, true)
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_hit_second_card_player_0" .. 5-v.seat)
+
+ table.insert(v.splitHand, card)
+ Wait(1500)
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.splitHand) == 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS 21")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.splitHand))
+ break
+ elseif handValue(v.splitHand) > 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WENT BUST")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_PLAYER_BUST")
+ else
+ -- Wait(2000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.splitHand))
+ end
+
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_intro")
+ -- Wait(1500)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_ANOTHER_CARD")
+ repeat Wait(0)
+ timeTracker[index] = 0
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle")
+ DebugPrint("TABLE "..index..": AWAITING MOVE FROM "..GetPlayerName(v.player):upper())
+ TriggerClientEvent("BLACKJACK:RequestMove", v.player, moveTime - timeTracker[index])
+ local receivedMove = false
+ local move = "stand"
+ local eventHandler = AddEventHandler("BLACKJACK:ReceivedMove", function(m)
+ if source ~= v.player then return end
+ move = m
+ receivedMove = true
+ end)
+
+ while receivedMove == false and tableTracker[tostring(v.player)] ~= nil and timeTracker[index] < moveTime do
+ for i,v in pairs(currentPlayers) do
+ TriggerClientEvent("BLACKJACK:SyncTimer", v.player, moveTime - timeTracker[index])
+ end
+ Wait(1000)
+ timeTracker[index] = timeTracker[index] + 1
+ end
+
+ --repeat Wait(0) until receivedMove == true
+ RemoveEventHandler(eventHandler)
+
+ if tableTracker[tostring(v.player)] == nil then
+ DebugPrint("TABLE "..index..": "..v.player.." WAS PUT OUT DUE TO LEAVING")
+ v.player_in = false
+ TriggerClientEvent("BLACKJACK:RetrieveCards", -1, index, v.seat)
+ print("breaking on 1st hand")
+ break
+ else
+ if move == "hit" then
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.hand+1, card, false, false)
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_hit_card_player_0" .. 5-v.seat)
+ table.insert(v.hand, card)
+ Wait(1500)
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.hand) == 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS 21")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ break
+ elseif handValue(v.hand) > 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WENT BUST")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_PLAYER_BUST")
+ else
+ -- Wait(1000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.hand))
+ end
+ elseif move == "stand" then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro_split")
+ -- Wait(1500)
+ break
+ end
+ end
+ until handValue(v.hand) >= 21 or #v.hand == 5
+
+ if v.player_in == true then
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ Wait(1500)
+
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_intro_split")
+ Wait(1500)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_ANOTHER_CARD")
+
+ repeat Wait(0)
+ timeTracker[index] = 0
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_split")
+ print(""..v.player)
+ DebugPrint("TABLE "..index..": AWAITING MOVE FROM "..GetPlayerName(v.player):upper())
+ TriggerClientEvent("BLACKJACK:RequestMove", v.player, moveTime - timeTracker[index])
+ local receivedMove = false
+ local move = "stand"
+ local eventHandler = AddEventHandler("BLACKJACK:ReceivedMove", function(m)
+ if source ~= v.player then return end
+ move = m
+ receivedMove = true
+ end)
+
+ while receivedMove == false and tableTracker[tostring(v.player)] ~= nil and timeTracker[index] < moveTime do
+ for i,v in pairs(currentPlayers) do
+ TriggerClientEvent("BLACKJACK:SyncTimer", v.player, moveTime - timeTracker[index])
+ end
+ Wait(1000)
+ timeTracker[index] = timeTracker[index] + 1
+ end
+ --repeat Wait(0) until receivedMove == true
+ RemoveEventHandler(eventHandler)
+
+ if tableTracker[tostring(v.player)] == nil then
+ DebugPrint("TABLE "..index..": "..v.player.." WAS PUT OUT DUE TO LEAVING")
+ v.player_in = false
+ TriggerClientEvent("BLACKJACK:RetrieveCards", -1, index, v.seat)
+ break
+ else
+ if move == "hit" then
+ local card = takeCard(deck)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, v.seat, #v.splitHand+1, card, false, true)
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_hit_second_card_player_0" .. 5-v.seat)
+ table.insert(v.splitHand, card)
+ Wait(1500)
+ DebugPrint("TABLE "..index..": DEALT "..GetPlayerName(v.player):upper().." "..card)
+
+ if handValue(v.splitHand) == 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS 21")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.splitHand))
+ break
+ elseif handValue(v.splitHand) > 21 then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WENT BUST")
+ -- v.player_in = false
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_PLAYER_BUST")
+ else
+ -- Wait(1000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(v.splitHand))
+ end
+ elseif move == "stand" then
+ break
+ end
+ end
+ until handValue(v.splitHand) >= 21 or #v.splitHand == 5
+
+ if handValue(v.hand) > 21 and handValue(v.splitHand) > 21 then
+ v.player_in = false
+ end
+
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro_split")
+ Wait(1500)
+ end
+
+ break
+
+ -- end
+ elseif move == "stand" then
+ -- PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ -- Wait(1500)
+ break
+ end
+ end
+ end
+
+ if not v.splitHand then
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_dealer_focus_player_0".. 5-v.seat .."_idle_outro")
+ Wait(1500)
+ end
+ end
+ end
+ end
+
+ -- Remove offline players from table
+ local j = 1
+
+ while j <= #currentPlayers do
+ local player = currentPlayers[j]
+
+ if tableTracker[tostring(player.player)] == nil then
+ DebugPrint("TABLE "..index..": "..player.player.." WAS REMOVED FROM PLAYERS LIST FOR LEAVING")
+ table.remove(currentPlayers, j)
+ else
+ j = j + 1
+ end
+ end
+
+ if ArePlayersStillIn(currentPlayers) then
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_turn_card")
+ TriggerClientEvent("BLACKJACK:DealerTurnOverCard", -1, index)
+ dealerVisibleHand = dealerHand
+ Wait(2000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(dealerHand))
+ TriggerClientEvent("BLACKJACK:UpdateDealerHand", -1, index, handValue(dealerVisibleHand))
+ end
+
+ if handValue(dealerHand) < 17 and ArePlayersStillIn(currentPlayers) then
+ repeat
+ local card = takeCard(deck)
+ table.insert(dealerHand, card)
+ TriggerClientEvent("BLACKJACK:GiveCard", -1, index, 0, #dealerHand, card, #dealerHand == 1)
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_deal_card_self_second_card")
+ DebugPrint("TABLE "..index..": DEALT DEALER "..card)
+ Wait(2000)
+ PlayDealerSpeech(index, "MINIGAME_BJACK_DEALER_"..handValue(dealerHand))
+ TriggerClientEvent("BLACKJACK:UpdateDealerHand", -1, index, handValue(dealerVisibleHand))
+ until handValue(dealerHand) >= 17
+ end
+ end
+
+ if handValue(dealerHand) > 21 then
+ PlayDealerSpeech(index, "MINIGAME_DEALER_BUSTS")
+ -- elseif handValue(dealerHand) < 21 and ArePlayersStillIn(currentPlayers) then
+ -- PlayDealerSpeech(index, "MINIGAME_DEALER_WINS")
+ end
+
+ DebugPrint("TABLE "..index..": DEALER HAS "..handValue(dealerHand))
+
+ for i,v in pairs(currentPlayers) do
+ -- if v.player_in then
+
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." HAS "..handValue(v.hand))
+
+ if v.player_in == true and (handValue(v.hand) > handValue(dealerHand) or handValue(dealerHand) > 21) then -- WIN
+ if v.splitHand then
+ if handValue(v.splitHand) > handValue(dealerHand) or handValue(dealerHand) > 21 then -- WIN
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "good")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WON")
+ v.player_in = false
+ end
+ end
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "good")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." WON")
+ GiveMoney(v.player, v.bet*2)
+ v.player_in = false
+ end
+ if v.player_in == true and handValue(v.hand) == handValue(dealerHand) then -- PUSH
+ if v.splitHand then
+ if handValue(v.splitHand) == handValue(dealerHand) then -- PUSH
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "impartial")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." IS PUSH")
+ v.player_in = false
+ end
+ end
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "impartial")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." IS PUSH")
+ GiveMoney(v.player, v.bet)
+ v.player_in = false
+ end
+ if v.player_in == true and handValue(v.hand) < handValue(dealerHand) and handValue(dealerHand) <= 21 then -- LOSE
+ if v.splitHand then
+ if handValue(v.splitHand) < handValue(dealerHand) and handValue(dealerHand) <= 21 then -- LOSE
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." LOST")
+ v.player_in = false
+ end
+ end
+ TriggerClientEvent("BLACKJACK:GameEndReaction", v.player, "bad")
+ DebugPrint("TABLE "..index..": "..GetPlayerName(v.player):upper().." LOST")
+ v.player_in = false
+ end
+ -- end
+ end
+
+ if handValue(dealerHand) >= 17 then
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@shared@dealer@", "female_dealer_reaction_impartial_var0"..math.random(1,3))
+ elseif handValue(dealerHand) > 21 then
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@shared@dealer@", "female_dealer_reaction_good_var0"..math.random(1,3))
+ else
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@shared@dealer@", "female_dealer_reaction_bad_var0"..math.random(1,3))
+ end
+
+ Wait(2500)
+
+ for i,v in pairs(currentPlayers) do
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_retrieve_cards_player_0".. 5-v.seat)
+ Wait(600)
+ TriggerClientEvent("BLACKJACK:RetrieveCardsWithAnim", -1, index, v.seat)
+ Wait(1400)
+
+ v.bet = 0
+ v.player_in = true
+ v.hand = {}
+ v.splitHand = nil
+ end
+
+ PlayDealerAnim(index, "anim_casino_b@amb@casino@games@blackjack@dealer", "female_retrieve_own_cards_and_remove")
+ Wait(600)
+ TriggerClientEvent("BLACKJACK:RetrieveCardsWithAnim", -1, index, 0)
+ Wait(1400)
+
+ timeTracker[index] = 0
+
+ for i,v in pairs(currentPlayers) do
+ TriggerClientEvent("BLACKJACK:RequestBets", v.player, index, timeTracker[index])
+ end
+ -- while true do Wait(0) end
+ else
+ for i,v in pairs(players[index]) do
+ v.bet = 0
+ v.player_in = true
+ v.hand = {}
+ v.splitHand = nil
+ end
+
+ timeTracker[index] = 0
+ end
+ end
+ end
+ end
+ end)
+end
+
+Citizen.CreateThread(function() -- INIT
+ for i,_ in pairs(tables) do
+ StartTableThread(i)
+ players[i] = {}
+ timeTracker[i] = 0
+ end
+end)
+
+function PlayerSatDown(i, seat)
+ table.insert(players[i], {player = source, seat = seat, hand = {}, player_in = true, bet = 0})
+ tableTracker[tostring(source)] = i
+ TriggerClientEvent("BLACKJACK:RequestBets", source, i)
+
+ DebugPrint(GetPlayerName(source):upper() .. " SAT DOWN AT TABLE " .. i)
+ DebugPrint(#players[i])
+end
+
+
+
+RegisterServerEvent("BLACKJACK:PlayerSatDown")
+AddEventHandler('BLACKJACK:PlayerSatDown', PlayerSatDown)
+
+
+function PlayerSatUp(i)
+ DebugPrint(GetPlayerName(source):upper() .. " LEFT TABLE "..i)
+ local num = FindPlayerIdx(players[i], source)
+ if num ~= nil then
+ DebugPrint(GetPlayerName(source):upper() .. " SUCCESSFULLY REMOVED FROM TABLE "..i)
+ table.remove(players[i], num)
+ tableTracker[tostring(source)] = nil
+ PlayDealerSpeech(i, "MINIGAME_DEALER_LEAVE_NEUTRAL_GAME")
+ end
+end
+
+RegisterServerEvent("BLACKJACK:PlayerSatUp")
+AddEventHandler('BLACKJACK:PlayerSatUp', PlayerSatUp)
+
+function PlayerLeft()
+ local playerTbl = tableTracker[tostring(source)]
+
+ if playerTbl ~= nil then
+ DebugPrint(GetPlayerName(source):upper() .. " LEFT SERVER")
+
+ local num = FindPlayerIdx(players[playerTbl], source)
+
+ if num ~= nil then
+ DebugPrint(GetPlayerName(source):upper() .. " REMOVED FROM TABLE FOR LEAVING")
+ table.remove(players[playerTbl], num)
+ end
+
+ tableTracker[tostring(source)] = nil
+ end
+end
+
+AddEventHandler("playerDropped", PlayerLeft)
+
+function PlayerRemove(i)
+ DebugPrint(GetPlayerName(source):upper() .. " LEFT TABLE "..i)
+
+ local num = FindPlayerIdx(players[i], source)
+
+ if num ~= nil then
+ DebugPrint(GetPlayerName(source):upper() .. " SUCCESSFULLY REMOVED FROM TABLE "..i)
+
+ local playerInfo = players[i][num]
+
+ if playerInfo.player_in then
+ if playerInfo.bet > 0 then
+ GiveMoney(source, playerInfo.bet) -- give money back as player was removed before losing or winning?
+ end
+ end
+
+ table.remove(players[i], num)
+ tableTracker[tostring(source)] = nil
+
+ PlayDealerSpeech(i, "MINIGAME_DEALER_LEAVE_NEUTRAL_GAME")
+ end
+end
+
+RegisterServerEvent("BLACKJACK:PlayerRemove")
+AddEventHandler('BLACKJACK:PlayerRemove', PlayerRemove)
+
+exports("SetGetChipsCallback", SetGetChipsCallback)
+exports("SetTakeChipsCallback", SetTakeChipsCallback)
+exports("SetGiveChipsCallback", SetGiveChipsCallback)
+
+
+-- ==================================================================================== Added
+
+local ItemList = {
+ ["casino_redchip"] = 1
+}
+QBCore.Functions.CreateCallback('BLACKJACKKGV:server:blackChipsAmount', function(source, cb)
+ local retval = 0
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.PlayerData.items ~= nil and next(Player.PlayerData.items) ~= nil then
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ retval = retval + (ItemList[Player.PlayerData.items[k].name] * Player.PlayerData.items[k].amount)
+ end
+ end
+ end
+ end
+ cb(retval)
+end)
+
+function SetExports()
+ exports["casino-blackjackKGV"]:SetGetChipsCallback(function(source)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local Chips = Player.Functions.GetItemByName("casino_redchip")
+ local minAmount = 10
+ if Chips ~= nil then
+ if Chips.amount >= minAmount then
+ Chips = Chips
+ else
+ return TriggerClientEvent('QBCore:Notify', src, 'You dont have enough Casino Chips', 'error')
+ end
+ else
+ return TriggerClientEvent('QBCore:Notify', src, 'You dont have any Casino Chips', 'error')
+ end
+ end)
+
+ exports["casino-blackjackKGV"]:SetTakeChipsCallback(function(source, amount)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player ~= nil then
+ Player.Functions.RemoveItem("casino_redchip", amount)
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items['casino_redchip'], "remove", amount)
+ end
+ end)
+
+ exports["casino-blackjackKGV"]:SetGiveChipsCallback(function(source, amount)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player ~= nil then
+ if Player.Functions.AddItem('casino_redchip', amount, nil, {["quality"] = 100}) then
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["casino_redchip"], "add", amount)
+ TriggerClientEvent('QBCore:Notify', src, "You Won "..math.floor(amount).." Casino Chips!")
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'You have to much in your pockets', 'error')
+ end
+ end
+ end)
+end
+
+AddEventHandler("onResourceStart", function(resourceName)
+ if ("casino-blackjackKGV" == resourceName) then
+ Citizen.Wait(1000)
+ SetExports()
+ end
+end)
+
+SetExports()
+
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackRT98/cl_blackjack.lua b/resources/[qb]/[qb_casino]/casino-blackjackRT98/cl_blackjack.lua
new file mode 100644
index 0000000..98ca950
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackRT98/cl_blackjack.lua
@@ -0,0 +1,3087 @@
+--------------------------------------------
+--Created by Robbster, do not redistribute--
+--------------------------------------------
+--If you're snooping here, before you ask why some function names are horrible things like func_368, its so I could keep track of where I was at in the decompiled scripts :P
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+local closeToCasino = false
+local closestChair = -1
+local closestChairDist = 1000
+local Local_198f_247 = -1 --this is just closestChair pretty sure
+local closestDealerPed = nil
+local closestDealerPedDist = 1000
+local dealerPeds = {}
+local Local_198f_255 = nil
+local waitingForBetState = false
+local waitingForSitDownState = false
+local waitingForStandOrHitState = false
+-- local blackjackInstructional = nil
+-- local bettingInstructional = nil
+local blackjackTableData = {}
+-- local timeoutHowToBlackjack = false
+local currentBlackjackGameID = 0
+local timeLeft = 20
+local drawTimerBar = false
+local bettedThisRound = false
+local standOrHitThisRound = false
+local globalGameId = -1
+local globalNextCardCount = -1
+cardObjects = {}
+local drawCurrentHand = false
+local currentHand = 0
+local dealersHand = 0
+currentBetAmount = 0
+sittingAtBlackjackTable = false
+local canExitBlackjack = false
+local dealerSecondCardFromGameId = {}
+local blackjackGameInProgress = false
+local shouldForceIdleCardGames = false
+
+local cfg = {}
+
+--Please note the config order is important, dealerPositions must start from 0 and increase consecutively
+cfg.blackjackTables = {
+ --[id] = {x,y,z,heading}
+ [0] = {
+ dealerPos = vector3(986.018, 59.759, 70.238),
+ dealerHeading = 10.804,
+ tablePos = vector3(985.9037, 60.55936, 69.23269),
+ tableHeading = 188.309,
+ distance = 1000.0,
+ prop = "vw_prop_casino_blckjack_01b"
+ },
+ [1] = {
+ dealerPos = vector3(981.661, 62.706, 70.238),
+ dealerHeading = 282.591,
+ tablePos = vector3(982.48, 62.90, 69.32),
+ tableHeading = 103.309,
+ distance = 1000.0,
+ prop = "vw_prop_casino_blckjack_01b"
+ },
+ [2] = {
+ dealerPos = vector3(988.644, 46.497, 70.238),
+ dealerHeading = 199.665,
+ tablePos = vector3(989.93, 45.7245, 69.23),
+ tableHeading = 23.309,
+ distance = 1000.0,
+ prop = "vw_prop_casino_blckjack_01b"
+ },
+ [3] = {
+ dealerPos = vector3(986.486, 41.996, 70.238),
+ dealerHeading = 284.971,
+ tablePos = vector3(987.26, 42.203, 69.232),
+ tableHeading = 103.309,
+ distance = 1000.0,
+ prop = "vw_prop_casino_blckjack_01b"
+ },
+}
+
+--Use this command to get the coords you need for setting up new tables.
+--Some maps use the prop vw_prop_casino_blckjack_01 some use vw_prop_casino_blckjack_01b, so change accordingly.
+RegisterCommand("getcasinotable",function()
+ local playerCoords = GetEntityCoords(PlayerPedId())
+ local blackjackTable = GetClosestObjectOfType(playerCoords.x,playerCoords.y,playerCoords.z,3.0,GetHashKey("vw_prop_casino_blckjack_01"),0,0,0)
+ if DoesEntityExist(blackjackTable) then
+ print("Found entity")
+ print("tablePos pos",GetEntityCoords(blackjackTable))
+ print("tableHeading heading",GetEntityHeading(blackjackTable))
+ print("prop: vw_prop_casino_blckjack_01")
+ else
+ local blackjackTable2 = GetClosestObjectOfType(playerCoords.x,playerCoords.y,playerCoords.z,3.0,GetHashKey("vw_prop_casino_blckjack_01b"),0,0,0)
+ if DoesEntityExist(blackjackTable2) then
+ print("Found entity")
+ print("tablePos pos:",GetEntityCoords(blackjackTable2))
+ print("tableHeading heading:",GetEntityHeading(blackjackTable2))
+ print("prop: vw_prop_casino_blckjack_01")
+ else
+ print("Could not find entity")
+ end
+ end
+end)
+
+CreateThread(function()
+ TriggerServerEvent("Blackjack:requestBlackjackTableData")
+end)
+
+RegisterNetEvent("Blackjack:sendBlackjackTableData")
+AddEventHandler("Blackjack:sendBlackjackTableData", function(newBlackjackTableData)
+ blackjackTableData = newBlackjackTableData
+end)
+
+CreateThread(function()
+ while not closeToCasino do
+ Wait(0)
+ end
+ maleCasinoDealer = GetHashKey("S_M_Y_Casino_01")
+ femaleCasinoDealer = GetHashKey("S_F_Y_Casino_01")
+ math.randomseed(GetGameTimer())
+
+ dealerAnimDict = "anim_casino_b@amb@casino@games@shared@dealer@"
+ RequestAnimDict(dealerAnimDict)
+ while not HasAnimDictLoaded(dealerAnimDict) do
+ Wait(0)
+ end
+ for i=0,#cfg.blackjackTables,1 do
+ math.random() math.random() math.random()
+ randomBlackShit = math.random(1,13)
+ if randomBlackShit < 7 then
+ dealerModel = maleCasinoDealer
+ else
+ dealerModel = femaleCasinoDealer
+ end
+ RequestModel(dealerModel)
+ while not HasModelLoaded(dealerModel) do
+ RequestModel(dealerModel)
+ Wait(0)
+ end
+ dealerEntity = CreatePed(26,dealerModel,cfg.blackjackTables[i].dealerPos.x,cfg.blackjackTables[i].dealerPos.y,cfg.blackjackTables[i].dealerPos.z,cfg.blackjackTables[i].dealerHeading,false,true)
+ table.insert(dealerPeds,dealerEntity)
+ SetModelAsNoLongerNeeded(dealerModel)
+ SetEntityCanBeDamaged(dealerEntity, 0)
+ SetPedAsEnemy(dealerEntity, 0)
+ SetBlockingOfNonTemporaryEvents(dealerEntity, 1)
+ SetPedResetFlag(dealerEntity, 249, 1)
+ SetPedConfigFlag(dealerEntity, 185, true)
+ SetPedConfigFlag(dealerEntity, 108, true)
+ SetPedCanEvasiveDive(dealerEntity, 0)
+ SetPedCanRagdollFromPlayerImpact(dealerEntity, 0)
+ SetPedConfigFlag(dealerEntity, 208, true)
+ setBlackjackDealerPedVoiceGroup(randomBlackShit,dealerEntity)
+ setBlackjackDealerClothes(randomBlackShit,dealerEntity)
+ SetEntityCoordsNoOffset(dealerEntity, cfg.blackjackTables[i].dealerPos.x,cfg.blackjackTables[i].dealerPos.y,cfg.blackjackTables[i].dealerPos.z, 0,0,1)
+ SetEntityHeading(dealerEntity, cfg.blackjackTables[i].dealerHeading)
+ if dealerModel == maleCasinoDealer then
+ TaskPlayAnim(dealerEntity, dealerAnimDict, "idle", 1000.0, -2.0, -1, 2, 1148846080, 0) --anim_name is idle or female_idle depending on gender
+ else
+ TaskPlayAnim(dealerEntity, dealerAnimDict, "female_idle", 1000.0, -2.0, -1, 2, 1148846080, 0) --anim_name is idle or female_idle depending on gender
+ end
+ PlayFacialAnim(dealerEntity, "idle_facial", dealerAnimDict)
+ RemoveAnimDict(dealerAnimDict)
+ end
+ local blackjackTable = GetClosestObjectOfType(1129.406, 262.3578, -52.041,1.0,GetHashKey("vw_prop_casino_blckjack_01b"),0,0,0)
+ SetObjectTextureVariant(blackjackTable,3)
+ local rouletteTable = GetClosestObjectOfType(1132.7875976563,262.42929077148,-51.035781860352,1.0,GetHashKey("vw_prop_casino_roulette_01b"),0,0,0)
+ SetObjectTextureVariant(rouletteTable,3)
+ local rouletteTable2 = GetClosestObjectOfType(1130.5859375,266.35610961914,-51.035778045654,1.0,GetHashKey("vw_prop_casino_roulette_01b"),0,0,0)
+ SetObjectTextureVariant(rouletteTable2,3)
+ local threeCardPoker = GetClosestObjectOfType(1132.9125976563,265.86212158203,-51.035766601563,1.0,GetHashKey("vw_prop_casino_3cardpoker_01b"),0,0,0)
+ SetObjectTextureVariant(threeCardPoker,3)
+
+ local blackjackTable = GetClosestObjectOfType(1145.3294677734,248.06758117676,-51.035781860352,1.0,GetHashKey("vw_prop_casino_blckjack_01b"),0,0,0)
+ SetObjectTextureVariant(blackjackTable,3)
+ local rouletteTable = GetClosestObjectOfType(1147.9478759766,247.95536804199,-51.035766601563,1.0,GetHashKey("vw_prop_casino_roulette_01b"),0,0,0)
+ SetObjectTextureVariant(rouletteTable,3)
+ local rouletteTable2 = GetClosestObjectOfType(1144.6773681641,250.74932861328,-51.035762786865,1.0,GetHashKey("vw_prop_casino_roulette_01b"),0,0,0)
+ SetObjectTextureVariant(rouletteTable2,3)
+ local threeCardPoker = GetClosestObjectOfType(1147.9067382813,250.86437988281,-51.035781860352,1.0,GetHashKey("vw_prop_casino_3cardpoker_01b"),0,0,0)
+ SetObjectTextureVariant(threeCardPoker,3)
+end)
+
+function resetDealerIdle(dealerPed)
+ local gender = getDealerGenderFromPed(dealerPed)
+ if DoesEntityExist(dealerPed) then
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ dealerAnimDict = "anim_casino_b@amb@casino@games@shared@dealer@"
+ RequestAnimDict(dealerAnimDict)
+ while not HasAnimDictLoaded(dealerAnimDict) do
+ Wait(0)
+ end
+ -- -- print("playing idle animation: " .. tostring(genderAnimString .. "idle"))
+ TaskPlayAnim(dealerPed, dealerAnimDict, genderAnimString .. "idle", 1000.0, -2.0, -1, 2, 1148846080, 0) --anim_name is idle or female_idle depending on gender
+ PlayFacialAnim(dealerPed, "idle_facial", dealerAnimDict)
+ TaskPlayAnim(PlayerPedId(),"anim_casino_b@amb@casino@games@shared@player@", "idle_cardgames", 1.0, 1.0, -1, 0)
+ end
+end
+
+CreateThread(function()
+ while true do
+ if shouldForceIdleCardGames and sittingAtBlackjackTable then
+ TaskPlayAnim(PlayerPedId(),"anim_casino_b@amb@casino@games@shared@player@", "idle_cardgames", 1.0, 1.0, -1, 0)
+ end
+ Wait(0)
+ end
+end)
+
+
+
+
+
+
+
+RegisterNetEvent('doj:client:openBetMenu', function()
+ exports['qb-menu']:openMenu({
+ {
+ header = "The Diamond Casino & Resort Blackjack",
+ isMenuHeader = true,
+ },
+ {
+ header = "Increase Bet",
+ txt = "+10",
+ params = {
+ event = "doj:client:startingBets",
+ args = 1
+ }
+ },
+ {
+ header = "Decrease bet",
+ txt = "-10",
+ params = {
+ event = "doj:client:startingBets",
+ args = 2
+ }
+ },
+ {
+ header = "Submit bet",
+ txt = "",
+ params = {
+ event = "doj:client:startingBets",
+ args = 3
+ }
+ },
+ -- {
+ -- header = "Custom Bet",
+ -- txt = "",
+ -- params = {
+ -- event = "doj:client:startingBets",
+ -- args = 4
+ -- }
+ -- },
+ {
+ header = "Exit",
+ txt = "",
+ params = {
+ event = "doj:client:startingBets",
+ args = 5
+ }
+ },
+ })
+end)
+
+RegisterNetEvent("doj:client:startingBets", function(args)
+ local args = tonumber(args)
+ if waitingForBetState then
+ if args == 1 then
+ -- -- print("Bet raised")
+ TriggerEvent("doj:client:openBetMenu")
+ currentBetAmount = currentBetAmount + 10
+ elseif args == 2 then
+ -- -- print("Bet lowered")
+ TriggerEvent("doj:client:openBetMenu")
+ if currentBetAmount >= 10 then
+ currentBetAmount = currentBetAmount - 10
+ else
+ QBCore.Functions.Notify("Cannot bet below zero", "error", 3500)
+ end
+ elseif args == 3 then
+ -- -- print("submitting bet")
+ if tonumber(currentBetAmount) >= 0 then
+ TriggerServerEvent("Blackjack:setBlackjackBet",globalGameId,currentBetAmount,closestChair)
+ closestDealerPed = getClosestDealer()
+ PlayAmbientSpeech1(closestDealerPed,"MINIGAME_DEALER_PLACE_CHIPS","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1) --TODO check this is the right sound?
+ putBetOnTable()
+ Wait(1000)
+ else
+ QBCore.Functions.Notify("Invalid amount.", "error", 3500)
+ end
+ elseif args == 4 then
+ -- -- print("custom bet")
+ local tmpInput = getGenericTextInput("Bet Amount")
+ if tonumber(tmpInput) then
+ tmpInput = tonumber(tmpInput)
+ if tmpInput > 0 then
+ currentBetAmount = tmpInput
+ end
+ end
+ TriggerEvent("doj:client:openBetMenu")
+ else
+ -- print('exit')
+ shouldForceIdleCardGames = false
+ blackjackAnimDictToLoad = "anim_casino_b@amb@casino@games@shared@player@"
+ RequestAnimDict(blackjackAnimDictToLoad)
+ while not HasAnimDictLoaded(blackjackAnimDictToLoad) do
+ Wait(0)
+ end
+ NetworkStopSynchronisedScene(Local_198f_255)
+ TaskPlayAnim(PlayerPedId(), blackjackAnimDictToLoad, "sit_exit_left", 1.0, 1.0, 2500, 0)
+ sittingAtBlackjackTable = false
+ drawTimerBar = false
+ drawCurrentHand = false
+ exports['casinoUi']:HideCasinoUi('hide')
+ waitingForBetState = false
+ TriggerServerEvent("Blackjack:leaveBlackjackTable")
+ closestDealerPed, closestDealerPedDistance = getClosestDealer()
+ PlayAmbientSpeech1(closestDealerPed,"MINIGAME_DEALER_LEAVE_NEUTRAL_GAME","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ end
+ end
+end)
+
+RegisterNetEvent('doj:client:hit&standMenu', function()
+ exports['qb-menu']:openMenu({
+ {
+ header = "The Diamond Casino & Resort Blackjack",
+ isMenuHeader = true,
+ },
+ {
+ header = "Hit",
+ txt = "Draw another card",
+ params = {
+ event = "doj:client:hit&standActions",
+ args = 1
+ }
+ },
+ {
+ header = "Stand",
+ txt = "Be a pussy",
+ params = {
+ event = "doj:client:hit&standActions",
+ args = 2
+ }
+ },
+ })
+end)
+
+RegisterNetEvent("doj:client:hit&standActions", function(args)
+ local args = tonumber(args)
+ if waitingForStandOrHitState and sittingAtBlackjackTable and blackjackGameInProgress then
+ if args == 1 then
+ -- print("hit")
+ waitingForStandOrHitState = false
+ TriggerServerEvent("Blackjack:hitBlackjack",globalGameId,globalNextCardCount)
+ drawTimerBar = false
+ standOrHitThisRound = true
+ requestCard()
+ else
+ -- print("stand")
+ waitingForStandOrHitState = false
+ TriggerServerEvent("Blackjack:standBlackjack",globalGameId,globalNextCardCount)
+ drawTimerBar = false
+ standOrHitThisRound = true
+ declineCard()
+ end
+ end
+end)
+
+RegisterNetEvent("Blackjack:successBlackjackBet")
+AddEventHandler("Blackjack:successBlackjackBet",function()
+ bettedThisRound = true
+ waitingForBetState = false
+ canExitBlackjack = false
+end)
+
+
+
+RegisterNetEvent("Blackjack:sitAtBlackjackTable",function(chair)
+ goToBlackjackSeat(chair)
+end)
+
+CreateThread(function()
+ while true do
+ local playerCoords = GetEntityCoords(PlayerPedId())
+ closeToCasino = false
+ for k,v in pairs(cfg.blackjackTables) do
+ cfg.blackjackTables[k].distance = #(playerCoords-cfg.blackjackTables[k].tablePos)
+ if cfg.blackjackTables[k].distance < 100.0 then
+ closeToCasino = true
+ end
+ end
+ Wait(1000)
+ end
+end)
+
+
+CreateThread(function()
+ while true do
+ local sleep = 5
+ local playerPed = PlayerPedId()
+ local inZone = false
+ if not sittingAtBlackjackTable then
+ if closestChair ~= nil and closestChairDist < 1.3 then
+ inZone = true
+ text = "The Diamond Casino & ResortBlackjack RT98Press E to sit"
+ if not timeoutHowToBlackjack then
+ if IsControlJustPressed(0, 38) then
+ if blackjackTableData[closestChair] == false then
+ print("calling goToBlackjackSeat with chairID: " .. tostring(closestChair))
+ TriggerServerEvent("Blackjack:requestSitAtBlackjackTable",closestChair)
+ else
+ QBCore.Functions.Notify("This seat is taken.", "error", 3500)
+ end
+ end
+ end
+ end
+ if inZone and not alreadyEnteredZone then
+ alreadyEnteredZone = true
+ exports['qb-core']:DrawText(text, "top")
+ end
+ if not inZone and alreadyEnteredZone then
+ alreadyEnteredZone = false
+ exports["qb-core"]:HideText()
+ end
+ end
+ Wait(sleep)
+ end
+end)
+
+CreateThread(function()
+ while true do
+ if closeToCasino then
+ closestChairDist = 1000
+ closestChair = -1
+ local playerCoords = GetEntityCoords(PlayerPedId())
+ for i=0,((#cfg.blackjackTables+1)*4)-1,1 do
+ local vectorOfBlackjackSeat = blackjack_func_348(i)
+ local distToBlackjackSeat = #(playerCoords - vectorOfBlackjackSeat)
+ if distToBlackjackSeat < closestChairDist then
+ closestChairDist = distToBlackjackSeat
+ closestChair = i
+ end
+ end
+ -- -- print("closestChair = ",closestChair)
+ end
+ Wait(100)
+ end
+end)
+
+CreateThread(function()
+ while true do
+ if drawTimerBar then
+ QBCore.Functions.TriggerCallback('BLACKJACKRT98:server:blackChipsAmount', function(result)
+ retval = result
+ exports['casinoUi']:DrawCasinoUi('show', "The Diamond Casino & Resort BlackjackTime Left: 0:"..timeLeft.."Availble chips: "..math.floor(result).."Current Bet: "..math.floor(currentBetAmount))
+ end)
+ end
+ if drawCurrentHand then
+ exports['qb-core']:DrawText("Dealers Hand: "..math.floor(dealersHand).."Your hand: "..math.floor(currentHand), "top")
+ end
+ Wait(250)
+ end
+end)
+
+RegisterNetEvent("Blackjack:syncChipsPropBlackjack")
+AddEventHandler("Blackjack:syncChipsPropBlackjack",function(betAmount,chairId)
+ if closeToCasino then
+ betBlackjack(betAmount,chairId)
+ end
+end)
+
+RegisterNetEvent("Blackjack:beginBetsBlackjack")
+AddEventHandler("Blackjack:beginBetsBlackjack",function(gameID,tableId)
+ globalGameId = gameID
+ -- blackjackInstructional = setupBlackjackInstructionalScaleform("instructional_buttons")
+ -- exports["qb-core"]:HideText()
+ TriggerEvent("doj:client:openBetMenu")
+ -- QBCore.Functions.Notify("Place your bets", 'primary', 3500)
+ exports['qb-core']:DrawText("Place your bets...", "top")
+
+ bettedThisRound = false
+ drawTimerBar = true
+ drawCurrentHand = false
+ standOrHitThisRound = false
+ canExitBlackjack = true
+ waitingForBetState = true
+ dealerPed = getDealerFromTableId(tableId)
+ PlayAmbientSpeech1(dealerPed,"MINIGAME_DEALER_PLACE_BET","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ currentBetAmount = 0
+ dealersHand = 0
+ currentHand = 0
+ SetEntityCoordsNoOffset(dealerPed, cfg.blackjackTables[tableId].dealerPos.x,cfg.blackjackTables[tableId].dealerPos.y,cfg.blackjackTables[tableId].dealerPos.z, 0,0,1)
+ SetEntityHeading(dealerPed, cfg.blackjackTables[tableId].dealerHeading)
+ CreateThread(function()
+ drawTimerBar = true
+ while timeLeft > 0 do
+ timeLeft = timeLeft - 1
+ Wait(1000)
+ end
+ timeLeft = 20
+ drawTimerBar = false
+ -- if not bettedThisRound then
+ --QBCore.Functions.Notify("No bet placed, round skipped", 'primary', 3500)
+
+ -- end
+ end)
+end)
+
+RegisterNetEvent("Blackjack:beginCardGiveOut")
+AddEventHandler("Blackjack:beginCardGiveOut",function(gameId,cardData,chairId,cardIndex,gotCurrentHand,tableId)
+ if closeToCasino then
+ blackjackGameInProgress = true
+ exports['casinoUi']:HideCasinoUi('hide')
+ blackjackAnimsToLoad = {
+ "anim_casino_b@amb@casino@games@blackjack@dealer",
+ "anim_casino_b@amb@casino@games@shared@dealer@",
+ "anim_casino_b@amb@casino@games@blackjack@player",
+ "anim_casino_b@amb@casino@games@shared@player@",
+ }
+ for k,v in pairs(blackjackAnimsToLoad) do
+ RequestAnimDict(v)
+ while not HasAnimDictLoaded(v) do
+ Wait(0)
+ end
+ end
+ if sittingAtBlackjackTable and bettedThisRound then
+ drawCurrentHand = true
+ end
+ dealerPed = getDealerFromTableId(tableId)
+ cardObj = startDealing(dealerPed,gameId,cardData,chairId,cardIndex+1,gotCurrentHand,((tableId+1)*4)-1)
+ if blackjack_func_368(closestChair) == tableId and gameId == chairId and cardIndex == 0 then
+ dealersHand = gotCurrentHand
+ -- blackjackInstructional = nil
+ end
+ dealerSecondCardFromGameId[gameId] = cardObj
+ if chairId == closestChair and gameId ~= chairId then
+ currentHand = gotCurrentHand
+ -- blackjackInstructional = nil
+ end
+ end
+end)
+
+RegisterNetEvent("Blackjack:singleCard")
+AddEventHandler("Blackjack:singleCard",function(gameId,cardData,chairID,nextCardCount,gotCurrentHand,tableId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ startSingleDealing(chairID,dealerPed,gameId,cardData,nextCardCount+1,gotCurrentHand)
+ end
+end)
+
+RegisterNetEvent("Blackjack:singleDealerCard")
+AddEventHandler("Blackjack:singleDealerCard",function(gameId,cardData,nextCardCount,gotCurrentHand,tableId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ startSingleDealerDealing(dealerPed,gameId,cardData,nextCardCount+1,gotCurrentHand,((tableId+1)*4)-1,tableId)
+ end
+end)
+
+RegisterNetEvent("Blackjack:standOrHit")
+AddEventHandler("Blackjack:standOrHit",function(gameId,chairId,nextCardCount,tableId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ standOrHitThisRound = false
+ if closestChair == chairId then
+ globalNextCardCount = nextCardCount
+ waitingForStandOrHitState = true
+ PlayAmbientSpeech1(dealerPed,"MINIGAME_BJACK_DEALER_ANOTHER_CARD","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ TriggerEvent("doj:client:hit&standMenu")
+ startStandOrHit(gameId,dealerPed,chairId,true)
+ CreateThread(function()
+ if sittingAtBlackjackTable then
+ drawTimerBar = true
+ timeLeft = 20
+ while timeLeft > 0 do
+ timeLeft = timeLeft - 1
+ if timeLeft == 6 then
+ PlayAmbientSpeech1(dealerPed,"MINIGAME_DEALER_COMMENT_SLOW","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1) --TODO check this is the right sound?
+ end
+ if standOrHitThisRound then
+ -- -- print("terminating standorhit timer thread")
+ timeLeft = 20
+ drawTimerBar = false
+ return
+ -- -- print("failed it didnt terminate!")
+ end
+ Wait(1000)
+ end
+ end
+ if not standOrHitThisRound and sittingAtBlackjackTable then
+ -- print("you took too long fam standing shit")
+ waitingForStandOrHitState = false
+ TriggerServerEvent("Blackjack:standBlackjack",globalGameId,globalNextCardCount)
+ declineCard()
+ QBCore.Functions.Notify("Failed to stand/hit in time, standing.", 'error', 3500)
+ end
+ end)
+ else
+ startStandOrHit(gameId,dealerPed,chairId,false)
+ end
+ end
+end)
+
+function getClosestDealer()
+ local tmpclosestDealerPed = nil
+ local tmpclosestDealerPedDistance = 100000
+ local playerCoords = GetEntityCoords(PlayerPedId())
+ for k,v in pairs(dealerPeds) do
+ local dealerPed = v
+ -- -- print("Entity ID of this dealer ped: " .. tostring(dealerPed))
+ local distanceToDealer = #(playerCoords - GetEntityCoords(dealerPed))
+ -- -- print("Distance to dealer ped: " .. tostring(distanceToDealer))
+ if distanceToDealer < tmpclosestDealerPedDistance then
+ tmpclosestDealerPedDistance = distanceToDealer
+ tmpclosestDealerPed = dealerPed
+ end
+ end
+ -- -- print("Closest dealer ped is: " .. tostring(tmpclosestDealerPed))
+ closestDealerPed = tmpclosestDealerPed
+ closestDealerPedDistance = tmpclosestDealerPedDistance
+ return closestDealerPed, closestDealerPedDistance
+end
+
+function getDealerFromChairId(chairId)
+ tableId = blackjack_func_368(chairId)
+ closestDealerPed = dealerPeds[tableId+1]
+ return closestDealerPed
+end
+
+function getDealerFromTableId(tableId)
+ closestDealerPed = dealerPeds[tableId+1]
+ return closestDealerPed
+end
+
+function goToBlackjackSeat(blackjackSeatID)
+
+ sittingAtBlackjackTable = true
+ waitingForSitDownState = true
+ canExitBlackjack = true
+ currentHand = 0
+ dealersHand = 0
+
+ closestDealerPed, closestDealerPedDistance = getClosestDealer()
+ PlayAmbientSpeech1(closestDealerPed,"MINIGAME_DEALER_GREET","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+
+
+ -- print("[CMG Casino] start sit at blackjack seat")
+ exports['qb-core']:DrawText("Waiting for game to start...", "top")
+
+ blackjackAnimsToLoad = {
+ "anim_casino_b@amb@casino@games@blackjack@dealer",
+ "anim_casino_b@amb@casino@games@shared@dealer@",
+ "anim_casino_b@amb@casino@games@blackjack@player",
+ "anim_casino_b@amb@casino@games@shared@player@",
+ }
+ for k,v in pairs(blackjackAnimsToLoad) do
+ RequestAnimDict(v)
+ while not HasAnimDictLoaded(v) do
+ Wait(10)
+ end
+ end
+ -- print("[CMG Casino] blackjack anims loaded")
+ Local_198f_247 = blackjackSeatID
+ print("blackjackSeatID: " .. blackjackSeatID)
+ fVar3 = blackjack_func_217(PlayerPedId(),blackjack_func_218(Local_198f_247, 0), 1)
+ fVar4 = blackjack_func_217(PlayerPedId(),blackjack_func_218(Local_198f_247, 1), 1)
+ fVar5 = blackjack_func_217(PlayerPedId(),blackjack_func_218(Local_198f_247, 2), 1)
+ -- print("[CMG Casino] fVars passed")
+ if (fVar4 < fVar5 and fVar4 < fVar3) then
+ Local_198f_251 = 1
+ elseif (fVar5 < fVar4 and fVar5 < fVar3) then
+ Local_198f_251 = 2
+ else
+ Local_198f_251 = 0
+ end
+ --blackjack_func_218 is get_anim_offset
+ --param0 is 0-3 && param1 is 0-15? (OF blackjack_func_218)
+ local walkToVector = blackjack_func_218(Local_198f_247, Local_198f_251)
+ local targetHeading = blackjack_func_216(Local_198f_247, Local_198f_251)
+ -- -- print("[CMG Casino] walking to seat, x: " .. tostring(walkToVector.x) .. " y: " .. tostring(walkToVector.y) .. " z: " .. tostring(walkToVector.z))
+ TaskGoStraightToCoord(PlayerPedId(), walkToVector.x, walkToVector.y, walkToVector.z, 1.0, 5000, targetHeading, 0.01)
+
+ local goToVector = blackjack_func_348(Local_198f_247)
+ local xRot,yRot,zRot = blackjack_func_215(Local_198f_247)
+ -- -- print("[CMG Casino] Blackjack sit at table net scene starting")
+ -- -- print("[CMG Casino] creating Scene at, x: " .. tostring(goToVector.x) .. " y: " .. tostring(goToVector.y) .. " z: " .. tostring(goToVector.z))
+ Local_198f_255 = NetworkCreateSynchronisedScene(goToVector.x, goToVector.y, goToVector.z, xRot, yRot, zRot, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), Local_198f_255, "anim_casino_b@amb@casino@games@shared@player@", blackjack_func_213(Local_198f_251), 2.0, -2.0, 13, 16, 2.0, 0) -- 8.0, -1.5, 157, 16, 1148846080, 0) ?
+ NetworkStartSynchronisedScene(Local_198f_255)
+ -- -- print("[CMG Casino] Blackjack sit at table net scene started")
+ --Local_198.f_255 = NETWORK::NETWORK_CREATE_SYNCHRONISED_SCENE(func_348(Local_198.f_247), func_215(Local_198.f_247), 2, 1, 0, 1065353216, 0, 1065353216)
+ --NETWORK::NETWORK_ADD_PED_TO_SYNCHRONISED_SCENE(PLAYER::PLAYER_PED_ID(), Local_198.f_255, "anim_casino_b@amb@casino@games@shared@player@", blackjack_func_213(Local_198f_251), 2f, -2f, 13, 16, 2f, 0)
+ --NETWORK::NETWORK_START_SYNCHRONISED_SCENE(Local_198.f_255)
+
+ --NEXT --> Line 5552
+ Citizen.InvokeNative(0x79C0E43EB9B944E2, -2124244681)
+ Wait(6000)
+ -- -- print("STOP STITTING ")
+ --Wait for sit down anim to end
+ Locali98f_55 = NetworkCreateSynchronisedScene(goToVector.x, goToVector.y, goToVector.z, xRot, yRot, zRot, 2, 1, 1, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), Locali98f_55, "anim_casino_b@amb@casino@games@shared@player@", "idle_cardgames", 2.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(Locali98f_55)
+ StartAudioScene("DLC_VW_Casino_Table_Games") --need to stream this
+ Citizen.InvokeNative(0x79C0E43EB9B944E2, -2124244681)
+ waitingForSitDownState = false
+ shouldForceIdleCardGames = true
+end
+
+function betBlackjack(amount,chairId)
+ local chipsProp = getChipPropFromAmount(amount)
+ --betChipsForNextHand(100,chipsProp,pos,chairId,false,stack/100) --false or true no clue
+ -- for stack=1,10,1 do
+ -- for pos=0,1,1 do --can be 0 to 3, however last 2 chip x/y positions are for a split I think
+
+ -- end
+ -- end
+ for i,v in ipairs(chipsProp) do
+ betChipsForNextHand(100,v,0,chairId,false,(i-1)/200) --false or true no clue
+ end
+end
+
+function startSingleDealerDealing(dealerPed,gameId,cardData,nextCardCount,gotCurrentHand,chairId,tableId)
+ -- -- print("startSingleDealerDealing", chairId)
+ N_0x469f2ecdec046337(1)
+ StartAudioScene("DLC_VW_Casino_Cards_Focus_Hand") --need to stream this
+ ensureCardModelsLoaded() --request all 52 card models
+ --AUDIO::_0xF8AD2EED7C47E8FE(iVar1, false, 1); call sound on dealer
+ ----------------THIS CREATES A CARD AT THE MACHINE WHERE THE CARD COMES OUT OF-----------------------
+ -- -- print("dealerPed: " .. tostring(dealerPed))
+ -- -- print("DoesEntityExist(dealerPed): " .. tostring(DoesEntityExist(dealerPed)))
+ -- -- print("NetworkHasControlOfEntity(dealerPed): " .. tostring(NetworkHasControlOfEntity(dealerPed)))
+ local gender = getDealerGenderFromPed(dealerPed)
+ -- -- print("getLocalChairIdFromGlobalChairId: " .. tostring(getLocalChairIdFromGlobalChairId))
+ if DoesEntityExist(dealerPed) then
+ cardPosition = nextCardCount
+ -- -- print("getLocalChairIdFromGlobalChairId: " .. tostring(getLocalChairIdFromGlobalChairId))
+ nextCard = getCardFromNumber(cardData,true)
+ local nextCardObj = getNewCardFromMachine(nextCard,chairId,gameId)
+ AttachEntityToEntity(nextCardObj, dealerPed, GetPedBoneIndex(dealerPed,28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ dealerGiveSelfCard(genderAnimString,dealerPed,3,nextCardObj)
+ DetachEntity(nextCardObj,false,true)
+ -- -- print("blackjack_func_368(closestChair)",blackjack_func_368(closestChair))
+ -- -- print("tableId",tableId)
+ if blackjack_func_368(closestChair) == tableId then
+ dealersHand = gotCurrentHand
+ end
+ local soundCardString = "MINIGAME_BJACK_DEALER_" .. tostring(gotCurrentHand)
+ PlayAmbientSpeech1(dealerPed,soundCardString,"SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairId)))
+ local tablePosX,tablePosY,tablePosZ = getTableCoords(blackjack_func_368(chairId))
+ local cardQueue = cardPosition -- number of card
+ local iVar5 = cardQueue
+ cardOffsetX,cardOffsetY,cardOffsetZ = blackjack_func_377(iVar5, 4, 1) --iVar9 is seat number 0-3
+ local cardPos = GetObjectOffsetFromCoords(tablePosX, tablePosY, tablePosZ, vVar8.z, cardOffsetX, cardOffsetY, cardOffsetZ)
+ SetEntityCoordsNoOffset(nextCardObj, cardPos.x, cardPos.y, cardPos.z, 0, 0, 1)
+ Wait(400)
+ else
+ -- -- print("Failed to deal cards, entity doesn't exist or we don't have control")
+ end
+end
+
+function startSingleDealing(chairId,dealerPed,gameId,cardData,nextCardCount,gotCurrentHand)
+ N_0x469f2ecdec046337(1)
+ StartAudioScene("DLC_VW_Casino_Cards_Focus_Hand") --need to stream this
+ ensureCardModelsLoaded()
+ local gender = getDealerGenderFromPed(dealerPed)
+ if DoesEntityExist(dealerPed) then
+ local localChairId = getLocalChairIdFromGlobalChairId(chairId)
+ cardPosition = nextCardCount
+ nextCard = getCardFromNumber(cardData,true)
+ local nextCardObj = getNewCardFromMachine(nextCard,chairId)
+ AttachEntityToEntity(nextCardObj, dealerPed, GetPedBoneIndex(dealerPed,28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ dealerGiveCards(chairId,genderAnimString,dealerPed,nextCardObj)
+ DetachEntity(nextCardObj,false,true)
+ if chairId == closestChair then
+ currentHand = gotCurrentHand
+ end
+ local soundCardString = "MINIGAME_BJACK_DEALER_" .. tostring(gotCurrentHand)
+ -- -- print("trying soundString: " .. tostring(soundCardString))
+ PlayAmbientSpeech1(dealerPed,soundCardString,"SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairId)))
+ local tablePosX,tablePosY,tablePosZ = getTableCoords(blackjack_func_368(chairId))
+ local cardQueue = cardPosition -- number of card
+ local iVar5 = cardQueue
+ local iVar9 = localChairId - 1-- <-ChairID 0-3
+ if iVar9 <= 4 then
+ -- -- print("single card pos: " .. tostring(iVar5))
+ cardOffsetX,cardOffsetY,cardOffsetZ = blackjack_func_377(iVar5, iVar9, 0) --iVar9 is seat number 0-3
+ else
+ cardOffsetX,cardOffsetY,cardOffsetZ = 0.5737, 0.2376, 0.948025
+ end
+ local cardPos = GetObjectOffsetFromCoords(tablePosX, tablePosY, tablePosZ, vVar8.z, cardOffsetX, cardOffsetY, cardOffsetZ)
+ SetEntityCoordsNoOffset(nextCardObj, cardPos.x, cardPos.y, cardPos.z, 0, 0, 1)
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairId)))
+ cardObjectOffsetRotation = vVar8 + func_376(iVar5, iVar9, 0, false)
+ SetEntityRotation(nextCardObj, cardObjectOffsetRotation.x, cardObjectOffsetRotation.y, cardObjectOffsetRotation.z, 2, 1)
+ Wait(400)
+ else
+ -- print("Failed to deal cards, entity doesn't exist or we don't have control")
+ end
+end
+
+function startDealing(dealerPed,gameId,cardData,chairId,cardIndex,gotCurrentHand,fakeChairIdForDealerTurn)
+ -- print("startDealing()")
+ --NEXT --> func_90 the FAT FUNCTION
+ N_0x469f2ecdec046337(1)
+ StartAudioScene("DLC_VW_Casino_Cards_Focus_Hand") --need to stream this
+ ensureCardModelsLoaded() --request all 52 card models
+ --AUDIO::_0xF8AD2EED7C47E8FE(iVar1, false, 1); call sound on dealer
+ ----------------THIS CREATES A CARD AT THE MACHINE WHERE THE CARD COMES OUT OF-----------------------
+ -- print("dealerPed: " .. tostring(dealerPed))
+ -- print("DoesEntityExist(dealerPed): " .. tostring(DoesEntityExist(dealerPed)))
+ -- print("NetworkHasControlOfEntity(dealerPed): " .. tostring(NetworkHasControlOfEntity(dealerPed)))
+ local gender = getDealerGenderFromPed(dealerPed)
+ if DoesEntityExist(dealerPed) then
+ -- print("startDealing() - entityExists")
+ -- print("request cardId: " .. tostring(cardData[cardIndex]))
+ nextCard = getCardFromNumber(cardData[cardIndex],true)
+ local nextCardObj = getNewCardFromMachine(nextCard,chairId)
+ AttachEntityToEntity(nextCardObj, dealerPed, GetPedBoneIndex(dealerPed,28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ if chairId <= 1000 then
+ -- print("[blackjack] giving player cards")
+ dealerGiveCards(chairId,genderAnimString,dealerPed,nextCardObj)
+ else
+ -- print("[blackjack] giving dealers cards")
+ dealerGiveSelfCard(genderAnimString,dealerPed,cardIndex,nextCardObj)
+ end
+ DetachEntity(nextCardObj,false,true)
+ if chairId ~= gameId or cardIndex ~= 2 then
+ local soundCardString = "MINIGAME_BJACK_DEALER_" .. tostring(gotCurrentHand)
+ -- print("trying soundString: " .. tostring(soundCardString))
+ PlayAmbientSpeech1(dealerPed,soundCardString,"SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ end
+ --ENTITY::SET_ENTITY_COORDS_NO_OFFSET(Local_198.f_648[iVar6], OBJECT::_GET_OBJECT_OFFSET_FROM_COORDS(func_70(iVar2), vVar8.z, func_377(iVar5, iVar9, 0)), 0, 0, 1);
+ --ENTITY::SET_ENTITY_ROTATION(Local_198.f_648[iVar6], vVar8 + func_376(iVar5, iVar9, 0, func_380(iVar6)), 2, 1);
+ cardQueue = cardIndex -- number of card
+ iVar5 = cardQueue
+ iVar9 = chairId -- <-localChairId 0-3
+ if chairId <= 1000 then
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairId)))
+ tablePosX,tablePosY,tablePosZ = getTableCoords(blackjack_func_368(chairId))
+ cardOffsetX,cardOffsetY,cardOffsetZ = blackjack_func_377(iVar5, getLocalChairIndexFromGlobalChairId(chairId), 0) --iVar9 is the local seat number 0-3
+ else
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(fakeChairIdForDealerTurn)))
+ tablePosX,tablePosY,tablePosZ = getTableCoords(blackjack_func_368(fakeChairIdForDealerTurn))
+ cardOffsetX,cardOffsetY,cardOffsetZ = blackjack_func_377(iVar5, 4, 1)
+ end
+ local cardPos = GetObjectOffsetFromCoords(tablePosX, tablePosY, tablePosZ, vVar8.z, cardOffsetX, cardOffsetY, cardOffsetZ)
+ SetEntityCoordsNoOffset(nextCardObj, cardPos.x, cardPos.y, cardPos.z, 0, 0, 1)
+ -- print("fakeChairIdForDealerTurn",fakeChairIdForDealerTurn)
+ if chairId <= 1000 then
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairId)))
+ cardObjectOffsetRotation = vVar8 + func_376(iVar5, getLocalChairIndexFromGlobalChairId(chairId), 0, false)
+ SetEntityRotation(nextCardObj, cardObjectOffsetRotation.x, cardObjectOffsetRotation.y, cardObjectOffsetRotation.z, 2, 1)
+ else
+ cardObjectOffsetRotation = blackjack_func_398(blackjack_func_368(fakeChairIdForDealerTurn))
+ end
+ -- print("checking betttingInstructional",closestChair,chairId)
+ if closestChair == chairId and sittingAtBlackjackTable then
+ bettingInstructional = setupBlackjackMidBetScaleform("instructional_buttons")
+ end
+ --soundID = GetSoundId()
+ --PlaySoundFromEntity(soundID,"DLC_VW_CHIP_BET_SML_MEDIUM",nextCardObj,"dlc_vw_table_games_sounds", 0, 0)
+ return nextCardObj
+ else
+ -- print("Failed to deal cards, entity doesn't exist or we don't have control")
+ end
+end
+
+function startStandOrHit(gameId,dealerPed,chairId,actuallyPlaying)
+ chairAnimId = getLocalChairIdFromGlobalChairId(chairId)
+ gender = getDealerGenderFromPed(dealerPed)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ -- -- print("dealerPed: " .. tostring(dealerPed))
+ -- -- print("chairAnimId: " .. tostring(chairAnimId))
+ -- -- print("genderAnimString: " .. tostring(genderAnimString))
+ RequestAnimDict("anim_casino_b@amb@casino@games@blackjack@dealer")
+ while not HasAnimDictLoaded("anim_casino_b@amb@casino@games@blackjack@dealer") do
+ Wait(0)
+ end
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle_intro", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ PlayFacialAnim(dealerPed, genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ Wait(0)
+ while IsEntityPlayingAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle_intro") do
+ Wait(10)
+ -- -- print("waiting for anim to end #1")
+ end
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ if actuallyPlaying then
+ waitingForPlayerToHitOrStand = true
+ end
+end
+
+function flipDealerCard(dealerPed,gotCurrentHand,tableId,gameId)
+ cardObj = dealerSecondCardFromGameId[gameId]
+ local cardX,cardY,cardZ = GetEntityCoords(cardObj)
+ local gender = getDealerGenderFromPed(dealerPed)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "check_and_turn_card", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ --PlayFacialAnim(dealerPed, genderAnimString .. "check_and_turn_card_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ while not HasAnimEventFired(dealerPed,-1345695206) do
+ -- print("waiting for -1345695206 to fire")
+ Wait(0)
+ end
+ AttachEntityToEntity(cardObj, dealerPed, GetPedBoneIndex(dealerPed,28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ while not HasAnimEventFired(dealerPed,585557868) do
+ Wait(0)
+ end
+ DetachEntity(cardObj,false,true)
+ if blackjack_func_368(closestChair) == tableId then
+ dealersHand = gotCurrentHand
+ end
+ local soundCardString = "MINIGAME_BJACK_DEALER_" .. tostring(gotCurrentHand)
+ PlayAmbientSpeech1(dealerPed,soundCardString,"SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ SetEntityCoordsNoOffset(cardObj, cardX,cardY,cardZ)
+end
+
+function checkCard(dealerPed,cardObj)
+ local cardX,cardY,cardZ = GetEntityCoords(cardObj)
+ AttachEntityToEntity(cardObj, dealerPed, GetPedBoneIndex(dealerPed,28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ local gender = getDealerGenderFromPed(dealerPed)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "check_card", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ PlayFacialAnim(dealerPed, genderAnimString .. "check_card_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ while not HasAnimEventFired(dealerPed,585557868) do
+ Wait(0)
+ end
+ Wait(100)
+ DetachEntity(cardObj,false,true)
+ SetEntityCoordsNoOffset(cardObj, cardX,cardY,cardZ)
+end
+
+RegisterNetEvent("Blackjack:endStandOrHitPhase")
+AddEventHandler("Blackjack:endStandOrHitPhase",function(chairId,tableId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ waitingForPlayerToHitOrStand = false
+ chairAnimId = getLocalChairIdFromGlobalChairId(chairId)
+ gender = getDealerGenderFromPed(dealerPed)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ -- print("dealer ending anim: " .. "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle_outro")
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle_outro", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ PlayFacialAnim(dealerPed, genderAnimString .. "dealer_focus_player_0" .. chairAnimId .. "_idle_outro_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ end
+end)
+
+RegisterNetEvent("Blackjack:bustBlackjack")
+AddEventHandler("Blackjack:bustBlackjack",function(chairID,tableId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ PlayAmbientSpeech1(dealerPed,"MINIGAME_BJACK_DEALER_PLAYER_BUST","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", "reaction_bad", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ -- print("closestChair:",closestChair)
+ -- print("getLocalChairIdFromGlobalChairId(closestChair):",getLocalChairIdFromGlobalChairId(closestChair))
+ -- print("chairID+1:",chairID)
+ -- print("sittingAtBlackjackTable:",sittingAtBlackjackTable)
+ if chairID == closestChair and sittingAtBlackjackTable then
+ angryIBust()
+ drawCurrentHand = false
+ currentHand = 0
+ dealersHand = 0
+ end
+ end
+end)
+
+RegisterNetEvent("Blackjack:flipDealerCard")
+AddEventHandler("Blackjack:flipDealerCard",function(gotCurrentHand,tableId,gameId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ flipDealerCard(dealerPed,gotCurrentHand,tableId,gameId)
+ end
+end)
+
+RegisterNetEvent("Blackjack:dealerBusts")
+AddEventHandler("Blackjack:dealerBusts",function(tableId)
+ if closeToCasino then
+ dealerPed = getDealerFromTableId(tableId)
+ PlayAmbientSpeech1(dealerPed,"MINIGAME_DEALER_BUSTS","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ end
+end)
+
+RegisterNetEvent("Blackjack:blackjackLose")
+AddEventHandler("Blackjack:blackjackLose",function(tableId)
+ if closeToCasino then
+ blackjackGameInProgress = false
+ dealerPed = getDealerFromTableId(tableId)
+ PlayAmbientSpeech1(dealerPed,"MINIGAME_DEALER_WINS","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", "reaction_bad", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ angryILost()
+ canExitBlackjack = true
+ PlaySoundFrontend(-1, "CHALLENGE_UNLOCKED", "HUD_AWARDS", 1)
+ drawCurrentHand = false
+ currentHand = 0
+ dealersHand = 0
+ end
+end)
+
+RegisterNetEvent("Blackjack:blackjackPush")
+AddEventHandler("Blackjack:blackjackPush",function(tableId)
+ if closeToCasino then
+ blackjackGameInProgress = false
+ dealerPed = getDealerFromTableId(tableId)
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", "reaction_impartial", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ annoyedIPushed()
+ canExitBlackjack = true
+ PlaySoundFrontend(-1, "ERROR", "HUD_AMMO_SHOP_SOUNDSET", 1)
+ drawCurrentHand = false
+ currentHand = 0
+ dealersHand = 0
+ end
+end)
+
+RegisterNetEvent("Blackjack:blackjackWin")
+AddEventHandler("Blackjack:blackjackWin",function(tableId)
+ if closeToCasino then
+ blackjackGameInProgress = false
+ dealerPed = getDealerFromTableId(tableId)
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", "reaction_good", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ happyIWon()
+ canExitBlackjack = true
+ PlaySoundFrontend(-1, "TENNIS_MATCH_POINT", "HUD_AWARDS", 1)
+ drawCurrentHand = false
+ currentHand = 0
+ dealersHand = 0
+ end
+end)
+
+RegisterNetEvent("Blackjack:chipsCleanup")
+AddEventHandler("Blackjack:chipsCleanup",function(chairId,tableId)
+ if closeToCasino then
+ if string.sub(chairId, -5) ~= "chips" then
+ dealerPed = getDealerFromTableId(tableId)
+ local gender = getDealerGenderFromPed(dealerPed)
+ if gender == "male" then
+ genderAnimString = ""
+ end
+ if gender == "female" then
+ genderAnimString = "female_"
+ end
+ localChairId = getLocalChairIdFromGlobalChairId(chairId)
+ if chairId > 99 then --if "chairId" is above 99 its not a chair Id, its the gameId so its the dealers turn
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "retrieve_own_cards_and_remove", 3.0, 1.0, -1, 2, 0, 0, 0, 0)
+ PlayFacialAnim(dealerPed, genderAnimString .. "retrieve_own_cards_and_remove_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ else
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", genderAnimString .. "retrieve_cards_player_0" .. tostring(localChairId), 3.0, 1.0, -1, 2, 0, 0, 0, 0)
+ PlayFacialAnim(dealerPed, genderAnimString .. "retrieve_cards_player_0" .. tostring(localChairId).."_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ end
+ while not HasAnimEventFired(dealerPed,-1345695206) do
+ -- print("waiting for -1345695206 to fire")
+ Wait(0)
+ end
+ for k,v in pairs(cardObjects) do
+ if k == chairId then
+ for k2,v2 in pairs(v) do
+ -- print("attach entity chairId",k,"objkey",k2," objvalue",v2)
+ AttachEntityToEntity(v2, dealerPed, GetPedBoneIndex(dealerPed,28422), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 1, 2, 1)
+ end
+ end
+ end
+ while not HasAnimEventFired(dealerPed,585557868) do
+ -- print("waiting for 585557868 to fire")
+ Wait(0)
+ end
+ for k,v in pairs(cardObjects) do
+ if k == chairId then
+ for k2,v2 in pairs(v) do
+ DeleteEntity(v2)
+ --v[k2] = nil
+ end
+ end
+ end
+ else
+ for k,v in pairs(cardObjects) do
+ if k == chairId then
+ for k2,v2 in pairs(v) do
+ DeleteEntity(v2)
+ --v[k2] = nil
+ end
+ end
+ end
+ end
+ end
+end)
+
+RegisterNetEvent("Blackjack:chipsCleanupNoAnim")
+AddEventHandler("Blackjack:chipsCleanupNoAnim",function(chairId,tableId)
+ for k,v in pairs(cardObjects) do
+ if k == chairId then
+ for k2,v2 in pairs(v) do
+ DeleteEntity(v2)
+ end
+ end
+ end
+end)
+
+function betChipsForNextHand(chipsAmount,chipsProp,something,chairID,someBool,zOffset)
+ -- Local_198.f_538[func_379(iVar2, iVar9, 0)] = OBJECT::CREATE_OBJECT_NO_OFFSET(func_375(iVar14, bVar4), OBJECT::_GET_OBJECT_OFFSET_FROM_COORDS(func_70(iVar2), vVar8.z, func_374(iVar14, 0, iVar9, bVar4)), 0, false, 1);
+ -- ENTITY::SET_ENTITY_COORDS_NO_OFFSET(Local_198.f_538[func_379(iVar2, iVar9, 0)],
+ --^-> OBJECT::_GET_OBJECT_OFFSET_FROM_COORDS(func_70(iVar2), vVar8.z, func_374(iVar14, 0, iVar9, bVar4)), 0, 0, 1);
+ -- ENTITY::SET_ENTITY_ROTATION(Local_198.f_538[func_379(iVar2, iVar9, 0)], vVar8 + func_373(iVar14, 0, iVar9, bVar4), 2, 1);
+ -- if (!MISC::IS_STRING_NULL_OR_EMPTY(func_372(iVar14)))
+ -- {
+ -- AUDIO::PLAY_SOUND_FROM_ENTITY(-1, func_372(iVar14), Local_198.f_538[func_379(iVar2, iVar9, 0)], "dlc_vw_table_games_sounds", 0, 0);
+ -- }
+ -- print("betChipsForNextHand",chairID)
+ -- print("betChipsForNextHand_local",getLocalChairIndexFromGlobalChairId(chairID))
+ RequestModel(chipsProp)
+ while not HasModelLoaded(chipsProp) do
+ Wait(0)
+ -- print("[CMG Casino] Stuck requesting model: " .. tostring(chipsProp))
+ RequestModel(chipsProp)
+ end
+ vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairID)))
+ local tablePosX,tablePosY,tablePosZ = getTableCoords(blackjack_func_368(chairID))
+ local chipsVector = blackjack_func_374(chipsAmount,something,getLocalChairIndexFromGlobalChairId(chairID),someBool)
+ local chipsOffset = GetObjectOffsetFromCoords(tablePosX,tablePosY,tablePosZ, vVar8.z, chipsVector.x, chipsVector.y, chipsVector.z)
+
+ local chipsObj = CreateObjectNoOffset(GetHashKey(chipsProp), chipsOffset.x,chipsOffset.y,chipsOffset.z, false, false, 1)
+ if cardObjects[tostring(chairID) .. "chips"] ~= nil then
+ table.insert(cardObjects[tostring(chairID) .. "chips"],chipsObj)
+ else
+ cardObjects[tostring(chairID) .. "chips"] = {}
+ table.insert(cardObjects[tostring(chairID) .. "chips"],chipsObj)
+ end
+ SetEntityCoordsNoOffset(chipsObj, chipsOffset.x, chipsOffset.y, chipsOffset.z+zOffset, 0, 0, 1)
+ local chipOffsetRotation = blackjack_func_373(chipsAmount,0,getLocalChairIndexFromGlobalChairId(chairID),someBool)
+ SetEntityRotation(chipsObj,vVar8 + chipOffsetRotation, 2, 1)
+
+ -- print("betChips DEBUG")
+ -- print("==============")
+ -- print("zOffset: " .. tostring(zOffset))
+ -- print("vVar8: " .. tostring(vVar8))
+ -- print("tablePosX: " .. tostring(tablePosX))
+ -- print("tablePosY: " .. tostring(tablePosY))
+ -- print("tablePosZ: " .. tostring(tablePosZ))
+ -- print("chipsVector: " .. tostring(chipsVector))
+ -- print("chipsOffset: " .. tostring(chipsOffset))
+ -- print("chipsObj: " .. tostring(chipsObj))
+ -- print("chipOffsetRotation: " .. tostring(chipOffsetRotation))
+end
+
+function getDealerGenderFromPed(dealerPed)
+ maleCasinoDealer = GetHashKey("S_M_Y_Casino_01")
+ femaleCasinoDealer = GetHashKey("S_F_Y_Casino_01")
+
+ if GetEntityModel(dealerPed) == maleCasinoDealer then
+ return "male"
+ end
+ return "female"
+end
+
+function getNewCardFromMachine(nextCard,chairId,gameId)
+ -- print("getNewCardFromMachine:",chairId)
+ RequestModel(nextCard)
+ while not HasModelLoaded(nextCard) do
+ Wait(0)
+ RequestModel(nextCard)
+ end
+ nextCardHash = GetHashKey(nextCard)
+ local cardObjectOffset = blackjack_func_399(blackjack_func_368(chairId))
+ local nextCardObj = CreateObjectNoOffset(nextCardHash, cardObjectOffset.x, cardObjectOffset.y, cardObjectOffset.z, false, false, 1)
+ if cardObjects[chairId] ~= nil then
+ if gameId then
+ -- print("inserting chipsobjects with key: " .. tostring(gameId))
+ table.insert(cardObjects[gameId],nextCardObj)
+ else
+ -- print("inserting chipsobjects with key: " .. tostring(chairId))
+ table.insert(cardObjects[chairId],nextCardObj)
+ end
+ else
+ cardObjects[chairId] = {}
+ if gameId then
+ -- print("inserting chipsobjects with key: " .. tostring(gameId))
+ table.insert(cardObjects[gameId],nextCardObj)
+ else
+ -- print("inserting chipsobjects with key: " .. tostring(chairId))
+ table.insert(cardObjects[chairId],nextCardObj)
+ end
+ end
+ SetEntityVisible(nextCardObj,false)
+ SetModelAsNoLongerNeeded(nextCardHash)
+ local cardObjectOffsetRotation = blackjack_func_398(blackjack_func_368(chairId))
+ SetEntityCoordsNoOffset(nextCardObj, cardObjectOffset.x, cardObjectOffset.y, cardObjectOffset.z, 0, 0, 1)
+ --vVar8 = vector3(0.0, 0.0, getTableHeading(blackjack_func_368(chairId)))
+
+ --if chairId > 99 then
+ -- cardObjectOffsetRotation = vVar8 + func_376(iVar5, iVar9, 0, false)
+ --else
+ -- cardObjectOffsetRotation = blackjack_func_398(blackjack_func_368(chairId))
+ --end
+ -- print("cardObjectOffsetRotation.x: " .. tostring(cardObjectOffsetRotation.x))
+ -- print("cardObjectOffsetRotation.y: " .. tostring(cardObjectOffsetRotation.y))
+ -- print("cardObjectOffsetRotation.z: " .. tostring(cardObjectOffsetRotation.z))
+ SetEntityRotation(nextCardObj, cardObjectOffsetRotation.x, cardObjectOffsetRotation.y, cardObjectOffsetRotation.z, 2, 1)
+ --FreezeEntityPosition(nextCardObj, true)
+ return nextCardObj
+end
+
+function dealerGiveCards(chairId,gender,dealerPed,cardObj) --func_36
+ local seatNumber = tostring(getLocalChairIdFromGlobalChairId(chairId))
+ --local currentScene = NetworkCreateSynchronisedScene(x, y, z, 0.0, 0.0, zRot, 2, 1, 0, 1065353216, 0, 1065353216)
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", gender .. "deal_card_player_0" .. seatNumber, 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ PlayFacialAnim(dealerPed,"deal_card_player_0"..seatNumber.."_facial")
+ --NetworkStartSynchronisedScene(currentScene)
+ --func_15(func_21(iParam0, Local_188.f_899[iVar2 /*9*/].f_8, 0, 0), Local_188.f_1[iParam0 /*211*/][Local_188.f_1[iParam0 /*211*/].f_209], 0, 0);
+ Wait(300)
+ SetEntityVisible(cardObj,true)
+ while not HasAnimEventFired(dealerPed, 585557868) do
+ Wait(0)
+ -- print("waiting for anim event to fire.. for dealergivecards")
+ end
+end
+
+function dealerGiveSelfCard(gender,dealerPed,cardIndex,cardObj) --func_36
+ if cardIndex == 1 then
+ cardAnim = "deal_card_self_second_card"
+ elseif cardIndex == 2 then
+ cardAnim = "deal_card_self"
+ else
+ cardAnim = "deal_card_self_card_10"
+ end
+ TaskPlayAnim(dealerPed, "anim_casino_b@amb@casino@games@blackjack@dealer", gender .. cardAnim, 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+ PlayFacialAnim(dealerPed, gender .. cardAnim.."_facial", "anim_casino_b@amb@casino@games@blackjack@dealer")
+ Wait(300)
+ SetEntityVisible(cardObj,true)
+ while not HasAnimEventFired(dealerPed, 585557868) do
+ Wait(0)
+ -- print("waiting for anim event to fire.. for dealerGiveSelfCard")
+ end
+ Wait(100)
+end
+
+local chipsProps = {
+ "vw_prop_chip_10dollar_x1",
+ "vw_prop_chip_50dollar_x1",
+ "vw_prop_chip_100dollar_x1",
+ "vw_prop_chip_50dollar_st",
+ "vw_prop_chip_100dollar_st",
+ "vw_prop_chip_500dollar_x1",
+ "vw_prop_chip_1kdollar_x1",
+ "vw_prop_chip_500dollar_st",
+ "vw_prop_chip_5kdollar_x1",
+ "vw_prop_chip_1kdollar_st",
+ "vw_prop_chip_10kdollar_x1",
+ "vw_prop_chip_5kdollar_st",
+ "vw_prop_chip_10kdollar_st",
+ "vw_prop_plaq_5kdollar_x1",
+ "vw_prop_plaq_5kdollar_st",
+ "vw_prop_plaq_10kdollar_x1",
+ "vw_prop_plaq_10kdollar_st",
+ "vw_prop_vw_chips_pile_01a",
+ "vw_prop_vw_chips_pile_02a",
+ "vw_prop_vw_chips_pile_03a",
+ "vw_prop_vw_coin_01a",
+}
+
+function declineCard()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@blackjack@player", "decline_card_001", 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(2000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function requestCard()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@blackjack@player", "request_card", 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(2000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function putBetOnTable()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@blackjack@player", getAnimNameFromBet(100), 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(5000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function angryIBust()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@shared@player@", "reaction_terrible_var_01", 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(5000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function angryILost()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@shared@player@", "reaction_bad_var_01", 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(5000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function annoyedIPushed()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@shared@player@", "reaction_impartial_var_01", 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(5000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function happyIWon()
+ shouldForceIdleCardGames = false
+ local chairPos = blackjack_func_348(closestChair)
+ local chairRot = blackjack_func_215(closestChair)
+ local currentScene = NetworkCreateSynchronisedScene(chairPos.x, chairPos.y, chairPos.z, chairRot.x, chairRot.y, chairRot.z, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, "anim_casino_b@amb@casino@games@shared@player@", "reaction_good_var_01", 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ SetTimeout(5000,function()
+ shouldForceIdleCardGames = true
+ end)
+end
+
+function blackjack_func_398(iParam0)
+ local vVar0 = vector3(0.0, 164.52, 11.5)
+ return vector3(getTableHeading(iParam0), 0.0, 0.0) + vVar0;
+end
+
+function blackjack_func_399(iParam0) --iParam0 is table ID?
+ local vVar0 = vector3(0.526, 0.571, 0.963)
+ -- print("func_399 iParam0",iParam0)
+ local x,y,z = getTableCoords(iParam0)
+ return GetObjectOffsetFromCoords(x, y, z, getTableHeading(iParam0), vVar0.x, vVar0.y, vVar0.z)
+end
+
+
+function ensureCardModelsLoaded()
+ cardNum = 0;
+ while cardNum < 52 do
+ iVar1 = cardNum + 1
+ local Local_198f_236 = 1 --assuming 1 cant find it equal anything else :/
+ iVar2 = getCardFromNumber(iVar1, Local_198f_236)
+ if not HasModelLoaded(iVar2) then
+ RequestModel(iVar2)
+ while not HasModelLoaded(iVar2) do
+ Wait(0)
+ end
+ end
+ cardNum = cardNum + 1
+ end
+end
+
+
+function blackjack_func_204(iParam0, iParam1, bParam2) --returns vector
+ if bParam2 then
+ return vector3(getTableHeading(iParam1), 0.0, 0.0) + vector3(0, 0.061, -59.1316);
+ else
+ vVar0 = blackjack_func_215(iParam0)
+ return vector3(vVar0.z, 0.0, 0.0) + vector3(-87.48, 0, -60.84);
+ end
+ return 0.0, 0.0, 0.0
+end
+
+function blackjack_func_205(iParam0, iParam1, bParam2) --returns Vector
+ if bParam2 then
+ --return OBJECT::_GET_OBJECT_OFFSET_FROM_COORDS(func_70(iParam1), func_69(iParam1), -0.0094f, -0.0611f, 1.5098f);
+ return GetObjectOffsetFromCoords(getTableCoords(iParam1), getTableHeading(iParam1),-0.0094, -0.0611, 1.5098)
+ else
+ --vVar0 = { func_215(iParam0) };
+ --return OBJECT::_GET_OBJECT_OFFSET_FROM_COORDS(func_348(iParam0), vVar0.z, 0.245f, 0f, 1.415f);
+ vVar0 = blackjack_func_215(iParam0)
+ return GetObjectOffsetFromCoords(blackjack_func_348(iParam0), vVar0.z,0.245, 0.0, 1.415)
+ end
+ return 0.0, 0.0, 0.0
+end
+
+function blackjack_func_216(iParam0, iParam1)
+ local goToVector = blackjack_func_348(iParam0)
+ local xRot,yRot,zRot = blackjack_func_215(iParam0)
+ vVar0 = GetAnimInitialOffsetRotation("anim_casino_b@amb@casino@games@shared@player@", blackjack_func_213(iParam1), goToVector.x, goToVector.y, goToVector.z, xRot, yRot, zRot, 0.01, 2)
+ return vVar0.z
+end
+
+function blackjack_func_217(iParam0, vParam1, bParam2)
+ local vVar0 = {}
+
+ if not IsEntityDead(iParam0,0) then
+ vVar0 = GetEntityCoords(iParam0,1)
+ else
+ vVar0 = GetEntityCoords(iParam0,0)
+ end
+ return #(vVar0-vParam1)
+end
+
+function blackjack_func_218(iParam0, iParam1) --//param0 is 0-3 && param1 is 0-15?
+ local goToVector = blackjack_func_348(iParam0)
+ local xRot,yRot,zRot = blackjack_func_215(iParam0)
+ vVar0 = GetAnimInitialOffsetPosition("anim_casino_b@amb@casino@games@shared@player@", blackjack_func_213(iParam1), goToVector.x, goToVector.y, goToVector.z, xRot, yRot, zRot, 0.01, 2)
+ return vVar0
+end
+
+function blackjack_func_213(sitAnimID)
+ if sitAnimID == 0 then
+ return "sit_enter_left"
+ elseif sitAnimID == 1 then
+ return "sit_enter_left_side"
+ elseif sitAnimID == 2 then
+ return "sit_enter_right_side"
+ end
+ return "sit_enter_left"
+end
+
+function getInverseChairId(chairId)
+ if chairId == 0 then return 3 end
+ if chairId == 1 then return 2 end
+ if chairId == 2 then return 1 end
+ if chairId == 3 then return 0 end
+end
+
+function blackjack_func_348(iParam0) --GetVectorFromChairId
+ if iParam0 == -1 then
+ return vector3(0.0,0.0,0.0)
+ end
+ local blackjackTableObj
+ local tableId = blackjack_func_368(iParam0)
+ local x,y,z = getTableCoords(tableId)
+ blackjackTableObj = GetClosestObjectOfType(x, y, z, 1.0, cfg.blackjackTables[tableId].prop, 0, 0, 0)
+
+ if DoesEntityExist(blackjackTableObj) and DoesEntityHaveDrawable(blackjackTableObj) then
+ local localChairId = getLocalChairIndexFromGlobalChairId(iParam0)
+ -- -- print("localchairId was",localChairId)
+ localChairId = getInverseChairId(localChairId) + 1
+ -- -- print("localchairId is now",localChairId)
+ return GetWorldPositionOfEntityBone_2(blackjackTableObj,GetEntityBoneIndexByName(blackjackTableObj, "Chair_Base_0"..localChairId))
+ end
+ return vector3(0.0,0.0,0.0)
+end
+
+function blackjack_func_215(iParam0)
+ if iParam0 == -1 then
+ return vector3(0.0,0.0,0.0)
+ end
+ local blackjackTableObj
+ local tableId = blackjack_func_368(iParam0)
+ local x,y,z = getTableCoords(tableId)
+ blackjackTableObj = GetClosestObjectOfType(x, y, z, 1.0, cfg.blackjackTables[tableId].prop, 0, 0, 0)
+ if DoesEntityExist(blackjackTableObj) and DoesEntityHaveDrawable(blackjackTableObj) then
+ local localChairId = getLocalChairIndexFromGlobalChairId(iParam0)
+ -- -- print("localchairId was",localChairId)
+ localChairId = getInverseChairId(localChairId) + 1
+ -- -- print("localchairId is now",localChairId)
+ return GetWorldRotationOfEntityBone(blackjackTableObj,GetEntityBoneIndexByName(blackjackTableObj, "Chair_Base_0"..localChairId))
+ else
+ return vector3(0.0,0.0,0.0)
+ end
+end
+
+function blackjack_func_368(chairId) --returns tableID based on chairID
+ local tableId = -1
+ for i=0,chairId,4 do
+ tableId = tableId + 1
+ end
+ return tableId
+end
+
+function getLocalChairIdFromGlobalChairId(globalChairId) --returns tableID based on chairID
+ if globalChairId ~= -1 then
+ return (globalChairId % 4) + 1
+ else
+ return 100
+ end
+end
+
+function getLocalChairIndexFromGlobalChairId(globalChairId) --returns tableID based on chairID
+ if globalChairId ~= -1 then
+ return (globalChairId % 4)
+ else
+ return 100
+ end
+end
+
+function getTableHeading(id) --previously blackjack_func_69
+ if cfg.blackjackTables[id] ~= nil then
+ return cfg.blackjackTables[id].tableHeading
+ else
+ return 0.0 --for when tableId = gameId (i.e for dealer)
+ end
+end
+
+function getTableCoords(id) --previously blackjack_func_70
+ if cfg.blackjackTables[id] ~= nil then
+ return cfg.blackjackTables[id].tablePos.x,cfg.blackjackTables[id].tablePos.y,cfg.blackjackTables[id].tablePos.z
+ else
+ return 0.0,0.0,0.0 --for when tableId = gameId (i.e for dealer)
+ end
+end
+
+function getCardFromNumber(iParam0, bParam1)
+ if bParam1 then
+ if iParam0 == 1 then
+ return "vw_prop_vw_club_char_a_a"
+ elseif iParam0 == 2 then
+ return "vw_prop_vw_club_char_02a"
+ elseif iParam0 == 3 then
+ return "vw_prop_vw_club_char_03a"
+ elseif iParam0 == 4 then
+ return "vw_prop_vw_club_char_04a"
+ elseif iParam0 == 5 then
+ return "vw_prop_vw_club_char_05a"
+ elseif iParam0 == 6 then
+ return "vw_prop_vw_club_char_06a"
+ elseif iParam0 == 7 then
+ return "vw_prop_vw_club_char_07a"
+ elseif iParam0 == 8 then
+ return "vw_prop_vw_club_char_08a"
+ elseif iParam0 == 9 then
+ return "vw_prop_vw_club_char_09a"
+ elseif iParam0 == 10 then
+ return "vw_prop_vw_club_char_10a"
+ elseif iParam0 == 11 then
+ return "vw_prop_vw_club_char_j_a"
+ elseif iParam0 == 12 then
+ return "vw_prop_vw_club_char_q_a"
+ elseif iParam0 == 13 then
+ return "vw_prop_vw_club_char_k_a"
+ elseif iParam0 == 14 then
+ return "vw_prop_vw_dia_char_a_a"
+ elseif iParam0 == 15 then
+ return "vw_prop_vw_dia_char_02a"
+ elseif iParam0 == 16 then
+ return "vw_prop_vw_dia_char_03a"
+ elseif iParam0 == 17 then
+ return "vw_prop_vw_dia_char_04a"
+ elseif iParam0 == 18 then
+ return "vw_prop_vw_dia_char_05a"
+ elseif iParam0 == 19 then
+ return "vw_prop_vw_dia_char_06a"
+ elseif iParam0 == 20 then
+ return "vw_prop_vw_dia_char_07a"
+ elseif iParam0 == 21 then
+ return "vw_prop_vw_dia_char_08a"
+ elseif iParam0 == 22 then
+ return "vw_prop_vw_dia_char_09a"
+ elseif iParam0 == 23 then
+ return "vw_prop_vw_dia_char_10a"
+ elseif iParam0 == 24 then
+ return "vw_prop_vw_dia_char_j_a"
+ elseif iParam0 == 25 then
+ return "vw_prop_vw_dia_char_q_a"
+ elseif iParam0 == 26 then
+ return "vw_prop_vw_dia_char_k_a"
+ elseif iParam0 == 27 then
+ return "vw_prop_vw_hrt_char_a_a"
+ elseif iParam0 == 28 then
+ return "vw_prop_vw_hrt_char_02a"
+ elseif iParam0 == 29 then
+ return "vw_prop_vw_hrt_char_03a"
+ elseif iParam0 == 30 then
+ return "vw_prop_vw_hrt_char_04a"
+ elseif iParam0 == 31 then
+ return "vw_prop_vw_hrt_char_05a"
+ elseif iParam0 == 32 then
+ return "vw_prop_vw_hrt_char_06a"
+ elseif iParam0 == 33 then
+ return "vw_prop_vw_hrt_char_07a"
+ elseif iParam0 == 34 then
+ return "vw_prop_vw_hrt_char_08a"
+ elseif iParam0 == 35 then
+ return "vw_prop_vw_hrt_char_09a"
+ elseif iParam0 == 36 then
+ return "vw_prop_vw_hrt_char_10a"
+ elseif iParam0 == 37 then
+ return "vw_prop_vw_hrt_char_j_a"
+ elseif iParam0 == 38 then
+ return "vw_prop_vw_hrt_char_q_a"
+ elseif iParam0 == 39 then
+ return "vw_prop_vw_hrt_char_k_a"
+ elseif iParam0 == 40 then
+ return "vw_prop_vw_spd_char_a_a"
+ elseif iParam0 == 41 then
+ return "vw_prop_vw_spd_char_02a"
+ elseif iParam0 == 42 then
+ return "vw_prop_vw_spd_char_03a"
+ elseif iParam0 == 43 then
+ return "vw_prop_vw_spd_char_04a"
+ elseif iParam0 == 44 then
+ return "vw_prop_vw_spd_char_05a"
+ elseif iParam0 == 45 then
+ return "vw_prop_vw_spd_char_06a"
+ elseif iParam0 == 46 then
+ return "vw_prop_vw_spd_char_07a"
+ elseif iParam0 == 47 then
+ return "vw_prop_vw_spd_char_08a"
+ elseif iParam0 == 48 then
+ return "vw_prop_vw_spd_char_09a"
+ elseif iParam0 == 49 then
+ return "vw_prop_vw_spd_char_10a"
+ elseif iParam0 == 50 then
+ return "vw_prop_vw_spd_char_j_a"
+ elseif iParam0 == 51 then
+ return "vw_prop_vw_spd_char_q_a"
+ elseif iParam0 == 52 then
+ return "vw_prop_vw_spd_char_k_a"
+ end
+ else
+ if iParam0 == 1 then
+ return "vw_prop_cas_card_club_ace"
+ elseif iParam0 == 2 then
+ return "vw_prop_cas_card_club_02"
+ elseif iParam0 == 3 then
+ return "vw_prop_cas_card_club_03"
+ elseif iParam0 == 4 then
+ return "vw_prop_cas_card_club_04"
+ elseif iParam0 == 5 then
+ return "vw_prop_cas_card_club_05"
+ elseif iParam0 == 6 then
+ return "vw_prop_cas_card_club_06"
+ elseif iParam0 == 7 then
+ return "vw_prop_cas_card_club_07"
+ elseif iParam0 == 8 then
+ return "vw_prop_cas_card_club_08"
+ elseif iParam0 == 9 then
+ return "vw_prop_cas_card_club_09"
+ elseif iParam0 == 10 then
+ return "vw_prop_cas_card_club_10"
+ elseif iParam0 == 11 then
+ return "vw_prop_cas_card_club_jack"
+ elseif iParam0 == 12 then
+ return "vw_prop_cas_card_club_queen"
+ elseif iParam0 == 13 then
+ return "vw_prop_cas_card_club_king"
+ elseif iParam0 == 14 then
+ return "vw_prop_cas_card_dia_ace"
+ elseif iParam0 == 15 then
+ return "vw_prop_cas_card_dia_02"
+ elseif iParam0 == 16 then
+ return "vw_prop_cas_card_dia_03"
+ elseif iParam0 == 17 then
+ return "vw_prop_cas_card_dia_04"
+ elseif iParam0 == 18 then
+ return "vw_prop_cas_card_dia_05"
+ elseif iParam0 == 19 then
+ return "vw_prop_cas_card_dia_06"
+ elseif iParam0 == 20 then
+ return "vw_prop_cas_card_dia_07"
+ elseif iParam0 == 21 then
+ return "vw_prop_cas_card_dia_08"
+ elseif iParam0 == 22 then
+ return "vw_prop_cas_card_dia_09"
+ elseif iParam0 == 23 then
+ return "vw_prop_cas_card_dia_10"
+ elseif iParam0 == 24 then
+ return "vw_prop_cas_card_dia_jack"
+ elseif iParam0 == 25 then
+ return "vw_prop_cas_card_dia_queen"
+ elseif iParam0 == 26 then
+ return "vw_prop_cas_card_dia_king"
+ elseif iParam0 == 27 then
+ return "vw_prop_cas_card_hrt_ace"
+ elseif iParam0 == 28 then
+ return "vw_prop_cas_card_hrt_02"
+ elseif iParam0 == 29 then
+ return "vw_prop_cas_card_hrt_03"
+ elseif iParam0 == 30 then
+ return "vw_prop_cas_card_hrt_04"
+ elseif iParam0 == 31 then
+ return "vw_prop_cas_card_hrt_05"
+ elseif iParam0 == 32 then
+ return "vw_prop_cas_card_hrt_06"
+ elseif iParam0 == 33 then
+ return "vw_prop_cas_card_hrt_07"
+ elseif iParam0 == 34 then
+ return "vw_prop_cas_card_hrt_08"
+ elseif iParam0 == 35 then
+ return "vw_prop_cas_card_hrt_09"
+ elseif iParam0 == 36 then
+ return "vw_prop_cas_card_hrt_10"
+ elseif iParam0 == 37 then
+ return "vw_prop_cas_card_hrt_jack"
+ elseif iParam0 == 38 then
+ return "vw_prop_cas_card_hrt_queen"
+ elseif iParam0 == 39 then
+ return "vw_prop_cas_card_hrt_king"
+ elseif iParam0 == 40 then
+ return "vw_prop_cas_card_spd_ace"
+ elseif iParam0 == 41 then
+ return "vw_prop_cas_card_spd_02"
+ elseif iParam0 == 42 then
+ return "vw_prop_cas_card_spd_03"
+ elseif iParam0 == 43 then
+ return "vw_prop_cas_card_spd_04"
+ elseif iParam0 == 44 then
+ return "vw_prop_cas_card_spd_05"
+ elseif iParam0 == 45 then
+ return "vw_prop_cas_card_spd_06"
+ elseif iParam0 == 46 then
+ return "vw_prop_cas_card_spd_07"
+ elseif iParam0 == 47 then
+ return "vw_prop_cas_card_spd_08"
+ elseif iParam0 == 48 then
+ return "vw_prop_cas_card_spd_09"
+ elseif iParam0 == 49 then
+ return "vw_prop_cas_card_spd_10"
+ elseif iParam0 == 50 then
+ return "vw_prop_cas_card_spd_jack"
+ elseif iParam0 == 51 then
+ return "vw_prop_cas_card_spd_queen"
+ elseif iParam0 == 52 then
+ return "vw_prop_cas_card_spd_king"
+ end
+ end
+ if bParam1 then
+ return "vw_prop_vw_jo_char_01a"
+ end
+ return "vw_prop_casino_cards_single"
+end
+
+function getAnimNameFromBet(betAmount)
+ --TODO sort this out once bet amounts decided
+ -- return "place_bet_small";
+ -- return "place_bet_small_alt1";
+ -- return "place_bet_small_alt2";
+ -- return "place_bet_small_alt3";
+ -- return "place_bet_large";
+ -- return "place_bet_double_down";
+ -- return "place_bet_small_player_02";
+ -- return "place_bet_large_player_02";
+ -- return "place_bet_double_down_player_02";
+ -- return "place_bet_small_split";
+ -- return "place_bet_large_split";
+
+ --default for now
+ return "place_bet_small"
+end
+
+
+function blackjack_func_377(iParam0, iParam1, bParam2) --iVar5, iVar9, 0
+ -- print("blackjack_func_377")
+ -- print("iParam0: " .. tostring(iParam0))
+ -- print("iParam1: " .. tostring(iParam1))
+ -- print("bParam2: " .. tostring(bParam2))
+ if bParam2 == 0 then
+ -- print("first check [OK]")
+ -- print("iParam1: " .. tostring(iParam1))
+ -- print("iParam0: " .. tostring(iParam0))
+ if iParam1 == 0 then
+ if iParam0 == 0 then
+ return 0.5737, 0.2376, 0.948025
+ elseif iParam0 == 1 then
+ return 0.562975, 0.2523, 0.94875
+ elseif iParam0 == 2 then
+ return 0.553875, 0.266325, 0.94955
+ elseif iParam0 == 3 then
+ return 0.5459, 0.282075, 0.9501
+ elseif iParam0 == 4 then
+ return 0.536125, 0.29645, 0.95085
+ elseif iParam0 == 5 then
+ return 0.524975, 0.30975, 0.9516
+ elseif iParam0 == 6 then
+ return 0.515775, 0.325325, 0.95235
+ end
+ elseif iParam1 == 1 then
+ if iParam0 == 0 then
+ return 0.2325, -0.1082, 0.94805
+ elseif iParam0 == 1 then
+ return 0.23645, -0.0918, 0.949
+ elseif iParam0 == 2 then
+ return 0.2401, -0.074475, 0.950225
+ elseif iParam0 == 3 then
+ return 0.244625, -0.057675, 0.951125
+ elseif iParam0 == 4 then
+ return 0.249675, -0.041475, 0.95205
+ elseif iParam0 == 5 then
+ return 0.257575, -0.0256, 0.9532
+ elseif iParam0 == 6 then
+ return 0.2601, -0.008175, 0.954375
+ end
+ elseif iParam1 == 2 then
+ if iParam0 == 0 then
+ return -0.2359, -0.1091, 0.9483
+ elseif iParam0 == 1 then
+ return -0.221025, -0.100675, 0.949
+ elseif iParam0 == 2 then
+ return -0.20625, -0.092875, 0.949725
+ elseif iParam0 == 3 then
+ return -0.193225, -0.07985, 0.950325
+ elseif iParam0 == 4 then
+ return -0.1776, -0.072, 0.951025
+ elseif iParam0 == 5 then
+ return -0.165, -0.060025, 0.951825
+ elseif iParam0 == 6 then
+ return -0.14895, -0.05155, 0.95255
+ end
+ elseif iParam1 == 3 then
+ if iParam0 == 0 then
+ return -0.5765, 0.2229, 0.9482
+ elseif iParam0 == 1 then
+ return -0.558925, 0.2197, 0.949175
+ elseif iParam0 == 2 then
+ return -0.5425, 0.213025, 0.9499
+ elseif iParam0 == 3 then
+ return -0.525925, 0.21105, 0.95095
+ elseif iParam0 == 4 then
+ return -0.509475, 0.20535, 0.9519
+ elseif iParam0 == 5 then
+ return -0.491775, 0.204075, 0.952825
+ elseif iParam0 == 6 then
+ return -0.4752, 0.197525, 0.9543
+ end
+ end
+ else
+ if iParam1 == 0 then
+ if iParam0 == 0 then
+ return 0.6083, 0.3523, 0.94795
+ elseif iParam0 == 1 then
+ return 0.598475, 0.366475, 0.948925
+ elseif iParam0 == 2 then
+ return 0.589525, 0.3807, 0.94975
+ elseif iParam0 == 3 then
+ return 0.58045, 0.39435, 0.950375
+ elseif iParam0 == 4 then
+ return 0.571975, 0.4092, 0.951075
+ elseif iParam0 == 5 then
+ return 0.5614, 0.4237, 0.951775
+ elseif iParam0 == 6 then
+ return 0.554325, 0.4402, 0.952525
+ end
+ elseif iParam1 == 1 then
+ if iParam0 == 0 then
+ return 0.3431, -0.0527, 0.94855
+ elseif iParam0 == 1 then
+ return 0.348575, -0.0348, 0.949425
+ elseif iParam0 == 2 then
+ return 0.35465, -0.018825, 0.9502
+ elseif iParam0 == 3 then
+ return 0.3581, -0.001625, 0.95115
+ elseif iParam0 == 4 then
+ return 0.36515, 0.015275, 0.952075
+ elseif iParam0 == 5 then
+ return 0.368525, 0.032475, 0.95335
+ elseif iParam0 == 6 then
+ return 0.373275, 0.0506, 0.9543
+ end
+ elseif iParam1 == 2 then
+ if iParam0 == 0 then
+ return -0.116, -0.1501, 0.947875
+ elseif iParam0 == 1 then
+ return -0.102725, -0.13795, 0.948525
+ elseif iParam0 == 2 then
+ return -0.08975, -0.12665, 0.949175
+ elseif iParam0 == 3 then
+ return -0.075025, -0.1159, 0.949875
+ elseif iParam0 == 4 then
+ return -0.0614, -0.104775, 0.9507
+ elseif iParam0 == 5 then
+ return -0.046275, -0.095025, 0.9516
+ elseif iParam0 == 6 then
+ return -0.031425, -0.0846, 0.952675
+ end
+ elseif iParam1 == 3 then
+ if iParam0 == 0 then
+ return -0.5205, 0.1122, 0.9478
+ elseif iParam0 == 1 then
+ return -0.503175, 0.108525, 0.94865
+ elseif iParam0 == 2 then
+ return -0.485125, 0.10475, 0.949175
+ elseif iParam0 == 3 then
+ return -0.468275, 0.099175, 0.94995
+ elseif iParam0 == 4 then
+ return -0.45155, 0.09435, 0.95085
+ elseif iParam0 == 5 then
+ return -0.434475, 0.089725, 0.95145
+ elseif iParam0 == 6 then
+ return -0.415875, 0.0846, 0.9523
+ end
+ elseif iParam1 == 4 then --estimated
+ if iParam0 == 0 then
+ return -0.293,0.253,0.950025
+ elseif iParam0 == 1 then
+ return -0.093,0.253,0.950025
+ elseif iParam0 == 2 then
+ return 0.0293,0.253,0.950025
+ elseif iParam0 == 3 then
+ return 0.1516,0.253,0.950025
+ elseif iParam0 == 4 then
+ return 0.2739,0.253,0.950025
+ elseif iParam0 == 5 then
+ return 0.3962,0.253,0.950025
+ elseif iParam0 == 6 then
+ return 0.5185,0.253,0.950025
+ end
+ end
+ end
+ return 0.0, 0.0, 0.947875
+end
+
+function func_376(iParam0, iParam1, bParam2, bParam3)
+ if not bParam2 then
+ if iParam1 == 0 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, 69.12)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, 67.8)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, 66.6)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, 70.44)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, 70.84)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, 67.88)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, 69.56)
+ end
+ elseif iParam0 == 1 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, 22.11)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, 22.32)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, 20.8)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, 19.8)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, 19.44)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, 26.28)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, 22.68)
+ end
+ elseif iParam0 == 2 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, -21.43)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, -20.16)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, -16.92)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, -23.4)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, -21.24)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, -23.76)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, -19.44)
+ end
+ elseif iParam0 == 3 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, -67.03)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, -69.12)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, -64.44)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, -67.68)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, -63.72)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, -68.4)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, -64.44)
+ end
+ end
+ else
+ if iParam1 == 0 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, 68.57)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, 67.52)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, 67.76)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, 67.04)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, 68.84)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, 65.96)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, 67.76)
+ end
+ elseif iParam1 == 1 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, 22.11)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, 22)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, 24.44)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, 21.08)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, 25.96)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, 26.16)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, 28.76)
+ end
+ elseif iParam1 == 2 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, -14.04)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, -15.48)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, -16.56)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, -15.84)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, -16.92)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, -14.4)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, -14.28)
+ end
+ elseif iParam1 == 3 then
+ if iParam0 == 0 then
+ return vector3(0.0, 0.0, -67.03)
+ elseif iParam0 == 1 then
+ return vector3(0.0, 0.0, -67.6)
+ elseif iParam0 == 2 then
+ return vector3(0.0, 0.0, -69.4)
+ elseif iParam0 == 3 then
+ return vector3(0.0, 0.0, -69.04)
+ elseif iParam0 == 4 then
+ return vector3(0.0, 0.0, -68.68)
+ elseif iParam0 == 5 then
+ return vector3(0.0, 0.0, -66.16)
+ elseif iParam0 == 6 then
+ return vector3(0.0, 0.0, -63.28)
+ end
+ end
+ end
+ if bParam3 then
+ vVar0.z = (vVar0.z + 90.0)
+ end
+ return vVar0
+end
+
+function getChipPropFromAmount(amount)
+ --? _x1 is 1 chip _st is stack of 10 chips
+ --vw_prop_chip_10dollar_x1 --! £10
+ --vw_prop_chip_50dollar_x1 --! £50
+ --vw_prop_chip_100dollar_x1 --! £100
+ --vw_prop_chip_50dollar_st --! £50 stack
+ --vw_prop_chip_100dollar_st --! £100 stack
+ --vw_prop_chip_500dollar_x1 --! £500
+ --vw_prop_chip_1kdollar_x1 --! £1,000
+ --vw_prop_chip_500dollar_st --! £500 stack
+ --vw_prop_chip_5kdollar_x1 --! £5,000
+ --vw_prop_chip_1kdollar_st --! £1,000 stack
+ --vw_prop_chip_10kdollar_x1 --! £10,000
+ --vw_prop_chip_5kdollar_st --! £5,000 stack
+ --vw_prop_chip_10kdollar_st --! £10,000 stack
+ --vw_prop_plaq_5kdollar_x1 --! £5,000
+ --vw_prop_plaq_5kdollar_st --! £5,000 stack
+ --vw_prop_plaq_10kdollar_x1 --! £10,0000
+ --vw_prop_plaq_10kdollar_st --! £10,0000 stack
+ --* below not included in func in decompiled code
+ --vw_prop_vw_chips_pile_01a.ydr
+ --vw_prop_vw_chips_pile_02a.ydr
+ --vw_prop_vw_chips_pile_03a.ydr
+ --vw_prop_vw_coin_01a.ydr
+ amount = tonumber(amount)
+ if amount < 1000000 then
+ denominations = {10,50,100,500,1000,5000,10000}
+ chips = {}
+ local max = 7
+ for k,v in ipairs(denominations) do
+ while amount >= denominations[max] do
+ table.insert(chips,denominations[max])
+ amount = amount - denominations[max]
+ end
+ max = max - 1
+ end
+ for k,v in ipairs(chips) do
+ chips[k] = getChipFromAmount(v)
+ end
+ return chips
+ elseif amount < 5000000 then
+ return {"vw_prop_vw_chips_pile_01a"}
+ elseif amount < 10000000 then
+ return {"vw_prop_vw_chips_pile_02a"}
+ else
+ return {"vw_prop_vw_chips_pile_03a"}
+ end
+ return {"vw_prop_chip_500dollar_st"}
+end
+
+local chipsFromAmount = {
+ [1] = "vw_prop_vw_coin_01a",
+ [10] = "vw_prop_chip_10dollar_x1",
+ [50] = "vw_prop_chip_50dollar_x1",
+ [100] = "vw_prop_chip_100dollar_x1",
+ [500] = "vw_prop_chip_500dollar_x1",
+ [1000] = "vw_prop_chip_1kdollar_x1",
+ [5000] = "vw_prop_plaq_5kdollar_x1",
+ [10000] = "vw_prop_plaq_10kdollar_x1",
+}
+
+function getChipFromAmount(amount)
+ return chipsFromAmount[amount]
+end
+
+function blackjack_func_374(betAmount, iParam1, chairId, bParam3) --returns vector3
+ --betAmount, 0, chairID, someBool
+ -- print("blackjack_func_374 params:")
+ -- print("betAmount: " .. tostring(betAmount))
+ -- print("iParam1: " .. tostring(iParam1))
+ -- print("chairId: " .. tostring(chairId))
+ -- print("bParam3: " .. tostring(bParam3))
+ fVar0 = 0.0
+ vVar1 = vector3(0,0,0)
+ if not bParam3 then
+ -- print("now checking betAmount: " .. tostring(betAmount))
+ if betAmount == 10 then
+ fVar0 = 0.95
+ elseif betAmount == 20 then
+ fVar0 = 0.896
+ elseif betAmount == 30 then
+ fVar0 = 0.901
+ elseif betAmount == 40 then
+ fVar0 = 0.907
+ elseif betAmount == 50 then
+ fVar0 = 0.95
+ elseif betAmount == 60 then
+ fVar0 = 0.917
+ elseif betAmount == 70 then
+ fVar0 = 0.922
+ elseif betAmount == 80 then
+ fVar0 = 0.927
+ elseif betAmount == 90 then
+ fVar0 = 0.932
+ elseif betAmount == 100 then
+ fVar0 = 0.95
+ elseif betAmount == 150 then
+ fVar0 = 0.904
+ elseif betAmount == 200 then
+ fVar0 = 0.899
+ elseif betAmount == 250 then
+ fVar0 = 0.914
+ elseif betAmount == 300 then
+ fVar0 = 0.904
+ elseif betAmount == 350 then
+ fVar0 = 0.924
+ elseif betAmount == 400 then
+ fVar0 = 0.91
+ elseif betAmount == 450 then
+ fVar0 = 0.935
+ elseif betAmount == 500 then
+ fVar0 = 0.95
+ elseif betAmount == 1000 then
+ fVar0 = 0.95
+ elseif betAmount == 1500 then
+ fVar0 = 0.904
+ elseif betAmount == 2000 then
+ fVar0 = 0.899
+ elseif betAmount == 2500 then
+ fVar0 = 0.915
+ elseif betAmount == 3000 then
+ fVar0 = 0.904
+ elseif betAmount == 3500 then
+ fVar0 = 0.925
+ elseif betAmount == 4000 then
+ fVar0 = 0.91
+ elseif betAmount == 4500 then
+ fVar0 = 0.935
+ elseif betAmount == 5000 then
+ fVar0 = 0.95
+ elseif betAmount == 6000 then
+ fVar0 = 0.919
+ elseif betAmount == 7000 then
+ fVar0 = 0.924
+ elseif betAmount == 8000 then
+ fVar0 = 0.93
+ elseif betAmount == 9000 then
+ fVar0 = 0.935
+ elseif betAmount == 10000 then
+ fVar0 = 0.95
+ elseif betAmount == 15000 then
+ fVar0 = 0.902
+ elseif betAmount == 20000 then
+ fVar0 = 0.897
+ elseif betAmount == 25000 then
+ fVar0 = 0.912
+ elseif betAmount == 30000 then
+ fVar0 = 0.902
+ elseif betAmount == 35000 then
+ fVar0 = 0.922
+ elseif betAmount == 40000 then
+ fVar0 = 0.907
+ elseif betAmount == 45000 then
+ fVar0 = 0.932
+ elseif betAmount == 50000 then
+ fVar0 = 0.912
+ end
+ if chairId == 0 then
+ if iParam1 == 0 then
+ vVar1 = vector3(0.712625, 0.170625, 0.0001)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.6658, 0.218375, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(0.756775, 0.292775, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(0.701875, 0.3439, 0.0)
+ end
+ elseif chairId == 1 then
+ if iParam1 == 0 then
+ vVar1 = vector3(0.278125, -0.2571, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.280375, -0.190375, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(0.397775, -0.208525, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(0.39715, -0.1354, 0.0)
+ end
+ elseif chairId == 2 then
+ if iParam1 == 0 then
+ vVar1 = vector3(-0.30305, -0.2464, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(-0.257975, -0.19715, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(-0.186575, -0.2861, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(-0.141675, -0.237925, 0.0)
+ end
+ elseif chairId == 3 then
+ if iParam1 == 0 then
+ vVar1 = vector3(-0.72855, 0.17345, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(-0.652825, 0.177525, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(-0.6783, 0.0744, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(-0.604425, 0.082575, 0.0)
+ end
+ end
+ else
+ if betAmount == 10 then
+ fVar0 = 0.95
+ elseif betAmount == 20 then
+ fVar0 = 0.896
+ elseif betAmount == 30 then
+ fVar0 = 0.901
+ elseif betAmount == 40 then
+ fVar0 = 0.907
+ elseif betAmount == 50 then
+ fVar0 = 0.95
+ elseif betAmount == 60 then
+ fVar0 = 0.917
+ elseif betAmount == 70 then
+ fVar0 = 0.922
+ elseif betAmount == 80 then
+ fVar0 = 0.927
+ elseif betAmount == 90 then
+ fVar0 = 0.932
+ elseif betAmount == 100 then
+ fVar0 = 0.95
+ elseif betAmount == 150 then
+ fVar0 = 0.904
+ elseif betAmount == 200 then
+ fVar0 = 0.899
+ elseif betAmount == 250 then
+ fVar0 = 0.914
+ elseif betAmount == 300 then
+ fVar0 = 0.904
+ elseif betAmount == 350 then
+ fVar0 = 0.924
+ elseif betAmount == 400 then
+ fVar0 = 0.91
+ elseif betAmount == 450 then
+ fVar0 = 0.935
+ elseif betAmount == 500 then
+ fVar0 = 0.95
+ elseif betAmount == 1000 then
+ fVar0 = 0.95
+ elseif betAmount == 1500 then
+ fVar0 = 0.904
+ elseif betAmount == 2000 then
+ fVar0 = 0.899
+ elseif betAmount == 2500 then
+ fVar0 = 0.915
+ elseif betAmount == 3000 then
+ fVar0 = 0.904
+ elseif betAmount == 3500 then
+ fVar0 = 0.925
+ elseif betAmount == 4000 then
+ fVar0 = 0.91
+ elseif betAmount == 4500 then
+ fVar0 = 0.935
+ elseif betAmount == 5000 then
+ fVar0 = 0.953
+ elseif betAmount == 6000 then
+ fVar0 = 0.919
+ elseif betAmount == 7000 then
+ fVar0 = 0.924
+ elseif betAmount == 8000 then
+ fVar0 = 0.93
+ elseif betAmount == 9000 then
+ fVar0 = 0.935
+ elseif betAmount == 10000 then
+ fVar0 = 0.95
+ elseif betAmount == 15000 then
+ fVar0 = 0.902
+ elseif betAmount == 20000 then
+ fVar0 = 0.897
+ elseif betAmount == 25000 then
+ fVar0 = 0.912
+ elseif betAmount == 30000 then
+ fVar0 = 0.902
+ elseif betAmount == 35000 then
+ fVar0 = 0.922
+ elseif betAmount == 40000 then
+ fVar0 = 0.907
+ elseif betAmount == 45000 then
+ fVar0 = 0.932
+ elseif betAmount == 50000 then
+ fVar0 = 0.912
+ end
+ -- case 5000:
+ -- case 10000:
+ -- case 15000:
+ -- case 20000:
+ -- case 25000:
+ -- case 30000:
+ -- case 35000:
+ -- case 40000:
+ -- case 45000:
+ if betAmount == 50000 then
+ if chairId == 0 then
+ if iParam1 == 0 then
+ vVar1 = vector3(0.6931, 0.1952, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.724925, 0.26955, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.7374, 0.349625, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.76415, 0.419225, 0.0)
+ end
+ elseif chairId == 1 then
+ if iParam1 == 0 then
+ vVar1 = vector3(0.2827, -0.227825, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.3605, -0.1898, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(0.4309, -0.16365, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(0.49275, -0.111575, 0.0)
+ end
+ elseif chairId == 2 then
+ if iParam1 == 0 then
+ vVar1 = vector3(-0.279425, -0.2238, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(-0.200775, -0.25855, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(-0.125775, -0.26815, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(-0.05615, -0.29435, 0.0)
+ end
+ elseif chairId == 3 then
+ if iParam1 == 0 then
+ vVar1 = vector3(-0.685925, 0.173275, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(-0.6568, 0.092525, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(-0.612875, 0.033025, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(-0.58465, -0.0374, 0.0)
+ end
+ end
+ else
+ if chairId == 0 then
+ if iParam1 == 0 then
+ vVar1 = vector3(0.712625, 0.170625, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.6658, 0.218375, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(0.756775, 0.292775, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(0.701875, 0.3439, 0.0)
+ end
+ elseif chairId == 1 then
+ if iParam1 == 0 then
+ vVar1 = vector3(0.278125, -0.2571, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(0.280375, -0.190375, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(0.397775, -0.208525, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(0.39715, -0.1354, 0.0)
+ end
+ elseif chairId == 2 then
+ if iParam1 == 0 then
+ vVar1 = vector3(-0.30305, -0.2464, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(-0.257975, -0.19715, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(-0.186575, -0.2861, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(-0.141675, -0.237925, 0.0)
+ end
+ elseif chairId == 3 then
+ if iParam1 == 0 then
+ vVar1 = vector3(-0.72855, 0.17345, 0.0)
+ elseif iParam1 == 1 then
+ vVar1 = vector3(-0.652825, 0.177525, 0.0)
+ elseif iParam1 == 2 then
+ vVar1 = vector3(-0.6783, 0.0744, 0.0)
+ elseif iParam1 == 3 then
+ vVar1 = vector3(-0.604425, 0.082575, 0.0)
+ end
+ end
+ end
+ end
+ -- print(vVar1)
+ -- print(vVar1.z)
+ -- print(fVar0)
+ --vVar1.z = fVar0
+ vVar1 = vVar1 + vector3(0.0,0.0,fVar0)
+ return vVar1
+end
+
+function blackjack_func_373(iParam0, iParam1, iParam2, bParam3)
+ if not bParam3 then
+ if iParam2 == 0 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, 72)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, 64.8)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, 74.52)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, 72)
+ end
+ elseif iParam2 == 1 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, 12.96)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, 29.16)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, 32.04)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, 32.04)
+ end
+ elseif iParam2 == 2 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -18.36)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -18.72)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -15.48)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -18)
+ end
+ elseif iParam2 == 3 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -79.2)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -68.76)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -57.6)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -64.8)
+ end
+ end
+ else
+ -- case 5000 then
+ -- case 10000 then
+ -- case 15000 then
+ -- case 20000 then
+ -- case 25000 then
+ -- case 30000 then
+ -- case 35000 then
+ -- case 40000 then
+ -- case 45000 then
+ if iParam0 == 50000 then
+ if iParam2 == 0 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -16.56)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -22.32)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -10.8)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -9.72)
+ end
+ elseif iParam2 == 1 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -69.12)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -64.8)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -58.68)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -51.12)
+ end
+ elseif iParam2 == 2 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -112.32)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -108.36)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -99.72)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -102.6)
+ end
+ elseif iParam2 == 3 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -155.88)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -151.92)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -147.24)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -146.52)
+ end
+ end
+ else
+ if iParam2 == 0 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, 72)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, 64.8)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, 74.52)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, 72)
+ end
+ elseif iParam2 == 1 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, 12.96)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, 29.16)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, 32.04)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, 32.04)
+ end
+ elseif iParam2 == 2 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -18.36)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -18.72)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -15.48)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -18)
+ end
+ elseif iParam2 == 3 then
+ if iParam1 == 0 then
+ return vector3(0.0, 0.0, -79.2)
+ elseif iParam1 == 1 then
+ return vector3(0.0, 0.0, -68.76)
+ elseif iParam1 == 2 then
+ return vector3(0.0, 0.0, -57.6)
+ elseif iParam1 == 3 then
+ return vector3(0.0, 0.0, -64.8)
+ end
+ end
+ end
+ end
+ return vector3(0.0, 0.0, 0)
+end
+
+function ButtonMessage(text)
+ BeginTextCommandScaleformString("STRING")
+ AddTextComponentScaleform(text)
+ EndTextCommandScaleformString()
+end
+
+function Button(ControlButton)
+ N_0xe83a3e3557a56640(ControlButton)
+end
+
+function setupBlackjackInstructionalScaleform(scaleform)
+ local scaleform = RequestScaleformMovie(scaleform)
+ while not HasScaleformMovieLoaded(scaleform) do
+ Wait(0)
+ end
+ PushScaleformMovieFunction(scaleform, "CLEAR_ALL")
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "SET_CLEAR_SPACE")
+ PushScaleformMovieFunctionParameterInt(200)
+ PopScaleformMovieFunctionVoid()
+
+ -- PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ -- PushScaleformMovieFunctionParameterInt(1)
+ -- Button(GetControlInstructionalButton(2, 194, true)) -- The button to display
+ -- ButtonMessage("Leave table") --BACKSPACE
+ -- PopScaleformMovieFunctionVoid()
+
+ -- PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ -- PushScaleformMovieFunctionParameterInt(0)
+ -- Button(GetControlInstructionalButton(2, 191, true))
+ -- ButtonMessage("Place bet") --ENTER
+ -- PopScaleformMovieFunctionVoid()
+
+ -- PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ -- PushScaleformMovieFunctionParameterInt(2)
+ -- Button(GetControlInstructionalButton(2, 11, true))
+ -- ButtonMessage("Lower bet") --Page Down
+ -- PopScaleformMovieFunctionVoid()
+
+ -- PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ -- PushScaleformMovieFunctionParameterInt(3)
+ -- Button(GetControlInstructionalButton(2, 10, true))
+ -- ButtonMessage("Increase bet") --Page Up
+ -- PopScaleformMovieFunctionVoid()
+
+ -- PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ -- PushScaleformMovieFunctionParameterInt(4)
+ -- Button(GetControlInstructionalButton(2, 22, true))
+ -- ButtonMessage("Custom bet") --Space
+ -- PopScaleformMovieFunctionVoid()
+
+
+
+ PushScaleformMovieFunction(scaleform, "DRAW_INSTRUCTIONAL_BUTTONS")
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "SET_BACKGROUND_COLOUR")
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(80)
+ PopScaleformMovieFunctionVoid()
+
+ return scaleform
+end
+
+function setupBlackjackMidBetScaleform(scaleform)
+ local scaleform = RequestScaleformMovie(scaleform)
+ while not HasScaleformMovieLoaded(scaleform) do
+ Wait(0)
+ end
+ PushScaleformMovieFunction(scaleform, "CLEAR_ALL")
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "SET_CLEAR_SPACE")
+ PushScaleformMovieFunctionParameterInt(200)
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ PushScaleformMovieFunctionParameterInt(1)
+ Button(GetControlInstructionalButton(2, 194, true)) -- The button to display
+ ButtonMessage("Stand") --BACKSPACE
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "SET_DATA_SLOT")
+ PushScaleformMovieFunctionParameterInt(4)
+ Button(GetControlInstructionalButton(2, 22, true))
+ ButtonMessage("Hit") --Space
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "DRAW_INSTRUCTIONAL_BUTTONS")
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, "SET_BACKGROUND_COLOUR")
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(80)
+ PopScaleformMovieFunctionVoid()
+
+ return scaleform
+end
+
+function getDealerIdFromEntity(dealerEntity)
+ local closestID = nil
+ local closestDist = 10000
+ local dealerCoords = GetEntityCoords(dealerEntity)
+ for k,v in pairs(cfg.blackjackTables) do
+ local actualDealerPos = v.dealerPos
+ if #(dealerCoords-dealerPos) < closestDist then
+ closestID = k
+ closestDist = #(dealerCoords-dealerPos)
+ end
+ end
+ return closestID
+end
+
+function setBlackjackDealerPedVoiceGroup(randomNumber,dealerPed)
+ if randomNumber == 0 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_WHITE_01"))
+ elseif randomNumber == 1 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_ASIAN_01"))
+ elseif randomNumber == 2 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_ASIAN_02"))
+ elseif randomNumber == 3 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_ASIAN_01"))
+ elseif randomNumber == 4 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_WHITE_01"))
+ elseif randomNumber == 5 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_WHITE_02"))
+ elseif randomNumber == 6 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_M_Y_Casino_01_WHITE_01"))
+ elseif randomNumber == 7 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_ASIAN_01"))
+ elseif randomNumber == 8 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_ASIAN_02"))
+ elseif randomNumber == 9 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_ASIAN_01"))
+ elseif randomNumber == 10 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_ASIAN_02"))
+ elseif randomNumber == 11 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_LATINA_01"))
+ elseif randomNumber == 12 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_LATINA_02"))
+ elseif randomNumber == 13 then
+ SetPedVoiceGroup(dealerPed,GetHashKey("S_F_Y_Casino_01_LATINA_01"))
+ end
+end
+
+function setBlackjackDealerClothes(randomNumber,dealerPed)
+ if randomNumber == 0 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 1 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 2, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 2 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 3 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 4 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 2, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 5 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 6 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 7 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 8 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 9 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 2, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 10 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 3, 3, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 11 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 1, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ SetPedPropIndex(dealerPed, 1, 0, 0, false)
+ elseif randomNumber == 12 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 3, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 1, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 13 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ SetPedPropIndex(dealerPed, 1, 0, 0, false)
+ end
+end
+
+function DrawTimerBar2(title, text, barIndex)
+ local width = 0.13
+ local hTextMargin = 0.003
+ local rectHeight = 0.038
+ local textMargin = 0.008
+
+ local rectX = GetSafeZoneSize() - width + width / 2
+ local rectY = GetSafeZoneSize() - rectHeight + rectHeight / 2 - (barIndex - 1) * (rectHeight + 0.005)
+
+ DrawSprite("timerbars", "all_black_bg", rectX, rectY, width, 0.038, 0, 0, 0, 0, 128)
+
+ DrawTimerBarText(title, GetSafeZoneSize() - width + hTextMargin, rectY - textMargin, 0.32)
+ DrawTimerBarText(string.upper(text), GetSafeZoneSize() - hTextMargin, rectY - 0.0175, 0.5, true, width / 2)
+end
+
+function DrawNoiseBar(noise, barIndex)
+ DrawTimerBar2("NOISE", math.floor(noise), barIndex)
+end
+
+function DrawTimerBarText(text, x, y, scale, right, width)
+ SetTextFont(0)
+ SetTextScale(scale, scale)
+ SetTextColour(254, 254, 254, 255)
+
+ if right then
+ SetTextWrap(x - width, x)
+ SetTextRightJustify(true)
+ end
+
+ BeginTextCommandDisplayText("STRING")
+ AddTextComponentSubstringPlayerName(text)
+ EndTextCommandDisplayText(x, y)
+end
+
+function DrawAdvancedNativeText(x,y,w,h,sc, text, r,g,b,a,font,jus)
+ SetTextFont(font)
+ SetTextScale(sc, sc)
+ N_0x4e096588b13ffeca(jus)
+ SetTextColour(254, 254, 254, 255)
+ SetTextEntry("STRING")
+ AddTextComponentString(text)
+ DrawText(x - 0.1+w, y - 0.02+h)
+end
+
+
+RegisterNetEvent("blackjack:notify")
+AddEventHandler("blackjack:notify",function(msg)
+ QBCore.Functions.Notify(msg, 'success', 3500)
+end)
+
+function getGenericTextInput(type)
+ if type == nil then type = "" end
+ AddTextEntry('FMMC_MPM_NA', "Enter " .. tostring(type))
+ DisplayOnscreenKeyboard(1, "FMMC_MPM_NA", "Enter " .. tostring(type) .. " message", "", "", "", "", 30)
+ while (UpdateOnscreenKeyboard() == 0) do
+ DisableAllControlActions(0);
+ Wait(0);
+ end
+ if (GetOnscreenKeyboardResult()) then
+ local result = GetOnscreenKeyboardResult()
+ if result then
+ return result
+ end
+ end
+ return false
+end
+
+--Debug Commands--
+RegisterCommand("cleantable",function()
+ for k,v in pairs(cardObjects) do
+ for _,obj in pairs(v) do
+ DeleteObject(obj)
+ end
+ end
+end)
+
+-- RegisterCommand("debugtable",function()
+-- print(dump(blackjackTableData))
+-- end)
+
+-- RegisterCommand("debugtable2",function()
+-- TriggerServerEvent("Blackjack:requestBlackjackTableData")
+-- end)
+
+-- RegisterCommand("testcasinosound", function()
+-- closestDealerPed, closestDealerPedDistance = getClosestDealer()
+-- PlayAmbientSpeech1(closestDealerPed,"MINIGAME_DEALER_BUSTS","SPEECH_PARAMS_FORCE_NORMAL_CLEAR",1)
+-- end)
+
+-- RegisterCommand("testcasinoanim", function()
+-- TaskPlayAnim(PlayerPedId(), "anim_casino_b@amb@casino@games@blackjack@dealer", "check_card", 3.0, 1.0, -1, 2, 0, 0, 0, 0 )
+-- -- print("animation started")
+-- -- while not HasEntityAnimFinished(PlayerPedId(), "anim_casino_b@amb@casino@games@blackjack@dealer", "check_card",3) do
+-- -- -- print("waiting for check card animation to end")
+-- -- Wait(0)
+-- -- end
+-- while true do
+-- -- print("hasAnimEventFired: " .. tostring(HasAnimEventFired(PlayerPedId(),585557868)))
+-- Wait(0)
+-- end
+-- -- print("animation finished")
+-- end)
+
+-- RegisterCommand("debugblackjack", function()
+-- -- print("closestBlackjackChair: " .. tostring(closestChairDist))
+-- -- print("closestChair: " .. tostring(closestChair))
+-- -- print("Local_198f_247: " .. tostring(Local_198f_247))
+-- end)
+
+-- RegisterCommand("debugtablepeds",function()
+-- print(dump(dealerPeds))
+-- end)
+
+-- RegisterCommand("testcleanup",function()
+-- print(dump(cardObjects))
+-- end)
+
+-- RegisterCommand("hitme",function()
+-- requestCard()
+-- end)
+
+-- RegisterCommand("stand",function()
+-- declineCard()
+-- end)
+
+-- RegisterCommand("dealerhit",function()
+-- closestDealerPed, closestDealerPedDistance = getClosestDealer()
+-- startStandOrHit(gameId,closestDealerPed,1)
+-- end)
+
+-- RegisterCommand("dealergive",function()
+-- closestDealerPed, closestDealerPedDistance = getClosestDealer()
+-- cardData = {20,19}
+-- chairId = 7
+-- tableId = 1
+-- cardObj = startDealing(closestChair,closestDealerPed,gameId,cardData,chairId,0,10,tableId)
+-- SetTimeout(5000,function()
+-- DeleteObject(cardObj)
+-- -- print("DELETED.")
+-- end)
+-- end)
+
+-- RegisterCommand("debugchips", function(source,args,rawCommand)
+-- local chips = args[2]
+-- -- print("getChipPropFromAmount(" .. tostring(chips) .. ")")
+-- getChipPropFromAmount(chips)
+-- end)
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackRT98/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-blackjackRT98/fxmanifest.lua
new file mode 100644
index 0000000..510f23e
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackRT98/fxmanifest.lua
@@ -0,0 +1,13 @@
+fx_version 'cerulean'
+
+game "gta5"
+
+description "DiamondBlackjack created by Robbster"
+
+client_scripts {
+ "cl_blackjack.lua",
+}
+
+server_script "sv_blackjack.lua"
+
+
diff --git a/resources/[qb]/[qb_casino]/casino-blackjackRT98/sv_blackjack.lua b/resources/[qb]/[qb_casino]/casino-blackjackRT98/sv_blackjack.lua
new file mode 100644
index 0000000..e89439b
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-blackjackRT98/sv_blackjack.lua
@@ -0,0 +1,700 @@
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+
+local ItemList = {
+ ["casino_redchip"] = 1
+}
+QBCore.Functions.CreateCallback('BLACKJACKRT98:server:blackChipsAmount', function(source, cb)
+ local retval = 0
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.PlayerData.items ~= nil and next(Player.PlayerData.items) ~= nil then
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ retval = retval + (ItemList[Player.PlayerData.items[k].name] * Player.PlayerData.items[k].amount)
+ end
+ end
+ end
+ end
+ cb(retval)
+end)
+
+
+local blackjackTables = {
+ --[chairId] == false or source if taken
+ [0] = false,
+ [1] = false,
+ [2] = false,
+ [3] = false,
+ [4] = false,
+ [5] = false,
+ [6] = false,
+ [7] = false,
+ [8] = false,
+ [9] = false,
+ [10] = false,
+ [11] = false,
+ [12] = false,
+ [13] = false,
+ [14] = false,
+ [15] = false,
+}
+
+for i=0,127,1 do
+ blackjackTables[i] = false
+end
+
+local blackjackGameInProgress = {}
+local blackjackGameData = {}
+
+function tryTakeChips(source,amount)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local ItemList = {
+ ["casino_redchip"] = 1,
+ }
+ local playerChips = Player.Functions.GetItemByName("casino_redchip")
+ local canBet = false
+
+ if Player.PlayerData.items ~= nil and next(Player.PlayerData.items) ~= nil then
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ if playerChips.amount >= amount then
+ Player.Functions.RemoveItem("casino_redchip", amount)
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items["casino_redchip"], 'remove')
+ canBet = true
+ end
+ end
+ end
+ end
+ end
+
+ return canBet
+end
+
+
+function giveChips(source,amount)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ if Player ~= nil then
+ if Player.Functions.AddItem('casino_redchip', amount, nil, {["quality"] = 100}) then
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["casino_redchip"], "add", amount)
+ TriggerClientEvent('QBCore:Notify', src, "You Won "..math.floor(amount).." Casino Chips!")
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'You have to much in your pockets', 'error')
+ end
+ end
+end
+
+AddEventHandler('playerDropped', function (reason)
+ local source = source
+ for k,v in pairs(blackjackTables) do
+ if v == source then
+ blackjackTables[k] = false
+ end
+ end
+end)
+
+RegisterNetEvent("Blackjack:requestBlackjackTableData")
+AddEventHandler("Blackjack:requestBlackjackTableData", function()
+ local source = source
+ TriggerClientEvent("Blackjack:sendBlackjackTableData",source,blackjackTables)
+end)
+
+RegisterNetEvent("Blackjack:requestSitAtBlackjackTable")
+AddEventHandler("Blackjack:requestSitAtBlackjackTable", function(chairId)
+ local source = source
+
+ if source ~= nil then
+ for k,v in pairs(blackjackTables) do
+ if v == source then
+ blackjackTables[k] = false
+ --print("[Error] Player tried to sit at a table, but he's already sitting there :?, proceeding...")
+ return
+ end
+ end
+ --print("setting blackjacktable chairID: " .. tostring(chairId))
+ blackjackTables[chairId] = source
+ TriggerClientEvent("Blackjack:sendBlackjackTableData",-1,blackjackTables)
+ TriggerClientEvent("Blackjack:sitAtBlackjackTable",source,chairId)
+ else
+ TriggerClientEvent('QBCore:Notify', source, 'cant sit you down.', 'error')
+ end
+end)
+
+RegisterNetEvent("Blackjack:leaveBlackjackTable")
+AddEventHandler("Blackjack:leaveBlackjackTable", function(chairId)
+ local source = source
+
+ if source ~= nil then
+ for k,v in pairs(blackjackTables) do
+ if v == source then
+ blackjackTables[k] = false
+ end
+ end
+ TriggerClientEvent("Blackjack:sendBlackjackTableData",-1,blackjackTables)
+ end
+end)
+
+RegisterNetEvent("Blackjack:setBlackjackBet")
+AddEventHandler("Blackjack:setBlackjackBet",function(gameId,betAmount,chairId)
+ local source = source
+
+ if gameId ~= nil and betAmount ~= nil and chairId ~= nil then
+ if blackjackGameData[gameId] == nil then
+ blackjackGameData[gameId] = {}
+ end
+ if not blackjackGameInProgress[gameId] then
+ if tonumber(betAmount) then
+ betAmount = tonumber(betAmount)
+ if betAmount > 0 then
+ if tryTakeChips(source,betAmount) then
+ ----print("Taken",betAmount,"chips from id",source)
+ if blackjackGameData[gameId][source] == nil then
+ blackjackGameData[gameId][source] = {}
+ end
+ blackjackGameData[gameId][source][1] = betAmount
+ ----print("GameId: " .. tostring(gameId) .. " source: " .. tostring(source) .. " has placed a bet of " .. tostring(betAmount))
+ TriggerClientEvent("Blackjack:successBlackjackBet",source)
+ TriggerClientEvent("Blackjack:syncChipsPropBlackjack",-1,betAmount,chairId)
+ -- TriggerClientEvent('QBCore:Notify', source, 'Bet placed: ' .. tostring(betAmount) .. ' chips.', 'success')
+ else
+ TriggerClientEvent('QBCore:Notify', source, 'You dont have enough chips', 'error')
+ TriggerClientEvent("doj:client:openBetMenu", source)
+ end
+ end
+ end
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', source, 'Error betting!', 'error')
+
+ end
+end)
+
+RegisterNetEvent("Blackjack:hitBlackjack")
+AddEventHandler("Blackjack:hitBlackjack",function(gameId,nextCardCount)
+ local source = source
+ blackjackGameData[gameId][source][2][nextCardCount] = true
+end)
+
+RegisterNetEvent("Blackjack:standBlackjack")
+AddEventHandler("Blackjack:standBlackjack",function(gameId,nextCardCount)
+ local source = source
+ blackjackGameData[gameId][source][2][nextCardCount] = false
+end)
+
+for i=0,31,1 do
+ CreateThread(function()
+ math.randomseed(os.clock()*100000000000)
+ while true do --blackjack game management thread
+ math.random()
+ math.random()
+ math.random()
+ local game_ready = false
+ local players_ready = {}
+ local tableId = i
+ local chairIdInitial = i*4 --0-3,4-7,8-11,12-15
+ local chairIdFinal = (i*4)+3
+ for chairID=chairIdInitial,chairIdFinal do
+ ----print("checking chairID[" .. tostring(chairID) .. "] = " .. tostring(blackjackTables[chairID]))
+ if blackjackTables[chairID] ~= false then
+ table.insert(players_ready,blackjackTables[chairID])
+ game_ready = true
+ end
+ end
+ if game_ready then
+ local gameId = math.random(1000,10000000)
+ --print("generated gameId",gameId)
+ blackjackGameData[gameId] = {} --init game data
+ blackjackGameInProgress[gameId] = false
+ for k,v in pairs(players_ready) do
+ local source = v
+ blackjackGameData[gameId][v] = {}
+ if source ~= nil then
+ TriggerClientEvent("Blackjack:beginBetsBlackjack",source,gameId,tableId)
+ end
+ end
+ Wait(21000) --Wait 20 seconds for everyone to put bets up
+ if blackjackGameData[gameId] ~= nil then
+ for k,v in pairs(blackjackGameData[gameId]) do
+ if v ~= nil then
+ local playerBetted = false
+ betAmount = v[1]
+ -- --print("betAmount: " .. tostring(betAmount))
+ -- --print("v: " .. tostring(v))
+ -- --print("vdump: " .. dump(blackjackGameData[gameId][k]))
+ if betAmount ~= nil and betAmount > 0 then
+ playerBetted = true
+ end
+ if not playerBetted then
+ blackjackGameData[gameId][k] = nil
+ end
+ end
+ end
+ if not isTableEmpty(blackjackGameData[gameId]) then
+ blackjackGameInProgress[gameId] = true
+ --generate random cards here to send? in round "1"
+ for cardIndex=0,1,1 do
+ for chairID=chairIdInitial,chairIdFinal do
+ if blackjackTables[chairID] ~= false then
+ local source = blackjackTables[chairID]
+ if blackjackGameData[gameId] == nil then
+ blackjackGameData[gameId] = {}
+ end
+ if blackjackGameData[gameId][source] == nil then
+ blackjackGameData[gameId][source] = {}
+ end
+ if blackjackGameData[gameId][source][1] ~= nil then
+ if blackjackGameData[gameId][source][1] > 0 then
+ if blackjackGameData[gameId][source]["cardData"] == nil then
+ blackjackGameData[gameId][source]["cardData"] = {}
+ end
+ local randomCard = math.random(1,52)
+ table.insert(blackjackGameData[gameId][source]["cardData"], randomCard)
+ TriggerClientEvent("Blackjack:beginCardGiveOut",-1,gameId,blackjackGameData[gameId][source]["cardData"],chairID,cardIndex,getCurrentHand(gameId,source),tableId)
+ Wait(3500)
+ else
+ blackjackGameData[gameId][source] = nil
+ end
+ else
+ blackjackGameData[gameId][source] = nil
+ end
+ end
+ end
+ if blackjackGameData[gameId]["dealer"] == nil then
+ blackjackGameData[gameId]["dealer"] = {}
+ end
+ if blackjackGameData[gameId]["dealer"]["cardData"] == nil then
+ blackjackGameData[gameId]["dealer"]["cardData"] = {}
+ end
+ if cardIndex == 0 then
+ local randomCard = math.random(1,52)
+ ----print("randomDealerCard: " .. tostring(randomCard))
+ table.insert(blackjackGameData[gameId]["dealer"]["cardData"], randomCard)
+ TriggerClientEvent("Blackjack:beginCardGiveOut",-1,gameId,blackjackGameData[gameId]["dealer"]["cardData"],gameId,cardIndex,getCurrentHand(gameId,"dealer"),tableId)
+ end
+ Wait(1500) --Wait between each initial give out card
+ end
+ --Wait(6000) --Wait for dealer to check own card
+ for chairID=chairIdInitial,chairIdFinal do
+ if blackjackTables[chairID] ~= false then
+ local source = blackjackTables[chairID]
+ if blackjackGameData[gameId][source] ~= nil then
+ local nextCardCount = 1
+ local currentHand = getCurrentHand(gameId,source)
+ if currentHand < 21 then
+ TriggerClientEvent("Blackjack:standOrHit",-1,gameId,chairID,nextCardCount,tableId)
+ blackjackGameData[gameId][source][2] = {}
+ ----print("initialize card count = 1")
+ while nextCardCount >= 1 do
+ ----print("while card count >= 1 waiting for a response... cardCount is: " .. tostring(nextCardCount))
+ secondsWaited = 0
+ ----print("error debug #1")
+ ----print("gameId",gameId)
+ --print(dump(blackjackGameData[gameId]))
+ ----print("=======")
+ while blackjackGameData[gameId][source][2][nextCardCount] == nil and secondsWaited < 20 do
+ Wait(100)
+ secondsWaited = secondsWaited + 0.1
+ ------print("response to stand or hit is still false")
+ end
+ --print("response received! [ok]")
+ if blackjackGameData[gameId][source][2][nextCardCount] == true then --if hit
+ ----print("response was hit")
+ nextCardCount = nextCardCount + 1
+ local randomCard = math.random(1,52)
+ table.insert(blackjackGameData[gameId][source]["cardData"], randomCard)
+ TriggerClientEvent("Blackjack:singleCard",-1,gameId,randomCard,chairID,nextCardCount,getCurrentHand(gameId,source),tableId)
+ Wait(2000)
+ local currentHand = getCurrentHand(gameId,source)
+ ----print("Checking for bust... currentHand: " .. tostring(currentHand))
+ if currentHand > 21 then
+ ----print("currentHand > 21")
+ TriggerClientEvent("Blackjack:bustBlackjack",-1,chairID,tableId)
+ nextCardCount = 0
+ blackjackGameData[gameId][source]["status"] = "bust"
+ local lostAmount = blackjackGameData[gameId][source][1]
+ TriggerClientEvent('QBCore:Notify', source, 'Lost -'..tostring(lostAmount).." chips", 'error')
+ if lostAmount > 10000000 then
+ TriggerClientEvent('chatMessage', -1, "Diamond Casino | " .. GetPlayerName(source) .. " has LOST " .. tostring(getMoneyStringFormatted(lostAmount)) .. " chips!")
+ end
+ elseif currentHand < 21 then
+ ----print("currentHand < 21")
+ TriggerClientEvent("Blackjack:standOrHit",-1,gameId,chairID,nextCardCount,tableId)
+ else
+ ----print("currentHand == 21")
+ ----print("got 21 auto-standing")
+ nextCardCount = 0
+ blackjackGameData[gameId][source]["status"] = "stand"
+ end
+ elseif blackjackGameData[gameId][source][2][nextCardCount] == false then --if stand
+ ----print("response was false")
+ nextCardCount = 0
+ blackjackGameData[gameId][source]["status"] = "stand"
+ else
+ ----print("response was false")
+ nextCardCount = 0
+ blackjackGameData[gameId][source]["status"] = "stand"
+ end
+ end
+ else
+ ----print("got 21 auto-standing")
+ blackjackGameData[gameId][source]["status"] = "stand"
+ end
+ end
+ TriggerClientEvent("Blackjack:endStandOrHitPhase",-1,chairID,tableId)
+ end
+ end
+ local randomCard = math.random(1,52)
+ ----print("randomDealerCard: " .. tostring(randomCard))
+ table.insert(blackjackGameData[gameId]["dealer"]["cardData"], randomCard)
+ TriggerClientEvent("Blackjack:beginCardGiveOut",-1,gameId,blackjackGameData[gameId]["dealer"]["cardData"],gameId,1,getCurrentHand(gameId,"dealer"),tableId)
+ Wait(2800)
+ dealerHand = getCurrentHand(gameId,"dealer")
+ TriggerClientEvent("Blackjack:flipDealerCard",-1,dealerHand,tableId,gameId)
+ Wait(2800)
+ --Dealer hit til 17 logic
+ local allPlayersHaveBusted = true
+ ----print("allPlayersHaveBusted loop")
+ for k,v in pairs(blackjackGameData[gameId]) do
+ local betStatus = v["status"]
+ ----print("betStatus: " .. tostring(betStatus))
+ if betStatus ~= nil then
+ if betStatus == "stand" then
+ allPlayersHaveBusted = false
+ ----print("allPlayersHaveBusted!")
+ end
+ end
+ end
+ dealerHand = getCurrentHand(gameId,"dealer")
+ if not allPlayersHaveBusted then
+ ----print("dealing hand is: " .. tostring(dealerHand))
+ if dealerHand >= 17 then
+ ----print("dealing hand is: " .. tostring(dealerHand) .. " so standing")
+ else
+ ----print("dealing hand is: " .. tostring(dealerHand) .. " so hitting")
+ local nextCardCount = 2
+ local highestPlayerHand = 0
+ ----print("highestPlayerHand",highestPlayerHand)
+ for k,v in pairs(blackjackGameData[gameId]) do
+ if k ~= "dealer" then
+ playerHand = getCurrentHand(gameId,k)
+ ----print("================")
+ ----print("playerHand",playerHand)
+ ----print("highestPlayerHand",highestPlayerHand)
+ ----print("================")
+ if playerHand ~= nil then
+ if playerHand > highestPlayerHand and playerHand <= 21 then
+ highestPlayerHand = playerHand
+ ----print("highestPlayerHand",highestPlayerHand,"= playerHand",playerHand)
+ end
+ end
+ end
+ end
+ while dealerHand < 17 do
+ local randomCard = math.random(1,52)
+ ----print("randomDealerCard: " .. tostring(randomCard))
+ table.insert(blackjackGameData[gameId]["dealer"]["cardData"], randomCard)
+ TriggerClientEvent("Blackjack:singleDealerCard",-1,gameId,randomCard,nextCardCount,getCurrentHand(gameId,"dealer"),tableId)
+ Wait(2800)
+ nextCardCount = nextCardCount + 1
+ dealerHand = getCurrentHand(gameId,"dealer")
+ end
+ end
+ end
+ for k,v in pairs(blackjackGameData[gameId]) do
+ if k ~= "dealer" then
+ local source = k
+ if blackjackGameData[gameId][source] ~= nil then
+ ----print("Checking source: " .. tostring(source) .. " for bust when final checks are doing")
+ ----print("result: " .. tostring(blackjackGameData[gameId][source]["status"]))
+ ----print("table dump:")
+ --print(dump(blackjackGameData[gameId][source]))
+ if blackjackGameData[gameId][source]["status"] ~= "bust" then
+ local currentHand = getCurrentHand(gameId,source)
+ ----print("Checking for bust... currentHand: " .. tostring(currentHand))
+ ----print("dealerHand: " .. tostring(dealerHand))
+ if currentHand ~= nil then
+ if currentHand <= 21 then
+ local potentialWinAmount = blackjackGameData[gameId][source][1] * 2
+ local potentialPushAmount = blackjackGameData[gameId][source][1]
+ local playerPing = GetPlayerPing(source)
+ if dealerHand > 21 then
+ ----print("source: " .. tostring(source) .. " wins!")
+ giveChips(source,potentialWinAmount)
+ if playerPing ~= nil then
+ if playerPing > 0 then
+ TriggerClientEvent("Blackjack:blackjackWin",source,tableId)
+ TriggerClientEvent('QBCore:Notify', source, 'You have BLACKJACK! +'..tostring(potentialWinAmount)..' chips', 'success')
+ if potentialPushAmount > 10000000 then
+ TriggerClientEvent('chatMessage', -1, "Diamond Casino | " .. GetPlayerName(source) .. " has WON " .. tostring(getMoneyStringFormatted(potentialPushAmount)) .. " chips!")
+ end
+ end
+ end
+ TriggerClientEvent("Blackjack:dealerBusts",-1,tableId)
+ elseif currentHand > dealerHand and currentHand <= 21 then
+ ----print("source: " .. tostring(source) .. " wins!")
+ giveChips(source,potentialWinAmount)
+ if playerPing ~= nil then
+ if playerPing > 0 then
+ TriggerClientEvent("Blackjack:blackjackWin",source,tableId)
+ TriggerClientEvent('QBCore:Notify', source, 'You have BLACKJACK! +'..tostring(potentialWinAmount)..' chips', 'success')
+ if potentialPushAmount > 10000000 then
+ TriggerClientEvent('chatMessage', -1, "Diamond Casino | " .. GetPlayerName(source) .. " has WON " .. tostring(getMoneyStringFormatted(potentialPushAmount)) .. " chips!")
+ end
+ end
+ end
+ elseif currentHand == dealerHand then
+ ----print("source: " .. tostring(source) .. " pushes!")
+ giveChips(source,potentialPushAmount)
+ if playerPing ~= nil then
+ if playerPing > 0 then
+ TriggerClientEvent("Blackjack:blackjackPush",source,tableId)
+ TriggerClientEvent('QBCore:Notify', source, 'You pushed!', 'error')
+ end
+ end
+ else
+ ----print("source: " .. tostring(source) .. " loses!")
+ if playerPing ~= nil then
+ if playerPing > 0 then
+ TriggerClientEvent("Blackjack:blackjackLose",source,tableId)
+ TriggerClientEvent('QBCore:Notify', source, 'You lost! -'..tostring(potentialPushAmount)..' chips', 'error')
+ if potentialPushAmount > 10000000 then
+ TriggerClientEvent('chatMessage', -1, "Diamond Casino | " .. GetPlayerName(source) .. " has LOST " .. tostring(getMoneyStringFormatted(potentialPushAmount)) .. " chips!")
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ for chairID=chairIdInitial,chairIdFinal do
+ if blackjackTables[chairID] ~= false then
+ local source = blackjackTables[chairID]
+ if blackjackGameData[gameId][source] ~= nil then
+ TriggerClientEvent("Blackjack:chipsCleanup",-1,chairID,tableId)
+ TriggerClientEvent("Blackjack:chipsCleanup",-1,tostring(chairID).."chips",tableId)
+ ----print("chips cleanup for chairID, waiting 2 seconds....")
+ Wait(3500)
+ end
+ end
+ end
+ ----print("chips cleanup for dealer")
+ TriggerClientEvent("Blackjack:chipsCleanup",-1,gameId,tableId)
+ for chairID=chairIdInitial,chairIdFinal do
+ TriggerClientEvent("Blackjack:chipsCleanupNoAnim",-1,chairID,tableId)
+ TriggerClientEvent("Blackjack:chipsCleanupNoAnim",-1,tostring(chairID).."chips",tableId)
+ end
+ blackjackGameInProgress[gameId] = false
+ else
+ ----print("Game not started")
+ end
+ else
+ ----print("No one betted :(")
+ end
+ else
+ Wait(1000)
+ end
+ Wait(1000) --Check ever second if anyones sitting at the table
+ end
+ end)
+end
+
+--1,1,3,6
+function getCurrentHand(gameId,userId)
+ ----print("error debug #2")
+ ----print("gameId",gameId)
+ ----print("userId",userId)
+ --print(dump(blackjackGameData[gameId]))
+ ----print("=======")
+ if blackjackGameData[gameId][userId]["cardData"] ~= nil then
+ local hand = 0
+ local numberOfAces = 0
+ for k,v in pairs(blackjackGameData[gameId][userId]["cardData"]) do
+ local nextCard = getCardNumberFromCardId(v)
+ if nextCard == 11 then
+ numberOfAces = numberOfAces + 1
+ else
+ hand = hand + nextCard
+ end
+ end
+ for i=1,numberOfAces,1 do
+ if i == 1 then
+ if hand + 11 > 21 then
+ nextCard = 1
+ else
+ nextCard = 11
+ end
+ else
+ nextCard = 1
+ end
+ hand = hand + nextCard
+ end
+ return hand
+ end
+end
+
+function chairIdToTableId(chairId)
+ if chairId <= 3 then return 0 end
+ if chairId <= 7 then return 1 end
+ if chairId <= 11 then return 2 end
+ if chairId <= 15 then return 3 end
+end
+
+function getCardNumberFromCardId(cardId)
+ if cardId == 1 then
+ return 11
+ elseif cardId == 2 then
+ return 2
+ elseif cardId == 3 then
+ return 3
+ elseif cardId == 4 then
+ return 4
+ elseif cardId == 5 then
+ return 5
+ elseif cardId == 6 then
+ return 6
+ elseif cardId == 7 then
+ return 7
+ elseif cardId == 8 then
+ return 8
+ elseif cardId == 9 then
+ return 9
+ elseif cardId == 10 then
+ return 10
+ elseif cardId == 11 then
+ return 10
+ elseif cardId == 12 then
+ return 10
+ elseif cardId == 13 then
+ return 10
+ elseif cardId == 14 then
+ return 11
+ elseif cardId == 15 then
+ return 2
+ elseif cardId == 16 then
+ return 3
+ elseif cardId == 17 then
+ return 4
+ elseif cardId == 18 then
+ return 5
+ elseif cardId == 19 then
+ return 6
+ elseif cardId == 20 then
+ return 7
+ elseif cardId == 21 then
+ return 8
+ elseif cardId == 22 then
+ return 9
+ elseif cardId == 23 then
+ return 10
+ elseif cardId == 24 then
+ return 10
+ elseif cardId == 25 then
+ return 10
+ elseif cardId == 26 then
+ return 10
+ elseif cardId == 27 then
+ return 11
+ elseif cardId == 28 then
+ return 2
+ elseif cardId == 29 then
+ return 3
+ elseif cardId == 30 then
+ return 4
+ elseif cardId == 31 then
+ return 5
+ elseif cardId == 32 then
+ return 6
+ elseif cardId == 33 then
+ return 7
+ elseif cardId == 34 then
+ return 8
+ elseif cardId == 35 then
+ return 9
+ elseif cardId == 36 then
+ return 10
+ elseif cardId == 37 then
+ return 10
+ elseif cardId == 38 then
+ return 10
+ elseif cardId == 39 then
+ return 10
+ elseif cardId == 40 then
+ return 11
+ elseif cardId == 41 then
+ return 2
+ elseif cardId == 42 then
+ return 3
+ elseif cardId == 43 then
+ return 4
+ elseif cardId == 44 then
+ return 5
+ elseif cardId == 45 then
+ return 6
+ elseif cardId == 46 then
+ return 7
+ elseif cardId == 47 then
+ return 8
+ elseif cardId == 48 then
+ return 9
+ elseif cardId == 49 then
+ return 10
+ elseif cardId == 50 then
+ return 10
+ elseif cardId == 51 then
+ return 10
+ elseif cardId == 52 then
+ return 10
+ end
+end
+
+function isTableEmpty(self)
+ for _, _ in pairs(self) do
+ return false
+ end
+ return true
+end
+
+function getMoneyStringFormatted(cashString)
+ local i, j, minus, int, fraction = tostring(cashString):find('([-]?)(%d+)([.]?%d*)')
+
+ -- reverse the int-string and append a comma to all blocks of 3 digits
+ int = int:reverse():gsub("(%d%d%d)", "%1,")
+
+ -- reverse the int-string back remove an optional comma and put the
+ -- optional minus and fractional part back
+ return minus .. int:reverse():gsub("^,", "") .. fraction
+end
+
+function dump(o)
+ if type(o) == 'table' then
+ local s = '{ '
+ for k,v in pairs(o) do
+ if type(k) ~= 'number' then k = '"'..k..'"' end
+ s = s .. '['..k..'] = ' .. dump(v) .. ','
+ end
+ return s .. '} '
+ else
+ return tostring(o)
+ end
+ end
+
+-- RegisterCommand("debugtableserver",function()
+-- --print("blackjackTables")
+-- --print("===============")
+-- print(dump(blackjackTables))
+-- --print("blackjackGameData")
+-- --print("===============")
+-- print(dump(blackjackGameData))
+-- end)
+
+-- RegisterCommand("debugcarddata",function()
+-- --print("carddata")
+-- --print("===============")
+-- print(dump(blackjackGameData[1024]))
+-- end)
diff --git a/resources/[qb]/[qb_casino]/casino-insidetrack/client/client.lua b/resources/[qb]/[qb_casino]/casino-insidetrack/client/client.lua
new file mode 100644
index 0000000..fb73cf0
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-insidetrack/client/client.lua
@@ -0,0 +1,273 @@
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+local cooldown = 60
+local tick = 0
+local checkRaceStatus = false
+local insideTrackActive = false
+local gameOpen = false
+
+
+
+CreateThread(function()
+ local insideTrackZone = CircleZone:Create(vector3(955.619, 70.179, 70.433), 2.5, {
+ name="insideTrack",
+ heading=328.0,
+ debugPoly=false,
+ useZ=true,
+ })
+ insideTrackZone:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ if Config.HorseBetPrompt == 'walk-up' then
+ TriggerEvent('doj:casinoinsideTrackHeader')
+ elseif Config.HorseBetPrompt == 'peek' then
+ text = 'The Diamond Casino & Resort Inside Track'
+ exports['qb-core']:DrawText(text)
+ exports['qb-target']:AddCircleZone("Betting", vector3(956.121,70.185,70.433), 1.0, {
+ name="Betting",
+ heading=160,
+ debugPoly=false,
+ useZ=true,
+ }, {
+ options = {
+ {
+ event = "QBCore:client:openInsideTrack",
+ icon = "fas fa-coins",
+ label = "Start Betting",
+ },
+ },
+ distance = 3.0
+ })
+ end
+ else
+ exports['qb-menu']:closeMenu()
+ exports["qb-core"]:HideText()
+ end
+ end)
+end)
+
+RegisterNetEvent('doj:casinoinsideTrackHeader', function()
+ exports['qb-menu']:showHeader({
+ {
+ header = "The Diamond Casino & Resort Inside Track",
+ isMenuHeader = true,
+ },
+ {
+ header = "Start Horse Betting",
+ txt = "100 casino chips",
+ params = {
+ event = "QBCore:client:openInsideTrack",
+ }
+ },
+ {
+ header = "Cancel",
+ txt = "",
+ params = {
+ event = "doj:casinoinsideTrackHeader"
+ }
+ },
+ })
+end)
+
+local function OpenInsideTrack()
+ QBCore.Functions.TriggerCallback("insidetrack:server:getbalance", function(balance)
+ Utils.PlayerBalance = balance
+ end)
+
+ if insideTrackActive then
+ return
+ end
+ insideTrackActive = true
+ -- Scaleform
+ Utils.Scaleform = RequestScaleformMovie('HORSE_RACING_CONSOLE')
+ while not HasScaleformMovieLoaded(Utils.Scaleform) do
+ Wait(0)
+ end
+ DisplayHud(false)
+ SetPlayerControl(PlayerId(), false, 0)
+ while not RequestScriptAudioBank('DLC_VINEWOOD/CASINO_GENERAL') do
+ Wait(0)
+ end
+ Utils:ShowMainScreen()
+ Utils:SetMainScreenCooldown(cooldown)
+ -- Add horses
+ Utils:AddHorses()
+ Utils:DrawInsideTrack()
+ Utils:HandleControls()
+end
+
+function closeHorseBets()
+ insideTrackActive = false
+ SetPlayerControl(PlayerId(), true, 0)
+ SetScaleformMovieAsNoLongerNeeded(Utils.Scaleform)
+ Utils.Scaleform = -1
+ StopSound(0)
+end
+
+local function LeaveInsideTrack()
+ insideTrackActive = false
+ SetPlayerControl(PlayerId(), true, 0)
+ SetScaleformMovieAsNoLongerNeeded(Utils.Scaleform)
+ Utils.Scaleform = -1
+ StopSound(0)
+end
+
+RegisterNetEvent('QBCore:client:closeBetsNotEnough')
+AddEventHandler('QBCore:client:closeBetsNotEnough', function()
+ closeHorseBets()
+ QBCore.Functions.Notify("Bets Closed! You dont have enough Casino Chips...", "error", 3500)
+end)
+
+RegisterNetEvent('QBCore:client:closeBetsZeroChips')
+AddEventHandler('QBCore:client:closeBetsZeroChips', function()
+ closeHorseBets()
+ QBCore.Functions.Notify("Bets Closed! You dont have any Casino Chips...", "error", 3500)
+end)
+
+
+
+RegisterNetEvent('QBCore:client:openInsideTrack')
+AddEventHandler('QBCore:client:openInsideTrack', function()
+ -- QBCore.Functions.TriggerCallback('QBCore:HasItem', function(HasItem)
+ -- if HasItem then
+ OpenInsideTrack()
+ -- else
+ -- QBCore.Functions.Notify('You are not a member of the casino', 'error', 3500)
+ -- end
+ -- end, "casino_member")
+end)
+
+
+
+
+function Utils:DrawInsideTrack()
+ CreateThread(function()
+ while insideTrackActive do
+ Wait(0)
+ local xMouse, yMouse = GetDisabledControlNormal(2, 239), GetDisabledControlNormal(2, 240)
+ -- Fake cooldown
+ tick = (tick + 10)
+ if (tick == 1000) then
+ if (cooldown == 1) then
+ cooldown = 60
+ end
+ cooldown = (cooldown - 1)
+ tick = 0
+ Utils:SetMainScreenCooldown(cooldown)
+ end
+ -- Mouse control
+ BeginScaleformMovieMethod(Utils.Scaleform, 'SET_MOUSE_INPUT')
+ ScaleformMovieMethodAddParamFloat(xMouse)
+ ScaleformMovieMethodAddParamFloat(yMouse)
+ EndScaleformMovieMethod()
+ -- Draw
+ DrawScaleformMovieFullscreen(Utils.Scaleform, 255, 255, 255, 255)
+ end
+ end)
+end
+
+function Utils:HandleControls()
+ CreateThread(function()
+ while insideTrackActive do
+ Wait(0)
+
+
+ if IsControlJustPressed(2, 194) then
+ LeaveInsideTrack()
+ end
+
+ if IsControlJustPressed(2, 202) then
+ LeaveInsideTrack()
+ end
+
+ -- Left click
+ if IsControlJustPressed(2, 237) then
+ local clickedButton = Utils:GetMouseClickedButton()
+
+ if Utils.ChooseHorseVisible then
+ if (clickedButton ~= 12) and (clickedButton ~= -1) then
+ Utils.CurrentHorse = (clickedButton - 1)
+ Utils:ShowBetScreen(Utils.CurrentHorse)
+ Utils.ChooseHorseVisible = false
+ end
+ end
+
+ -- Rules button
+ if (clickedButton == 15) then
+ Utils:ShowRules()
+ end
+
+ -- Close buttons
+ if (clickedButton == 12) then
+ if Utils.ChooseHorseVisible then
+ Utils.ChooseHorseVisible = false
+ end
+
+ if Utils.BetVisible then
+ Utils:ShowHorseSelection()
+ Utils.BetVisible = false
+ Utils.CurrentHorse = -1
+ else
+ Utils:ShowMainScreen()
+ end
+ end
+
+ -- Start bet
+ if (clickedButton == 1) then
+ Utils:ShowHorseSelection()
+ end
+
+ -- Start race
+ if (clickedButton == 10) then
+ PlaySoundFrontend(-1, 'race_loop', 'dlc_vw_casino_inside_track_betting_single_event_sounds')
+ TriggerServerEvent("insidetrack:server:placebet", Utils.CurrentBet)
+ Utils:StartRace()
+ checkRaceStatus = true
+ end
+
+ -- Change bet
+ if (clickedButton == 8) then
+ if (Utils.CurrentBet < Utils.PlayerBalance) then
+ Utils.CurrentBet = (Utils.CurrentBet + 100)
+ Utils.CurrentGain = (Utils.CurrentBet * 2)
+ Utils:UpdateBetValues(Utils.CurrentHorse, Utils.CurrentBet, Utils.PlayerBalance, Utils.CurrentGain)
+ end
+ end
+
+ if (clickedButton == 9) then
+ if (Utils.CurrentBet > 100) then
+ Utils.CurrentBet = (Utils.CurrentBet - 100)
+ Utils.CurrentGain = (Utils.CurrentBet * 2)
+ Utils:UpdateBetValues(Utils.CurrentHorse, Utils.CurrentBet, Utils.PlayerBalance, Utils.CurrentGain)
+ end
+ end
+
+ if (clickedButton == 13) then
+ Utils:ShowMainScreen()
+ end
+
+ -- Check race
+ while checkRaceStatus do
+ Wait(0)
+ local raceFinished = Utils:IsRaceFinished()
+ if (raceFinished) then
+ StopSound(0)
+ if (Utils.CurrentHorse == Utils.CurrentWinner) then
+ TriggerServerEvent("insidetrack:server:winnings", Utils.CurrentGain)
+ end
+ QBCore.Functions.TriggerCallback("insidetrack:server:getbalance", function(balance)
+ Utils.PlayerBalance = balance
+ end)
+ Utils:UpdateBetValues(Utils.CurrentHorse, Utils.CurrentBet, Utils.PlayerBalance, Utils.CurrentGain)
+ Utils:ShowResults()
+ Utils.CurrentHorse = -1
+ Utils.CurrentWinner = -1
+ Utils.HorsesPositions = {}
+ checkRaceStatus = false
+ end
+ end
+ end
+ end
+ end)
+end
+
diff --git a/resources/[qb]/[qb_casino]/casino-insidetrack/client/utils.lua b/resources/[qb]/[qb_casino]/casino-insidetrack/client/utils.lua
new file mode 100644
index 0000000..24f5a9e
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-insidetrack/client/utils.lua
@@ -0,0 +1,377 @@
+
+
+Utils = {
+ Scaleform = -1,
+ ChooseHorseVisible = false,
+ BetVisible = false,
+ HorseStyles = {
+ {15553363,5474797,9858144,4671302},
+ {16724530,3684408,14807026,16777215},
+ {13560920,15582764,16770746,7500402},
+ {16558591,5090807,10446437,7493977},
+ {5090807,16558591,3815994,9393493},
+ {16269415,16767010,10329501,16777215},
+ {2263807,16777215,9086907,3815994},
+ {4879871,16715535,3815994,16777215},
+ {16777215,2263807,16769737,15197642},
+ {16338779,16777215,11166563,6974058},
+ {16777215,16559849,5716493,3815994},
+ {16760644,3387257,16701597,16777215},
+ {6538729,2249420,16777215,3815994},
+ {15913534,15913534,16304787,15985375},
+ {15655629,16240452,16760474,13664854},
+ {16320263,16777215,14920312,16773316},
+ {7176404,15138618,6308658,13664854},
+ {4879871,8453903,11382189,15724527},
+ {16777215,16777215,16754809,16777215},
+ {16732497,16732497,3815994,16777215},
+ {5739220,5739220,11382189,15724527},
+ {16712909,6935639,8742735,3877137},
+ {2136867,16777215,16761488,3877137},
+ {3118422,10019244,14932209,6121086},
+ {2136867,10241979,8081664,3815994},
+ {16769271,13724403,9852728,14138263},
+ {13724403,16769271,6444881,14138263},
+ {10017279,4291288,16304787,15985375},
+ {1071491,4315247,14935011,6121086},
+ {3861944,16627705,14932209,6121086},
+ {15583546,4671303,11836798,3090459},
+ {15567418,4671303,9985296,3815994},
+ {5701417,16711680,16771760,6970713},
+ {16760303,5986951,12353664,15395562},
+ {8907670,2709022,9475214,4278081},
+ {5429688,6400829,16777215,16773316},
+ {15138618,5272210,14920312,16773316},
+ {10241979,12396337,14920312,15395562},
+ {16777215,13481261,13667152,3815994},
+ {5077874,16777215,15444592,7820105},
+ {10408040,2960685,7424036,10129549},
+ {7754308,16777215,12944259,3815994},
+ {16736955,16106560,16771760,6970713},
+ {16106560,16770224,16767659,15843765},
+ {9573241,14703194,9789279,3815994},
+ {44799,14703194,10968156,16777215},
+ {7143224,16753956,10975076,4210752},
+ {7895160,4013373,5855577,11645361},
+ {16075595,6869196,13530742,7105644},
+ {16090955,6272992,16777215,16777215},
+ {13313356,13313356,5849409,11623516},
+ {13911070,5583427,14935011,6121086},
+ {8604661,10408040,12944259,3815994},
+ {9716612,2960685,16767659,6708313},
+ {7806040,16777215,16765601,14144436},
+ {15632075,11221989,16777215,16770037},
+ {1936722,14654697,16763851,3815994},
+ {10377543,3815994,14807026,16777215},
+ {16775067,11067903,16770746,7500402},
+ {16741712,8669718,16777215,16777215},
+ {16515280,6318459,3815994,9393493},
+ {65526,16515280,10329501,16777215},
+ {16711680,4783925,3815994,3815994},
+ {65532,4783925,16766671,15197642},
+ {16760303,16760303,3815994,14207663},
+ {16770048,16770048,3815994,3815994},
+ {16737792,16737792,11166563,6974058},
+ {12773119,12773119,5716493,3815994},
+ {16777215,16763043,16701597,16777215},
+ {6587161,6587161,16777215,3815994},
+ {6329328,16749602,3815994,3815994},
+ {15793920,16519679,14920312,15395562},
+ {15466636,10724259,16760474,13664854},
+ {11563263,327629,6308658,13664854},
+ {58867,16777215,16754809,8082236},
+ {4909311,16777215,5849409,11623516},
+ {3700643,7602233,9852728,14138263},
+ {16777215,1017599,8742735,3877137},
+ {16772022,16772022,16761488,3877137},
+ {7849983,5067443,8081664,3815994},
+ {15913534,7602233,6444881,14138263},
+ {12320733,16775618,11836798,3090459},
+ {15240846,16777215,9985296,3815994},
+ {14967137,3702939,3815994,14207663},
+ {6343571,3702939,12353664,15395562},
+ {16761374,15018024,9475214,4278081},
+ {16743936,3756172,16777215,16773316},
+ {2899345,5393472,16777215,4210752},
+ {11645361,16777215,16771542,10123632},
+ {3421236,5958825,16771542,3815994},
+ {15851871,5395026,15444592,7820105},
+ {16777215,9463517,7424036,10129549},
+ {16760556,16733184,16767659,15843765},
+ {4781311,15771930,16765601,14144436},
+ {16760556,10287103,16767659,6708313},
+ {13083490,16777215,9789279,3815994},
+ {13810226,9115524,5855577,11645361},
+ {14176336,9115524,13530742,7105644},
+ {16770310,16751169,16772294,16777215}
+ },
+ PlayerBalance = 500,
+ CurrentHorse = -1,
+ CurrentBet = 100,
+ CurrentGain = 1000,
+ HorsesPositions = {},
+ CurrentWiner = -1
+}
+
+
+
+
+function Utils:GetMouseClickedButton()
+ local returnValue = -1
+
+ CallScaleformMovieMethodWithNumber(self.Scaleform, 'SET_INPUT_EVENT', 237.0, -1082130432, -1082130432, -1082130432, -1082130432)
+ BeginScaleformMovieMethod(self.Scaleform, 'GET_CURRENT_SELECTION')
+
+ returnValue = EndScaleformMovieMethodReturnValue()
+
+ while not IsScaleformMovieMethodReturnValueReady(returnValue) do
+ Wait(0)
+ end
+
+ return GetScaleformMovieMethodReturnValueInt(returnValue)
+end
+
+function Utils.GetRandomHorseName()
+ local random = math.random(0, 99)
+ local randomName = (random < 10) and ('ITH_NAME_00'..random) or ('ITH_NAME_0'..random)
+
+ return randomName
+end
+
+-- int param :
+-- 0 = main
+-- 1 = choose a horse
+-- 2 = choose a horse (2)
+-- 3 = select a bet
+-- 4 = select a bet (2)
+-- 5 = race screen (frozen)
+-- 6 = photo finish (frozen)
+-- 7 = results
+-- 8 = same as main but a bit different
+-- 9 = rules
+function Utils:ShowMainScreen()
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(0)
+ EndScaleformMovieMethod()
+
+ BeginScaleformMovieMethod(Utils.Scaleform, 'SET_MAIN_EVENT_IN_PROGRESS')
+ ScaleformMovieMethodAddParamBool(true)
+ EndScaleformMovieMethod()
+
+ BeginScaleformMovieMethod(Utils.Scaleform, 'CLEAR_ALL')
+ EndScaleformMovieMethod()
+end
+
+---@param cooldown int
+---(in seconds).
+function Utils:SetMainScreenCooldown(cooldown)
+ BeginScaleformMovieMethod(self.Scaleform, 'SET_COUNTDOWN')
+ ScaleformMovieMethodAddParamInt(cooldown)
+ EndScaleformMovieMethod()
+end
+
+function Utils:SetNotAvailable()
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_ERROR')
+
+ BeginTextCommandScaleformString('IT_ERROR_TITLE')
+ EndTextCommandScaleformString()
+
+ BeginTextCommandScaleformString('IT_ERROR_MSG')
+ EndTextCommandScaleformString()
+
+ EndScaleformMovieMethod()
+end
+
+local function IsPositionAvailable(position)
+ for i = 1, #Utils.HorsesPositions do
+ if (Utils.HorsesPositions[i] == position) then
+ return false
+ end
+ end
+
+ return true
+end
+
+local function GenerateHorsesOrder()
+ while (#Utils.HorsesPositions < 6) do
+ Wait(0)
+
+ for i = 1, 6 do
+ local randomPos = math.random(6)
+
+ if IsPositionAvailable(randomPos) then
+ table.insert(Utils.HorsesPositions, randomPos)
+ end
+ end
+ end
+end
+
+function Utils:StartRace()
+ GenerateHorsesOrder()
+
+ self.CurrentWinner = self.HorsesPositions[1]
+
+ BeginScaleformMovieMethod(self.Scaleform, 'START_RACE')
+ ScaleformMovieMethodAddParamFloat(15000.0) -- Race duration (in MS)
+ ScaleformMovieMethodAddParamInt(4)
+
+ -- Add each horses by their index (win order)
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[1])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[2])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[3])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[4])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[5])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[6])
+
+ ScaleformMovieMethodAddParamFloat(0.0) -- Unk
+ ScaleformMovieMethodAddParamBool(false)
+ EndScaleformMovieMethod()
+end
+
+function Utils:IsRaceFinished()
+ BeginScaleformMovieMethod(Utils.Scaleform, 'GET_RACE_IS_COMPLETE')
+
+ local raceReturnValue = EndScaleformMovieMethodReturnValue()
+
+ while not IsScaleformMovieMethodReturnValueReady(raceReturnValue) do
+ Wait(0)
+ end
+
+ return GetScaleformMovieMethodReturnValueBool(raceReturnValue)
+end
+
+function Utils:ShowResults()
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(7)
+ EndScaleformMovieMethod()
+end
+
+function Utils:ShowRules()
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(9)
+ EndScaleformMovieMethod()
+end
+
+function Utils:ShowHorseSelection()
+ self.ChooseHorseVisible = true
+
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(1)
+ EndScaleformMovieMethod()
+end
+
+function Utils:AddHorses()
+ for i = 1, 6 do
+ local name = self.GetRandomHorseName()
+
+ BeginScaleformMovieMethod(self.Scaleform, 'SET_HORSE')
+ ScaleformMovieMethodAddParamInt(i) -- Horse index
+
+ -- Horse name
+ BeginTextCommandScaleformString(name)
+ EndTextCommandScaleformString()
+
+ ScaleformMovieMethodAddParamPlayerNameString('Cool Horse')
+
+ -- Horse style
+ ScaleformMovieMethodAddParamInt(self.HorseStyles[i][1])
+ ScaleformMovieMethodAddParamInt(self.HorseStyles[i][2])
+ ScaleformMovieMethodAddParamInt(self.HorseStyles[i][3])
+ ScaleformMovieMethodAddParamInt(self.HorseStyles[i][4])
+ EndScaleformMovieMethod()
+ end
+end
+
+local function IsPositionAvailable(position)
+ for i = 1, #Utils.HorsesPositions do
+ if (Utils.HorsesPositions[i] == position) then
+ return false
+ end
+ end
+
+ return true
+end
+
+local function GenerateHorsesOrder()
+ while (#Utils.HorsesPositions < 6) do
+ Wait(0)
+
+ for i = 1, 6 do
+ local randomPos = math.random(6)
+
+ if IsPositionAvailable(randomPos) then
+ table.insert(Utils.HorsesPositions, randomPos)
+ end
+ end
+ end
+end
+
+function Utils:StartRace()
+ GenerateHorsesOrder()
+
+ self.CurrentWinner = self.HorsesPositions[1]
+
+ BeginScaleformMovieMethod(self.Scaleform, 'START_RACE')
+ ScaleformMovieMethodAddParamFloat(15000.0) -- Race duration (in MS)
+ ScaleformMovieMethodAddParamInt(4)
+
+ -- Add each horses by their index (win order)
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[1])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[2])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[3])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[4])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[5])
+ ScaleformMovieMethodAddParamInt(self.HorsesPositions[6])
+
+ ScaleformMovieMethodAddParamFloat(0.0) -- Unk
+ ScaleformMovieMethodAddParamBool(false)
+ EndScaleformMovieMethod()
+end
+
+function Utils:IsRaceFinished()
+ BeginScaleformMovieMethod(Utils.Scaleform, 'GET_RACE_IS_COMPLETE')
+
+ local raceReturnValue = EndScaleformMovieMethodReturnValue()
+
+ while not IsScaleformMovieMethodReturnValueReady(raceReturnValue) do
+ Wait(0)
+ end
+
+ return GetScaleformMovieMethodReturnValueBool(raceReturnValue)
+end
+
+function Utils:ShowResults()
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(7)
+ EndScaleformMovieMethod()
+end
+
+function Utils:ShowRules()
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(9)
+ EndScaleformMovieMethod()
+end
+
+function Utils:ShowBetScreen(horse)
+ self:UpdateBetValues(horse, self.CurrentBet, self.PlayerBalance, self.CurrentGain)
+
+ BeginScaleformMovieMethod(self.Scaleform, 'SHOW_SCREEN')
+ ScaleformMovieMethodAddParamInt(3)
+ EndScaleformMovieMethod()
+
+ BeginScaleformMovieMethod(self.Scaleform, 'SET_BETTING_ENABLED')
+ ScaleformMovieMethodAddParamBool(true)
+ EndScaleformMovieMethod()
+
+ self.BetVisible = true
+end
+
+function Utils:UpdateBetValues(horse, bet, balance, gain)
+ BeginScaleformMovieMethod(self.Scaleform, 'SET_BETTING_VALUES')
+ ScaleformMovieMethodAddParamInt(horse) -- Horse index
+
+ ScaleformMovieMethodAddParamInt(bet) -- Bet
+ ScaleformMovieMethodAddParamInt(balance) -- Current balance
+ ScaleformMovieMethodAddParamInt(gain) -- Gain
+ EndScaleformMovieMethod()
+end
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/casino-insidetrack/config.lua b/resources/[qb]/[qb_casino]/casino-insidetrack/config.lua
new file mode 100644
index 0000000..b7f920f
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-insidetrack/config.lua
@@ -0,0 +1,4 @@
+Config = {}
+
+
+Config.HorseBetPrompt = 'walk-up' -- 'peek' or 'walk-up' ['walk-up' = walk up to open menu] ['peek' = uses qb-target to start bets]
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/casino-insidetrack/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-insidetrack/fxmanifest.lua
new file mode 100644
index 0000000..948440f
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-insidetrack/fxmanifest.lua
@@ -0,0 +1,20 @@
+fx_version 'cerulean'
+
+game 'gta5'
+
+description 'Rexhack Gaming : Inside-Track'
+
+version '1.0.1'
+
+client_scripts {
+ '@PolyZone/client.lua',
+ '@PolyZone/BoxZone.lua',
+ '@PolyZone/EntityZone.lua',
+ '@PolyZone/CircleZone.lua',
+ '@PolyZone/ComboZone.lua',
+ 'config.lua',
+ 'client/utils.lua',
+ 'client/client.lua',
+}
+
+server_script 'server/server.lua'
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/casino-insidetrack/server/server.lua b/resources/[qb]/[qb_casino]/casino-insidetrack/server/server.lua
new file mode 100644
index 0000000..d5a86cf
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-insidetrack/server/server.lua
@@ -0,0 +1,49 @@
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+QBCore.Functions.CreateCallback("insidetrack:server:getbalance", function(source, cb)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local Chips = Player.Functions.GetItemByName("casino_redchip")
+ local minAmount = 100
+ if Chips ~= nil then
+ if Chips.amount >= minAmount then
+ Chips = Chips
+ else
+ return TriggerClientEvent('QBCore:client:closeBetsNotEnough', src)
+ end
+ else
+ return TriggerClientEvent('QBCore:client:closeBetsZeroChips', src)
+ end
+end)
+
+RegisterServerEvent("insidetrack:server:placebet", function(bet)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local Chips = Player.Functions.GetItemByName("casino_redchip")
+ if Chips ~= nil then
+ if Chips.amount >= bet then
+ Player.Functions.RemoveItem("casino_redchip", bet)
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['casino_redchip'], "remove", bet)
+ TriggerClientEvent('QBCore:Notify', src, "You placed a "..bet.." casino chips bet")
+ else
+ return TriggerClientEvent('QBCore:client:closeBetsNotEnough', src)
+ end
+ else
+ return TriggerClientEvent('QBCore:client:closeBetsZeroChips', src)
+ end
+end)
+
+RegisterServerEvent("insidetrack:server:winnings", function(amount)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ if Player ~= nil then
+ if Player.Functions.AddItem('casino_redchip', amount, nil, {["quality"] = 100}) then
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["casino_redchip"], "add", amount)
+ TriggerClientEvent('QBCore:Notify', src, "You Won "..amount.." casino chips!")
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'You have to much in your pockets', 'error')
+ end
+ end
+end)
+
diff --git a/resources/[qb]/[qb_casino]/casino-luckywheel/client.lua b/resources/[qb]/[qb_casino]/casino-luckywheel/client.lua
new file mode 100644
index 0000000..60d5c8a
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-luckywheel/client.lua
@@ -0,0 +1,418 @@
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+local car, h
+local _wheel, _base, _lights1, _lights2, _arrow1, _arrow2 = nil, nil, nil, nil, nil, nil
+
+
+local m1a = GetHashKey('vw_prop_vw_luckylight_off')
+local m1b = GetHashKey('vw_prop_vw_luckylight_on')
+local m2a = GetHashKey('vw_prop_vw_jackpot_off')
+local m2b = GetHashKey('vw_prop_vw_jackpot_on')
+
+local _wheelPos = Config.WheelPos
+local _isRolling = false
+
+
+-- Car on podium, Start
+local ped
+Citizen.CreateThread(function()
+ while 1 do
+ ped = PlayerPedId()
+ Wait(5000)
+ end
+end)
+spawned = nil
+
+Citizen.CreateThread(function()
+ while 1 do
+ local pCoords = GetEntityCoords(PlayerPedId())
+ for i=1, #Config.Cars do
+ if #(pCoords - Config.Cars[i].pos) < Config.ShowRange then
+ if Config.Cars[i].spawned == nil then
+ SpawnLocalCar(i)
+ end
+ else
+ DeleteEntity(Config.Cars[i].spawned)
+ Config.Cars[i].spawned = nil
+ end
+ Wait(500)
+ end
+ end
+end)
+
+Citizen.CreateThread(function()
+ local ped = ped
+ while true do
+ Citizen.Wait(0)
+ local pl = GetEntityCoords(ped, true)
+ for k, v in pairs(Config.Cars) do
+ if GetDistanceBetweenCoords(pl.x, pl.y, pl.z, v.pos.x, v.pos.y, v.pos.z, true) < Config.ShowRange then
+ Draw3DText(v.pos.x, v.pos.y, v.pos.z - 0.5, v.text, 0, 0.1, 0.1)
+ end
+ end
+ end
+end)
+
+Citizen.CreateThread(function()
+ while 1 do
+ for i=1, #Config.Cars do
+ if Config.Cars[i].spawned ~= nil and Config.Cars[i].spin then
+ SetEntityHeading(Config.Cars[i].spawned, GetEntityHeading(Config.Cars[i].spawned) + 0.069)
+ end
+ end
+ Wait(5)
+ end
+end)
+
+function SpawnLocalCar(i)
+ Citizen.CreateThread(function()
+ local hash = GetHashKey(Config.Cars[i].model)
+ RequestModel(hash)
+ local attempt = 0
+ while not HasModelLoaded(hash) do
+ attempt = attempt + 1
+ if attempt > 2000 then return end
+ Wait(0)
+ end
+ local veh = CreateVehicle(hash, Config.Cars[i].pos.x, Config.Cars[i].pos.y, Config.Cars[i].pos.z-1, Config.Cars[i].heading, false, false)
+ SetModelAsNoLongerNeeded(hash)
+ SetVehicleEngineOn(veh, false, true, true)
+ SetVehicleBrakeLights(veh, false)
+ SetVehicleLights(veh, 0)
+ SetVehicleLightsMode(veh, 0)
+ SetVehicleInteriorlight(veh, true)
+ SetVehicleOnGroundProperly(veh)
+ FreezeEntityPosition(veh, true)
+ SetVehicleCanBreak(veh, false)
+ SetVehicleFullbeam(veh, false)
+ SetVehicleReceivesRampDamage(veh, true)
+ RemoveDecalsFromVehicle(veh)
+ SetVehicleCanBeVisiblyDamaged(veh, false)
+ SetVehicleLightsCanBeVisiblyDamaged(veh, false)
+ SetVehicleWheelsCanBreakOffWhenBlowUp(veh, false)
+ SetDisableVehicleWindowCollisions(veh, true)
+ SetEntityInvincible(veh, true)
+ SetVehicleDoorsLocked(veh, 2)
+ SetVehicleNumberPlateText(veh, Config.Cars[i].plate)
+ Config.Cars[i].spawned = veh
+ end)
+end
+
+AddEventHandler('onResourceStop', function(res)
+ if res == GetCurrentResourceName() then
+ for i=1, #Cars do
+ if Config.Cars[i].spawned ~= nil then
+ DeleteEntity(Config.Cars[i].spawned)
+ end
+ end
+ end
+end)
+
+function Draw3DText(x, y, z, textInput, fontId, scaleX, scaleY)
+ local px, py, pz = table.unpack(GetGameplayCamCoords())
+ local dist = GetDistanceBetweenCoords(px, py, pz, x, y, z, true)
+ local scale = (1 / dist) * 20
+ local fov = (1 / GetGameplayCamFov()) * 100
+ local scale = scale * fov
+ SetTextScale(scaleX * scale, scaleY * scale)
+ SetTextFont(fontId)
+ SetTextProportional(1)
+ SetTextColour(250, 250, 250, 255)
+ SetTextDropshadow(1, 1, 1, 1, 255)
+ SetTextEdge(2, 0, 0, 0, 150)
+ SetTextOutline()
+ SetTextEntry("STRING")
+ SetTextCentre(1)
+ AddTextComponentString(textInput)
+ SetDrawOrigin(x, y, z + 2, 0)
+ DrawText(0.0, 0.0)
+ ClearDrawOrigin()
+end
+
+-- Car on podium, End
+
+CreateThread(function()
+ RequestScriptAudioBank("DLC_VINEWOOD\\CASINO_GENERAL", false)
+ local model1 = GetHashKey('vw_prop_vw_luckywheel_02a')
+ local model2 = GetHashKey('vw_prop_vw_luckywheel_01a')
+ local podiumModel = GetHashKey('vw_prop_vw_casino_podium_01a')
+ CreateThread(function()
+ RequestModel(model1) while not HasModelLoaded(model1) do Wait(0) end
+ RequestModel(model2) while not HasModelLoaded(model2) do Wait(0) end
+ RequestModel(m1a) while not HasModelLoaded(m1a) do Wait(0) end
+ RequestModel(m1b) while not HasModelLoaded(m1b) do Wait(0) end
+ RequestModel(m2a) while not HasModelLoaded(m2a) do Wait(0) end
+ RequestModel(m2b) while not HasModelLoaded(m2b) do Wait(0) end
+ ClearArea(Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z, 5.0, true, false, false, false)
+ _wheel = CreateObject(model1, Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z, false, false, true)
+ SetEntityHeading(_wheel, Config.WheelPos.h)
+ SetModelAsNoLongerNeeded(model1)
+ _base = CreateObject(model2, Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z-0.26, false, false, true)
+ SetEntityHeading(_base, Config.WheelPos.h)
+ SetModelAsNoLongerNeeded(_base)
+ _lights1 = CreateObject(m1a, Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z+0.35, false, false, true)
+ SetEntityHeading(_lights1, Config.WheelPos.h)
+ SetModelAsNoLongerNeeded(_lights1)
+ _lights2 = CreateObject(m1b, Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z+0.35, false, false, true)
+ SetEntityVisible(_lights2, false, 0)
+ SetEntityHeading(_lights2, Config.WheelPos.h)
+ SetModelAsNoLongerNeeded(_lights2)
+ _arrow1 = CreateObject(m2a, Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z+2.5, false, false, true)
+ SetEntityHeading(_arrow1, Config.WheelPos.h)
+ SetModelAsNoLongerNeeded(_arrow1)
+ _arrow2 = CreateObject(m2b, Config.WheelPos.x, Config.WheelPos.y, Config.WheelPos.z+2.5, false, false, true)
+ SetEntityVisible(_arrow2, false, 0)
+ SetEntityHeading(_arrow2, Config.WheelPos.h)
+ SetModelAsNoLongerNeeded(_arrow2)
+ h = GetEntityRotation(_wheel)
+ end)
+end)
+
+CreateThread(function()
+ local LuckyWheelZone = CircleZone:Create(vector3(949.71, 45.1, 70.9), 2.5, {
+ name="LuckyWheelZone",
+ heading=328.0,
+ debugPoly=false,
+ useZ=true,
+ })
+ LuckyWheelZone:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ text = "The Diamond Casino & ResortLucky Wheel "..Config.startingPrice..",- a spin"
+ exports['qb-core']:DrawText(text, "top")
+ exports['qb-target']:AddCircleZone("LuckyWheel", vector3(949.391, 44.72, 71.638), 2.0, {
+ name="LuckyWheel",
+ heading=160,
+ debugPoly=false,
+ useZ=true,
+ }, {
+ options = {
+ {
+ event = "luckywheel:client:startWheel",
+ icon = "fas fa-sync-alt",
+ label = "Try Your Luck",
+ },
+ },
+ distance = 2.0
+ })
+ else
+ exports['qb-menu']:closeMenu()
+ exports["qb-core"]:HideText()
+ end
+ end)
+end)
+
+RegisterNetEvent('doj:casinoLuckyWheelHeader', function()
+ exports['qb-menu']:showHeader({
+ {
+ header = "The Diamond Casino & Resort Lucky Wheel",
+ isMenuHeader = true,
+ },
+ {
+ header = "Try Your Luck",
+ txt = "$"..Config.startingPrice.." a spin",
+ params = {
+ event = "luckywheel:client:startWheel",
+ }
+ },
+ {
+ header = "Cancel",
+ txt = "",
+ params = {
+ event = "doj:casinoLuckyWheelHeader"
+ }
+ },
+ })
+end)
+
+-- RegisterNetEvent("luckywheel:client:startWheel", function()
+-- QBCore.Functions.TriggerCallback('QBCore.Functions.HasItem', function(HasItem)
+-- if HasItem then
+-- TriggerServerEvent("luckywheel:getwheel")
+-- else
+-- QBCore.Functions.Notify('You are not a V.I.P of the casino', 'error', 3500)
+-- end
+-- end, "casino_vip")
+-- end)
+
+
+RegisterNetEvent("luckywheel:client:startWheel", function()
+ QBCore.Functions.TriggerCallback('doj:server:HasVIPMembership', function(HasItem)
+ if HasItem then
+ TriggerServerEvent("luckywheel:getwheel")
+ else
+ QBCore.Functions.Notify('You dont have a V.I.P Membership!', 'error', 3500)
+ text = 'The Diamond Casino & ResortPlease visit the front desk!'
+ exports['qb-core']:DrawText(text, "top")
+ end
+ end)
+end)
+
+RegisterNetEvent("luckywheel:syncanim", function()
+ doRoll(0)
+end)
+
+RegisterNetEvent("luckywheel:startroll", function(s, index, p)
+ Wait(1000)
+ SetEntityVisible(_lights1, false, 0)
+ SetEntityVisible(_lights2, true, 0)
+ win = (index - 1) * 18 + 0.0
+ local j = 360
+ if s == GetPlayerServerId(PlayerId()) then
+ PlaySoundFromEntity(-1, "Spin_Start", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ end
+ for i=1,1100,1 do
+ SetEntityRotation(_wheel, h.x, j+0.0, h.z, 0, false)
+ if i < 50 then
+ j = j - 1.5
+ elseif i < 100 then
+ j = j - 2.0
+ elseif i < 150 then
+ j = j - 2.5
+ elseif i > 1060 then
+ j = j - 0.3
+ elseif i > 1030 then
+ j = j - 0.6
+ elseif i > 1000 then
+ j = j - 0.9
+ elseif i > 970 then
+ j = j - 1.2
+ elseif i > 940 then
+ j = j - 1.5
+ elseif i > 910 then
+ j = j - 1.8
+ elseif i > 880 then
+ j = j - 2.1
+ elseif i > 850 then
+ j = j - 2.4
+ elseif i > 820 then
+ j = j - 2.7
+ else
+ j = j - 3.0
+ end
+ if i == 850 then j = math.random(win-4, win+10) + 0.0 end
+ if j > 360 then j = j + 0 end
+ if j < 0 then j = j + 360 end
+ if i == 900 then
+ end
+ Wait(0)
+ end
+ Wait(300)
+ SetEntityVisible(_arrow1, false, 0)
+ SetEntityVisible(_arrow2, true, 0)
+ local t = true
+ if s == GetPlayerServerId(PlayerId()) then
+ if p.sound == 'car' then
+ PlaySoundFromEntity(-1, "Win_Car", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ elseif p.sound == 'cash' then
+ PlaySoundFromEntity(-1, "Win_Cash", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ elseif p.sound == 'chips' then
+ PlaySoundFromEntity(-1, "Win_Chips", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ elseif p.sound == 'clothes' then
+ PlaySoundFromEntity(-1, "Win_Clothes", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ elseif p.sound == 'mystery' then
+ PlaySoundFromEntity(-1, "Win_Mystery", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ else
+ PlaySoundFromEntity(-1, "Win", _wheel, 'dlc_vw_casino_lucky_wheel_sounds', 1, 1)
+ end
+ end
+ for i=1,15,1 do
+ Wait(200)
+ SetEntityVisible(_lights1, t, 0)
+ SetEntityVisible(_arrow2, t, 0)
+ t = not t
+ SetEntityVisible(_lights2, t, 0)
+ SetEntityVisible(_arrow1, t, 0)
+ if i == 5 then
+ if s == GetPlayerServerId(PlayerId()) then
+ TriggerServerEvent('luckywheel:give', s, p)
+ end
+ end
+ end
+ Wait(1000)
+ SetEntityVisible(_lights1, true, 0)
+ SetEntityVisible(_lights2, false, 0)
+ SetEntityVisible(_arrow1, true, 0)
+ SetEntityVisible(_arrow2, false, 0)
+ TriggerServerEvent('luckywheel:stoproll')
+end)
+
+RegisterNetEvent("luckywheel:rollFinished", function()
+ _isRolling = false
+end)
+
+function QBCoreRequestAnimDict(animDict, cb)
+ if not HasAnimDictLoaded(animDict) then
+ RequestAnimDict(animDict)
+
+ while not HasAnimDictLoaded(animDict) do
+ Wait(1)
+ end
+ end
+
+ if cb ~= nil then
+ cb()
+ end
+end
+
+function doRoll(index)
+ if not _isRolling then
+ exports["qb-core"]:HideText()
+ _isRolling = true
+ local playerPed = PlayerPedId()
+ local _lib = 'anim_casino_a@amb@casino@games@lucky7wheel@female'
+ if IsPedMale(playerPed) then
+ _lib = 'anim_casino_a@amb@casino@games@lucky7wheel@male'
+ end
+ local lib, anim = _lib, 'enter_right_to_baseidle'
+
+ QBCoreRequestAnimDict(lib, function()
+ local _movePos = GetObjectOffsetFromCoords(GetEntityCoords(_base), GetEntityHeading(_base),-0.9, -0.8, -1.0)
+ TaskGoStraightToCoord(playerPed, _movePos.x, _movePos.y, _movePos.z, 1.0, 3000, GetEntityHeading(_base), 0.0)
+ local _isMoved = false
+ while not _isMoved do
+ local coords = GetEntityCoords(PlayerPedId())
+ if coords.x >= (_movePos.x - 0.01) and coords.x <= (_movePos.x + 0.01) and coords.y >= (_movePos.y - 0.01) and coords.y <= (_movePos.y + 0.01) then
+ _isMoved = true
+ end
+ Wait(0)
+ end
+ SetEntityHeading(playerPed, GetEntityHeading(_base))
+ TaskPlayAnim(playerPed, lib, anim, 8.0, -8.0, -1, 0, 0, false, false, false)
+ while IsEntityPlayingAnim(playerPed, lib, anim, 3) do
+ Wait(0)
+ DisableAllControlActions(0)
+ end
+ TaskPlayAnim(playerPed, lib, 'enter_to_armraisedidle', 8.0, -8.0, -1, 0, 0, false, false, false)
+ while IsEntityPlayingAnim(playerPed, lib, 'enter_to_armraisedidle', 3) do
+ Wait(0)
+ DisableAllControlActions(0)
+ end
+ TaskPlayAnim(playerPed, lib, 'armraisedidle_to_spinningidle_high', 8.0, -8.0, -1, 0, 0, false, false, false)
+ Wait(4800)
+ TaskStartScenarioInPlace(playerPed, "WORLD_HUMAN_STRIP_WATCH_STAND", 0, true)
+ Wait(4800)
+ ClearPedTasks(playerPed)
+ end)
+ end
+end
+
+
+
+RegisterNetEvent('dojLuckywheel:winCar', function(plate)
+ local ped = PlayerPedId()
+ local coords = Config.VehicleSpawnCoords
+ QBCore.Functions.TriggerCallback('QBCore:Server:SpawnVehicle', function(netId)
+ local veh = NetToVeh(netId)
+ SetVehicleNumberPlateText(veh, Config.VehiclePlateText)
+ TaskWarpPedIntoVehicle(PlayerPedId(), veh, -1)
+ SetVehicleFuelLevel(veh, 100)
+ TriggerEvent("vehiclekeys:client:SetOwner", Config.VehiclePrize)
+ TriggerServerEvent('luckywheel:server:setVehicleOwner')
+ QBCore.Functions.SetVehicleProperties(veh, vehmods)
+ end, Config.VehiclePrize, coords, true)
+end)
+
+
+
+
diff --git a/resources/[qb]/[qb_casino]/casino-luckywheel/config.lua b/resources/[qb]/[qb_casino]/casino-luckywheel/config.lua
new file mode 100644
index 0000000..19b76ef
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-luckywheel/config.lua
@@ -0,0 +1,56 @@
+Config = {}
+
+
+Config.WheelPos = {x = 949.71, y = 45.1, z = 70.9, h =328.0} -- Where the wheel prop will spawn OR where wheel prop is
+Config.startingPrice = 5000
+Config.VehiclePrize = 'p90d'
+Config.VehicleSpawnCoords = vector4(933.29, -2.82, 78.76, 144.6)
+Config.VehiclePlateText = 'CASINO'
+
+
+Config.LimitedSpins = false -- [true = players spin once per day for free] [false= $5000 a spin]
+Config.LimitedSpinResetTime = 3600000 -- 1 hour real time
+
+
+-- Config for car on podium
+Config.ShowRange = 200
+Config.Cars = {
+ {
+ pos = vector3(935.3839, 42.5959, 72.5251),
+ heading = 192.56,
+ model = 'p90d',
+ spin = true,
+ text = "",
+ plate = "CASINO"
+ }
+}
+
+
+-- type = [weapon, money, item, car] (for money it will give only in bank)
+-- name = item in the database
+-- count = amount to receive
+-- sound = [car, cash, clothes, chips, mystery, win]
+
+
+Config.Prices = {
+ [1] = {type = 'car', name = 'car', count = 1, sound = 'car', probability = {a = 0, b = 1}}, -- 0.1 % 0.1 -- VEHICLE
+ [2] = {type = 'money', name = 'money', count = 15000, sound = 'cash', probability = {a = 1, b = 5}}, -- 0.4 % 0.5 -- 15.000 RP
+ [3] = {type = 'item', name = 'casino_vip', count = 1, sound = 'clothes', probability = {a = 5, b = 10}}, -- 0.5 % 1.0 -- CLOTHING
+ [4] = {type = 'item', name = 'casino_redchip', count = 25000, sound = 'chips', probability = {a = 10, b = 20}}, -- 1.0 % 2.0 -- 25.000 chips
+ [5] = {type = 'money', name = 'money', count = 40000, sound = 'cash', probability = {a = 20, b = 40}}, -- 2.0 % 4.0 -- 40.000 $
+ [6] = {type = 'money', name = 'money', count = 10000, sound = 'cash', probability = {a = 40, b = 60}}, -- 2.0 % 6.0 -- 10.000 RP
+ [7] = {type = 'item', name = 'bread', count = 1, sound = 'clothes', probability = {a = 60, b = 80}}, -- 4.0 % 8.0 -- CLOTHING
+ [8] = {type = 'item', name = 'casino_vip', count = 1, sound = 'mystery', probability = {a = 80, b = 120}}, -- 4.0 % 12.0 -- MYSTERY
+ [9] = {type = 'item', name = 'casino_redchip', count = 20000, sound = 'chips', probability = {a = 120, b = 170}}, -- 5.0 % 17.0 -- 20.000 chips
+ [10] = {type = 'money', name = 'money', count = 7500, sound = 'cash', probability = {a = 170, b = 250}}, -- 5.0 % 22.0 -- 7.500 RP
+ [11] = {type = 'item', name = 'bread', count = 1, sound = 'clothes', probability = {a = 250, b = 300}}, -- 6.0 % 28.0 -- CLOTHING
+ [12] = {type = 'item', name = 'casino_redchip', count = 15000, sound = 'chips', probability = {a = 300, b = 340}}, -- 6.0 % 34.0 -- 15.000 chips
+ [13] = {type = 'money', name = 'money', count = 30000, sound = 'cash', probability = {a = 340, b = 380}}, -- 7.0 % 41.0 -- 30.000 $
+ [14] = {type = 'money', name = 'money', count = 5000, sound = 'cash', probability = {a = 380, b = 540}}, -- 7.0 % 48.0 -- 5.000 RP
+ [15] = {type = 'weapon', name = 'weapon_pistol', count = 1, sound = 'mystery', probability = {a = 540, b = 610}}, -- 8.0 % 56.0 -- DISCOUNT
+ [16] = {type = 'item', name = 'casino_redchip', count = 10000, sound = 'chips', probability = {a = 610, b = 640}}, -- 8.0 % 64.0 -- 10.000 chips
+ [17] = {type = 'money', name = 'money', count = 20000, sound = 'cash', probability = {a = 640, b = 700}}, -- 8.0 % 72.0 -- 20.000 $
+ [18] = {type = 'money', name = 'money', count = 2500, sound = 'cash', probability = {a = 700, b = 810}}, -- 9.0 % 81.0 -- 2.500 RP
+ [19] = {type = 'item', name = 'bread', count = 1, sound = 'clothes', probability = {a = 810, b = 990}}, -- 9.0 % 90.0 -- CLOTHING
+ [20] = {type = 'money', name = 'money', count = 50000, sound = 'cash', probability = {a = 990, b = 1000}}, -- 1.0 % -- 50.000 $
+}
diff --git a/resources/[qb]/[qb_casino]/casino-luckywheel/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-luckywheel/fxmanifest.lua
new file mode 100644
index 0000000..271c3a9
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-luckywheel/fxmanifest.lua
@@ -0,0 +1,49 @@
+
+
+fx_version 'cerulean'
+game 'gta5'
+description 'Lucky Wheel'
+
+
+server_script 'server.lua'
+
+client_scripts {
+ '@PolyZone/client.lua',
+ '@PolyZone/BoxZone.lua',
+ '@PolyZone/EntityZone.lua',
+ '@PolyZone/CircleZone.lua',
+ '@PolyZone/ComboZone.lua',
+ 'client.lua',
+}
+
+shared_script 'config.lua'
+
+-- files {
+-- 'audio/dlcvinewood_amp.dat10',
+-- 'audio/dlcvinewood_amp.dat10.nametable',
+-- 'audio/dlcvinewood_amp.dat10.rel',
+-- 'audio/dlcvinewood_game.dat151',
+-- 'audio/dlcvinewood_game.dat151.nametable',
+-- 'audio/dlcvinewood_game.dat151.rel',
+-- 'audio/dlcvinewood_mix.dat15',
+-- 'audio/dlcvinewood_mix.dat15.nametable',
+-- 'audio/dlcvinewood_mix.dat15.rel',
+-- 'audio/dlcvinewood_sounds.dat54',
+-- 'audio/dlcvinewood_sounds.dat54.nametable',
+-- 'audio/dlcvinewood_sounds.dat54.rel',
+-- 'audio/dlcvinewood_speech.dat4',
+-- 'audio/dlcvinewood_speech.dat4.nametable',
+-- 'audio/dlcvinewood_speech.dat4.rel',
+-- 'audio/sfx/dlc_vinewood/casino_general.awc',
+-- 'audio/sfx/dlc_vinewood/casino_interior_stems.awc',
+-- 'audio/sfx/dlc_vinewood/casino_slot_machines_01.awc',
+-- 'audio/sfx/dlc_vinewood/casino_slot_machines_02.awc',
+-- 'audio/sfx/dlc_vinewood/casino_slot_machines_03.awc'
+-- }
+
+-- data_file 'AUDIO_GAMEDATA' 'audio/dlcvinewood_game.dat'
+-- data_file 'AUDIO_SOUNDDATA' 'audio/dlcvinewood_sounds.dat'
+-- data_file 'AUDIO_DYNAMIXDATA' 'audio/dlcvinewood_mix.dat'
+-- data_file 'AUDIO_SYNTHDATA' 'audio/dlcVinewood_amp.dat'
+-- data_file 'AUDIO_SPEECHDATA' 'audio/dlcvinewood_speech.dat'
+-- data_file 'AUDIO_WAVEPACK' 'audio/sfx/dlc_vinewood'
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/casino-luckywheel/luckywheel.sql b/resources/[qb]/[qb_casino]/casino-luckywheel/luckywheel.sql
new file mode 100644
index 0000000..baa30c9
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-luckywheel/luckywheel.sql
@@ -0,0 +1,2 @@
+
+ALTER TABLE `players` ADD COLUMN `luckywheel_spins` VARCHAR(1) NULL DEFAULT '0'
diff --git a/resources/[qb]/[qb_casino]/casino-luckywheel/server.lua b/resources/[qb]/[qb_casino]/casino-luckywheel/server.lua
new file mode 100644
index 0000000..1b0d347
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-luckywheel/server.lua
@@ -0,0 +1,120 @@
+math.randomseed(os.time())
+
+local QBCore = exports['qb-core']:GetCoreObject()
+isRoll = false
+-- local car = Config.Cars[math.random(#Config.Cars)]
+
+if Config.LimitedSpins then
+ Citizen.CreateThread(function()
+ while true do
+ Wait(1000*60)
+ if os.date('%H:%M') == Config.LimitedSpins then
+ exports.oxmysql:execute('UPDATE players SET luckywheel_spins = 0')
+ end
+ end
+ end)
+end
+
+RegisterNetEvent('luckywheel:getwheel', function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ if Config.LimitedSpins == true then
+ local result = exports.oxmysql:scalarSync('SELECT luckywheel_spins FROM players where citizenid= ?', {Player.PlayerData.citizenid})
+ if result == '0' then
+ TriggerEvent("luckywheel:startwheel", Player, src)
+ else
+ TriggerClientEvent('QBCore:Notify', src, "You have already had a spin on the wheel today", "error")
+ end
+ elseif Config.LimitedSpins == false then
+ if Player.PlayerData.money["bank"] >= Config.startingPrice then
+ Player.Functions.RemoveMoney("bank", tonumber(Config.startingPrice), "lucky-wheel")
+ TriggerEvent("luckywheel:startwheel", Player, src)
+ else
+ -- return TriggerClientEvent('QBCore:Notify', src, "You have enough in the bank to spin", "error")
+ TriggerClientEvent('QBCore:Notify', src, "You have enough in the bank to spin", "error")
+ end
+ end
+end)
+
+RegisterNetEvent('luckywheel:startwheel', function(Player, source)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ if not isRoll then
+ if Player ~= nil then
+ exports.oxmysql:execute('UPDATE players SET luckywheel_spins = 1 where citizenid= ?', {Player.PlayerData.citizenid})
+ isRoll = true
+ local rnd = math.random(1, 1000)
+ local price = 0
+ local priceIndex = 0
+ for k,v in pairs(Config.Prices) do
+ if (rnd > v.probability.a) and (rnd <= v.probability.b) then
+ price = v
+ priceIndex = k
+ break
+ end
+ end
+ TriggerClientEvent("luckywheel:syncanim", src, priceIndex)
+ TriggerClientEvent("luckywheel:startroll", -1, src, priceIndex, price)
+ end
+ end
+end)
+
+RegisterNetEvent('luckywheel:give', function(source, price)
+ local Player = QBCore.Functions.GetPlayer(source)
+ isRoll = false
+ if price.type == 'car' then
+ TriggerClientEvent("dojLuckywheel:winCar", source)
+ TriggerClientEvent("chCasinoWall:bigWin", source)
+ elseif price.type == 'item' then
+ TriggerClientEvent("chCasinoWall:bigWin", source)
+ Player.Functions.AddItem(price.name, price.count, slot)
+ TriggerClientEvent('QBCore:Notify', source, "Congratulations! You won "..price.count.." "..price.name.."!", 'success')
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items[price.name], "add",price.count )
+ elseif price.type == 'money' then
+ TriggerClientEvent("chCasinoWall:bigWin", source)
+ Player.Functions.AddMoney('bank', tonumber(price.count), 'banking-quick-depo')
+ TriggerClientEvent('QBCore:Notify', source, "Congratulations! You won $"..price.count, 'success')
+ elseif price.type == 'weapon' then
+ TriggerClientEvent("chCasinoWall:bigWin", source)
+ Player.Functions.AddItem(price.name, 1, slot)
+ TriggerClientEvent('QBCore:Notify', source, "Congratulations! You won a Pistol!", 'success')
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items[price.name], "add",1)
+ end
+ TriggerClientEvent("luckywheel:rollFinished", -1)
+end)
+
+RegisterNetEvent('luckywheel:stoproll', function()
+ isRoll = false
+end)
+
+RegisterNetEvent('luckywheel:server:setVehicleOwner', function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local cid = Player.PlayerData.citizenid
+ local vehicle = Config.VehiclePrize
+ local plate = GeneratePlate()
+ exports.oxmysql:insert('INSERT INTO player_vehicles (license, citizenid, vehicle, hash, mods, plate, state) VALUES (?, ?, ?, ?, ?, ?, ?)', {
+ Player.PlayerData.license,
+ cid,
+ vehicle,
+ GetHashKey(vehicle),
+ '{}',
+ -- plate,
+ Config.VehiclePlateText,
+ 0
+ })
+ TriggerClientEvent('QBCore:Notify', src, "YOU WON THE SHOW CAR! congratulations!", 'success')
+end)
+
+
+function GeneratePlate()
+ local plate = QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(2)
+ local result = exports.oxmysql:scalarSync('SELECT plate FROM player_vehicles WHERE plate = ?', {plate})
+ if result then
+ return GeneratePlate()
+ else
+ return plate:upper()
+ end
+end
+
+
diff --git a/resources/[qb]/[qb_casino]/casino-luckywheel/stream/vw_prop_vw_luckywheel.ytd b/resources/[qb]/[qb_casino]/casino-luckywheel/stream/vw_prop_vw_luckywheel.ytd
new file mode 100644
index 0000000..b6a7d06
Binary files /dev/null and b/resources/[qb]/[qb_casino]/casino-luckywheel/stream/vw_prop_vw_luckywheel.ytd differ
diff --git a/resources/[qb]/[qb_casino]/casino-poker/client/cl_main.lua b/resources/[qb]/[qb_casino]/casino-poker/client/cl_main.lua
new file mode 100644
index 0000000..91206fe
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-poker/client/cl_main.lua
@@ -0,0 +1,2091 @@
+QBCore = exports['qb-core']:GetCoreObject()
+
+SharedPokers = {}
+closeToPokers = false
+
+function ShowHelpNotification(msg)
+ exports["qb-core"]:DrawText(msg)
+ -- exports["qb-core"]:DrawText("Diamond Casino Poker"..msg)
+ -- exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino Poker"..reactiveText)
+end
+
+local mainScene = nil -- the main sitting scene, we need it globally, for the exit
+local activePokerTable = nil -- current table Id where we are sitting
+local activeChairData = nil -- chair data, it is a table with rotation and coords
+local currentBetInput = 0 -- currently bet input
+
+local playerBetted = nil -- important, because when it changes to TRUE, we are disabling the standup, etc
+local playerPairPlus = nil -- pair plus bet amount
+local watchingCards = false -- for the notification and other inputs
+local playerDecidedChoice = false
+
+local clientTimer = nil
+local currentHelpText = nil
+
+local mainCamera = nil
+
+local buttonScaleform = nil
+
+local networkedChips = {}
+
+local PlayerOwnedChips = 0
+
+local InformationPlaying = false
+
+local playedHudSound = false
+
+local frm_showed = false
+
+-- EVENTS
+RegisterNetEvent('aquiverPoker:updateCards')
+RegisterNetEvent('aquiverPoker:updateState')
+RegisterNetEvent('aquiverPoker:playerBetAnim')
+RegisterNetEvent('aquiverPoker:Stage:1')
+RegisterNetEvent('aquiverPoker:Stage:2')
+RegisterNetEvent('aquiverPoker:Stage:3')
+RegisterNetEvent('aquiverPoker:Stage:4')
+RegisterNetEvent('aquiverPoker:playerPlayCards')
+RegisterNetEvent('aquiverPoker:playerFoldCards')
+RegisterNetEvent('aquiverPoker:Stage:5')
+RegisterNetEvent('aquiverPoker:Stage:6')
+RegisterNetEvent('aquiverPoker:Stage:7')
+RegisterNetEvent('aquiverPoker:resetTable')
+RegisterNetEvent('aquiverPoker:playerWin')
+RegisterNetEvent('aquiverPoker:playerLost')
+RegisterNetEvent('aquiverPoker:playerDraw')
+RegisterNetEvent('aquiverPoker:updatePlayerChips')
+RegisterNetEvent('aquiverPoker:playerPairPlusAnim')
+----------------------
+
+AddEventHandler(
+ 'aquiverPoker:playerPairPlusAnim',
+ function(amount)
+ if SharedPokers[activePokerTable] ~= nil then
+ SharedPokers[activePokerTable].playerPairPlusAnim(amount)
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:updateCards',
+ function(tableId, Cards)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].updateCards(Cards)
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:updateState',
+ function(tableId, Active, TimeLeft)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].updateState(Active, TimeLeft)
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:playerBetAnim',
+ function(amount)
+ if SharedPokers[activePokerTable] ~= nil then
+ SharedPokers[activePokerTable].playerBetAnim(amount)
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:updatePlayerChips',
+ function(amount)
+ PlayerOwnedChips = math.floor(amount)
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:playerDraw',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].playerDraw()
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:playerLost',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].playerLost()
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:playerWin',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].playerWin()
+ end
+ end
+)
+
+AddEventHandler('aquiverPoker:resetTable',function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].resetTable()
+ exports["qb-core"]:DrawText("Place Bet: ↵Adjust Bet: ↑/↓Exit: ←")
+ end
+end)
+
+AddEventHandler(
+ 'aquiverPoker:Stage:7',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ currentHelpText = _U('clearing_table')
+ SharedPokers[tableId].clearTable()
+ end
+ end
+)
+AddEventHandler(
+ 'aquiverPoker:Stage:6',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ currentHelpText = _U('dealer_showing_hand')
+ SharedPokers[tableId].revealSelfCards()
+ end
+ end
+)
+AddEventHandler(
+ 'aquiverPoker:Stage:5',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ currentHelpText = _U('players_showing_hands')
+ SharedPokers[tableId].revealPlayerCards()
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:Stage:1',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].FirstAction()
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:Stage:2',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ currentHelpText = _U('dealing_cards')
+ SharedPokers[tableId].dealToPlayers()
+ end
+ end
+)
+AddEventHandler(
+ 'aquiverPoker:Stage:3',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ currentHelpText = nil
+ SharedPokers[tableId].dealToSelf()
+ SharedPokers[tableId].putDownDeck()
+ SharedPokers[tableId].dealerStandingIdle()
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:Stage:4',
+ function(tableId)
+ if SharedPokers[tableId] ~= nil then
+ currentHelpText = nil
+ SharedPokers[tableId].watchCards()
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:playerPlayCards',
+ function(mainSrc, tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].playCards(mainSrc)
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:playerFoldCards',
+ function(mainSrc, tableId)
+ if SharedPokers[tableId] ~= nil then
+ SharedPokers[tableId].foldCards(mainSrc)
+ end
+ end
+)
+
+AquiverPoker = function(index, data)
+ local self = {}
+
+ self.index = index
+ self.data = data
+
+ self.cards = {}
+
+ self.playersFolded = {}
+
+ self.updateCards = function(Cards)
+ self.ServerCards = Cards
+ end
+
+ self.updateState = function(Active, TimeLeft)
+ self.Active = Active
+ self.TimeLeft = TimeLeft
+ end
+
+ self.playerDraw = function()
+ local pedReaction = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ local pedr = ({'female_dealer_reaction_impartial_var01', 'female_dealer_reaction_impartial_var02', 'female_dealer_reaction_impartial_var03'})[math.random(1, 3)]
+ TaskSynchronizedScene(self.ped, pedReaction, Config.DealerAnimDictShared, pedr, 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ local pedr = ({'reaction_impartial_var_01', 'reaction_impartial_var_02', 'reaction_impartial_var_03', 'reaction_impartial_var_04'})[math.random(1, 4)]
+ TaskSynchronizedScene(self.ped, pedReaction, Config.DealerAnimDictShared, pedr, 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ end
+
+ self.playerWin = function()
+ local reaction = nil
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then -- female
+ reaction =
+ ({
+ 'female_reaction_great_var_01',
+ 'female_reaction_great_var_02',
+ 'female_reaction_great_var_03',
+ 'female_reaction_great_var_04',
+ 'female_reaction_great_var_05'
+ })[math.random(1, 5)]
+ else
+ reaction = ({'reaction_great_var_01', 'reaction_great_var_02', 'reaction_great_var_03', 'reaction_great_var_04'})[math.random(1, 4)]
+ end
+
+ if reaction then
+ local reactionScene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), reactionScene, Config.PlayerAnimDictShared, reaction, 2.0, -2.0, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(reactionScene)
+ end
+
+ local pedReaction = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ local pedr = ({'female_dealer_reaction_bad_var01', 'female_dealer_reaction_bad_var02', 'female_dealer_reaction_bad_var03'})[math.random(1, 3)]
+ TaskSynchronizedScene(self.ped, pedReaction, Config.DealerAnimDictShared, pedr, 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ local pedr = ({'reaction_bad_var_01', 'reaction_bad_var_02', 'reaction_bad_var_03', 'reaction_bad_var_04'})[math.random(1, 4)]
+ TaskSynchronizedScene(self.ped, pedReaction, Config.DealerAnimDictShared, pedr, 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ end
+
+ self.playerLost = function()
+ local reaction = nil
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then -- female
+ reaction =
+ ({
+ 'female_reaction_terrible_var_01',
+ 'female_reaction_terrible_var_02',
+ 'female_reaction_terrible_var_03',
+ 'female_reaction_terrible_var_04',
+ 'female_reaction_terrible_var_05'
+ })[math.random(1, 5)]
+ else
+ reaction = ({'reaction_terrible_var_01', 'reaction_terrible_var_02', 'reaction_terrible_var_03', 'reaction_terrible_var_04'})[math.random(1, 4)]
+ end
+
+ if reaction then
+ local reactionScene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), reactionScene, Config.PlayerAnimDictShared, reaction, 2.0, -2.0, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(reactionScene)
+ end
+
+ local pedReaction = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ local pedr = ({'female_dealer_reaction_good_var01', 'female_dealer_reaction_good_var02', 'female_dealer_reaction_good_var03'})[math.random(1, 3)]
+ TaskSynchronizedScene(self.ped, pedReaction, Config.DealerAnimDictShared, pedr, 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ local pedr = ({'reaction_good_var_01', 'reaction_good_var_02', 'reaction_good_var_03'})[math.random(1, 3)]
+ TaskSynchronizedScene(self.ped, pedReaction, Config.DealerAnimDictShared, pedr, 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ end
+
+ self.speakPed = function(duma)
+ Citizen.CreateThread(function()
+ PlayPedAmbientSpeechNative(self.ped, duma, 'SPEECH_PARAMS_FORCE_NORMAL_CLEAR', 1)
+ end)
+ end
+
+ self.createDefaultPakli = function()
+ Citizen.CreateThread(
+ function()
+ local cardModel = GetHashKey('vw_prop_casino_cards_01')
+ RequestModel(cardModel)
+ while not HasModelLoaded(cardModel) do
+ Citizen.Wait(1)
+ end
+
+ RequestAnimDict(Config.DealerAnimDictPoker)
+ while not HasAnimDictLoaded(Config.DealerAnimDictPoker) do
+ Citizen.Wait(1)
+ end
+
+ local offset = GetAnimInitialOffsetPosition(Config.DealerAnimDictPoker, 'deck_pick_up_deck', self.data.Position, 0.0, 0.0, self.data.Heading, 0.01, 2)
+ self.pakli = CreateObject(cardModel, offset, false, false, true)
+ SetEntityCoordsNoOffset(self.pakli, offset, false, false, true)
+ SetEntityRotation(self.pakli, 0.0, 0.0, self.data.Rotation, 2, true)
+ FreezeEntityPosition(self.pakli, true)
+ end
+ )
+ end
+
+ self.isPedFemale = function()
+ if GetEntityModel(self.ped) == GetHashKey('S_M_Y_Casino_01') then
+ return false
+ else
+ return true
+ end
+ end
+
+ self.createPed = function()
+ Citizen.CreateThread(
+ function()
+ local maleCasinoDealer = GetHashKey('S_M_Y_Casino_01')
+ local femaleCasinoDealer = GetHashKey('S_F_Y_Casino_01')
+
+ local frmVar_1 = math.random(1, 13)
+ if frmVar_1 < 7 then
+ dealerModel = maleCasinoDealer
+ else
+ dealerModel = femaleCasinoDealer
+ end
+
+ RequestModel(dealerModel)
+ while not HasModelLoaded(dealerModel) do
+ Citizen.Wait(1)
+ end
+
+ self.ped = CreatePed(26, dealerModel, self.data.Position, self.data.Heading, false, true)
+ SetModelAsNoLongerNeeded(dealerModel)
+ SetEntityCanBeDamaged(self.ped, false)
+ SetPedAsEnemy(self.ped, false)
+ SetBlockingOfNonTemporaryEvents(self.ped, true)
+ SetPedResetFlag(self.ped, 249, 1)
+ SetPedConfigFlag(self.ped, 185, true)
+ SetPedConfigFlag(self.ped, 108, true)
+ SetPedCanEvasiveDive(self.ped, 0)
+ SetPedCanRagdollFromPlayerImpact(self.ped, 0)
+ SetPedConfigFlag(self.ped, 208, true)
+ SetPedCanRagdoll(self.ped, false)
+ -- N_0x352e2b5cf420bf3b(self.ped, 1) -- no idea what are these
+ -- N_0x2f3c3d9f50681de4(self.ped, true) -- no idea what are these
+ -- N_0xf8ad2eed7c47e8fe(self.ped, true, false) -- no idea what are these
+
+ frm_setPedClothes(frmVar_1, self.ped)
+ frm_setPedVoiceGroup(frmVar_1, self.ped)
+
+ SetEntityCoordsNoOffset(self.ped, self.data.Position + vector3(0.0, 0.0, 1.0), false, false, true)
+ SetEntityHeading(self.ped, self.data.Heading)
+
+ RequestAnimDict(Config.DealerAnimDictShared)
+ while not HasAnimDictLoaded(Config.DealerAnimDictShared) do
+ Citizen.Wait(1)
+ end
+
+ self.dealerStandingIdle()
+
+ Config.DebugMsg('Poker ped created.')
+ end
+ )
+ end
+
+ self.sitDown = function(chairId, chairCoords, chairRotation)
+ StartAudioScene('DLC_VW_Casino_Table_Games')
+
+ if not IsEntityDead(PlayerPedId()) then
+ QBCore.Functions.TriggerCallback(
+ 'aquiverPoker:sitDown',
+ function(canSit)
+ if canSit then
+ activeChairData = {
+ chairId = chairId,
+ chairCoords = chairCoords,
+ chairRotation = chairRotation
+ }
+
+ exports["qb-core"]:HideText()
+ -- exports['casinoUi']:HideCasinoUi('hide')
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_m_freemode_01') then
+ local rspeech = math.random(1, 2)
+ if rspeech == 1 then
+ self.speakPed('MINIGAME_DEALER_GREET')
+ else
+ self.speakPed('MINIGAME_DEALER_GREET_MALE')
+ end
+ else
+ local rspeech = math.random(1, 2)
+ if rspeech == 1 then
+ self.speakPed('MINIGAME_DEALER_GREET')
+ else
+ self.speakPed('MINIGAME_DEALER_GREET_FEMALE')
+ end
+ end
+
+ buttonScaleform = setupFirstButtons('instructional_buttons')
+
+ RequestAnimDict(Config.PlayerAnimDictShared)
+ while not HasAnimDictLoaded(Config.PlayerAnimDictShared) do
+ Citizen.Wait(1)
+ end
+ SetPlayerControl(PlayerPedId(), 0, 0)
+ local sitScene = NetworkCreateSynchronisedScene(chairCoords, chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ local sitAnim = ({'sit_enter_left_side', 'sit_enter_right_side'})[math.random(1, 2)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), sitScene, Config.PlayerAnimDictShared, sitAnim, 2.0, -2.0, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(sitScene)
+
+ Citizen.Wait(4000)
+ mainScene = NetworkCreateSynchronisedScene(chairCoords, chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), mainScene, Config.PlayerAnimDictShared, 'idle_cardgames', 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(mainScene)
+
+ self.EnableRender(true)
+ SetPlayerControl(PlayerPedId(), 1, 0)
+ exports["qb-core"]:DrawText("Place Bet: ↵Adjust Bet: ↑/↓Exit: ←")
+
+ Citizen.Wait(500)
+ else
+ QBCore.Functions.Notify('This seat is occupied.')
+ end
+ end,
+ self.index,
+ chairId
+ )
+ end
+ end
+
+ self.createCard = function(cardName)
+ local cardModel = GetHashKey(cardName)
+ RequestModel(cardModel)
+ while not HasModelLoaded(cardModel) do
+ Citizen.Wait(1)
+ end
+
+ return CreateObject(cardModel, self.data.Position + vector3(0.0, 0.0, -0.1), false, true, true)
+ end
+
+ self.FirstAction = function()
+ self.speakPed('MINIGAME_DEALER_CLOSED_BETS')
+
+ -- FIRST ACTION TO DO WHEN STARTING GAME
+ RequestAnimDict(Config.DealerAnimDictPoker)
+ while not HasAnimDictLoaded(Config.DealerAnimDictPoker) do
+ Citizen.Wait(1)
+ end
+
+ local firstScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, firstScene, Config.DealerAnimDictPoker, 'female_deck_pick_up', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, firstScene, Config.DealerAnimDictPoker, 'deck_pick_up', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+
+ while GetSynchronizedScenePhase(firstScene) < 0.99 do
+ if HasAnimEventFired(self.ped, 1691374422) then
+ if not IsEntityAttachedToAnyPed(self.pakli) then
+ FreezeEntityPosition(self.pakli, false)
+ AttachEntityToEntity(self.pakli, self.ped, GetPedBoneIndex(self.ped, 60309), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false, false, false, true, 2, true)
+ end
+ end
+
+ Citizen.Wait(1)
+ end
+
+ if self.ServerCards['dealer'] ~= nil then
+ self.cards['dealer'] = {}
+
+ if not DoesEntityExist(self.cards['dealer'][1]) then
+ self.cards['dealer'][1] = self.createCard(Config.Cards[self.ServerCards['dealer'].Hand[1]])
+ end
+ if not DoesEntityExist(self.cards['dealer'][2]) then
+ self.cards['dealer'][2] = self.createCard(Config.Cards[self.ServerCards['dealer'].Hand[2]])
+ end
+ if not DoesEntityExist(self.cards['dealer'][3]) then
+ self.cards['dealer'][3] = self.createCard(Config.Cards[self.ServerCards['dealer'].Hand[3]])
+ end
+ end
+
+ local secondScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, secondScene, Config.DealerAnimDictPoker, 'female_deck_shuffle', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, secondScene, Config.DealerAnimDictPoker, 'deck_shuffle', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ PlaySynchronizedEntityAnim(self.cards['dealer'][1], secondScene, 'deck_shuffle_card_a', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][2], secondScene, 'deck_shuffle_card_b', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][3], secondScene, 'deck_shuffle_card_c', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+
+ while GetSynchronizedScenePhase(secondScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+
+ SetEntityVisible(self.cards['dealer'][1], false, false)
+ SetEntityVisible(self.cards['dealer'][2], false, false)
+ SetEntityVisible(self.cards['dealer'][3], false, false)
+
+ local thirdScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, thirdScene, Config.DealerAnimDictPoker, 'female_deck_idle', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, thirdScene, Config.DealerAnimDictPoker, 'deck_idle', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ while GetSynchronizedScenePhase(thirdScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+ end
+
+ self.dealToPlayers = function()
+ StartAudioScene('DLC_VW_Casino_Cards_Focus_Hand')
+ StartAudioScene('DLC_VW_Casino_Table_Games')
+
+ buttonScaleform = nil
+ Config.DebugMsg('dealing to players')
+ -- SECOND ACTIONS TO DO, THERE CAN BE MORE PLAYERS!
+ for targetSrc, data in pairs(self.ServerCards) do
+ if targetSrc ~= 'dealer' then
+ self.cards[targetSrc] = {}
+ self.cards[targetSrc][1] = self.createCard(Config.Cards[data.Hand[1]])
+ self.cards[targetSrc][2] = self.createCard(Config.Cards[data.Hand[2]])
+ self.cards[targetSrc][3] = self.createCard(Config.Cards[data.Hand[3]])
+
+ RequestAnimDict(Config.DealerAnimDictPoker)
+ while not HasAnimDictLoaded(Config.DealerAnimDictPoker) do
+ Citizen.Wait(1)
+ end
+
+ local playerAnimId = nil
+
+ if data.chairData.chairId == 4 then -- this is reverse because rockstar think differently no idea why
+ playerAnimId = 'p01'
+ elseif data.chairData.chairId == 3 then
+ playerAnimId = 'p02'
+ elseif data.chairData.chairId == 2 then
+ playerAnimId = 'p03'
+ elseif data.chairData.chairId == 1 then
+ playerAnimId = 'p04'
+ end
+
+ if playerAnimId ~= nil then
+ local dealScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+
+ SetEntityVisible(self.cards[targetSrc][1], false, false)
+ SetEntityVisible(self.cards[targetSrc][2], false, false)
+ SetEntityVisible(self.cards[targetSrc][3], false, false)
+
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, dealScene, Config.DealerAnimDictPoker, string.format('female_deck_deal_%s', playerAnimId), 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, dealScene, Config.DealerAnimDictPoker, string.format('deck_deal_%s', playerAnimId), 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+
+ PlaySynchronizedEntityAnim(
+ self.cards[targetSrc][1],
+ dealScene,
+ string.format('deck_deal_%s_card_a', playerAnimId),
+ Config.DealerAnimDictPoker,
+ 1000.0,
+ 0,
+ 0,
+ 1000.0
+ )
+ PlaySynchronizedEntityAnim(
+ self.cards[targetSrc][2],
+ dealScene,
+ string.format('deck_deal_%s_card_b', playerAnimId),
+ Config.DealerAnimDictPoker,
+ 1000.0,
+ 0,
+ 0,
+ 1000.0
+ )
+ PlaySynchronizedEntityAnim(
+ self.cards[targetSrc][3],
+ dealScene,
+ string.format('deck_deal_%s_card_c', playerAnimId),
+ Config.DealerAnimDictPoker,
+ 1000.0,
+ 0,
+ 0,
+ 1000.0
+ )
+
+ while GetSynchronizedScenePhase(dealScene) < 0.05 do
+ Citizen.Wait(1)
+ end
+
+ SetEntityVisible(self.cards[targetSrc][1], true, false)
+ SetEntityVisible(self.cards[targetSrc][2], true, false)
+ SetEntityVisible(self.cards[targetSrc][3], true, false)
+
+ while GetSynchronizedScenePhase(dealScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+ end
+ end
+ end
+ Config.DebugMsg('dealing ended')
+ end
+
+ self.watchCards = function()
+ self.speakPed('MINIGAME_DEALER_COMMENT_SLOW')
+
+ if self.index == activePokerTable and playerBetted ~= nil then
+ clientTimer = Config.PlayerDecideTime
+ Citizen.CreateThread(
+ function()
+ while clientTimer ~= nil do
+ Citizen.Wait(1000)
+ if clientTimer ~= nil then
+ clientTimer = clientTimer - 1
+
+ if clientTimer < 1 then
+ clientTimer = nil
+ QBCore.Functions.Notify('You did not respond for the dealer ask in time, you have folded your hand.')
+ TriggerServerEvent('aquiverPoker:foldCards', self.index)
+ end
+ end
+ end
+ end
+ )
+ end
+
+ RequestAnimDict(Config.PlayerAnimDictPoker)
+ while not HasAnimDictLoaded(Config.PlayerAnimDictPoker) do
+ Citizen.Wait(1)
+ end
+
+ for targetSrc, data in pairs(self.ServerCards) do
+ if targetSrc ~= 'dealer' then
+ -- if we are the player, we call it once
+ if GetPlayerServerId(PlayerId()) == targetSrc and self.index == activePokerTable then
+ local scene = NetworkCreateSynchronisedScene(data.chairData.chairCoords, data.chairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, Config.PlayerAnimDictPoker, 'cards_pickup', 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(scene)
+ Citizen.CreateThread(
+ function()
+ Citizen.Wait(1500)
+ watchingCards = true
+ -- ShakeGameplayCam('HAND_SHAKE', 0.15)
+ -- buttonScaleform = setupThirdButtons('instructional_buttons')
+ exports["qb-core"]:DrawText("Play Hand: EFold Hand: ←")
+
+ local playerHandValue = Config.getHandAllValues(data.Hand)
+ if playerHandValue ~= nil then
+ Config.DebugMsg(string.format('Player hand value: %s', playerHandValue))
+ local form = Config.formatHandValue(playerHandValue)
+ if form ~= nil then
+ Citizen.CreateThread(
+ function()
+ while watchingCards do
+ Citizen.Wait(0)
+ exports['casinoUi']:DrawCasinoUi('show', "The Diamond Casino & Resort PokerPlayer hand: "..form)
+
+ -- drawText2d(0.5, 0.9, 0.45, form)
+
+ end
+ end
+ )
+ -- else
+ -- exports['casinoUi']:HideCasinoUi('hide')
+ end
+ end
+ end
+ )
+ end
+
+ local cardsScene = CreateSynchronizedScene(data.chairData.chairCoords, data.chairData.chairRotation, 2)
+
+ PlaySynchronizedEntityAnim(self.cards[targetSrc][1], cardsScene, 'cards_pickup_card_a', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[targetSrc][2], cardsScene, 'cards_pickup_card_b', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[targetSrc][3], cardsScene, 'cards_pickup_card_c', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ end
+ end
+ end
+
+ self.foldCards = function(mainSrc)
+ self.playersFolded[mainSrc] = true
+
+ if GetPlayerServerId(PlayerId()) == mainSrc then
+ local scene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, Config.PlayerAnimDictPoker, 'cards_fold', 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(scene)
+ playerDecidedChoice = true
+ watchingCards = false
+ buttonScaleform = nil
+ StopGameplayCamShaking(true)
+ end
+
+ if self.cards[mainSrc] ~= nil then
+ local chairData = self.ServerCards[mainSrc].chairData
+ local cardsScene = CreateSynchronizedScene(chairData.chairCoords, chairData.chairRotation, 2)
+ PlaySynchronizedEntityAnim(self.cards[mainSrc][1], cardsScene, 'cards_fold_card_a', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[mainSrc][2], cardsScene, 'cards_fold_card_b', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[mainSrc][3], cardsScene, 'cards_fold_card_c', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ end
+ end
+
+ self.playCards = function(mainSrc)
+ if GetPlayerServerId(PlayerId()) == mainSrc then
+ playerDecidedChoice = true
+ watchingCards = false
+ buttonScaleform = nil
+ StopGameplayCamShaking(true)
+
+ Citizen.CreateThread(
+ function()
+ local scene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, Config.PlayerAnimDictPoker, 'cards_play', 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(scene)
+
+ while not HasAnimEventFired(PlayerPedId(), -1424880317) do
+ Citizen.Wait(1)
+ end
+
+ local nextScene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), nextScene, Config.PlayerAnimDictPoker, 'cards_bet', 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(nextScene)
+
+ Citizen.Wait(500)
+
+ local offsetAlign = nil
+ if activeChairData.chairId == 4 then
+ offsetAlign = vector3(0.689125, 0.171575, 0.954)
+ elseif activeChairData.chairId == 3 then
+ offsetAlign = vector3(0.2869, -0.211925, 0.954)
+ elseif activeChairData.chairId == 2 then
+ offsetAlign = vector3(-0.30935, -0.205675, 0.954)
+ elseif activeChairData.chairId == 1 then
+ offsetAlign = vector3(-0.69795, 0.211525, 0.954)
+ end
+
+ if offsetAlign == nil then
+ Config.DebugMsg('Something error happened during the playCards function.')
+ return
+ end
+
+ local offset = GetObjectOffsetFromCoords(self.data.Position, self.data.Heading, offsetAlign)
+ local chipModel = getChipModelByAmount(playerBetted)
+ RequestModel(chipModel)
+ while not HasModelLoaded(chipModel) do
+ Citizen.Wait(1)
+ end
+
+ local chipObj = CreateObjectNoOffset(chipModel, offset, true, false, true)
+ SetEntityCoordsNoOffset(chipObj, offset, false, false, true)
+ SetEntityHeading(chipObj, GetEntityHeading(PlayerPedId()))
+ table.insert(networkedChips, chipObj)
+
+ while not HasAnimEventFired(PlayerPedId(), -1424880317) do
+ Citizen.Wait(1)
+ end
+
+ self.playerRandomIdleAnim()
+ end
+ )
+ end
+
+ if self.cards[mainSrc] ~= nil and self.ServerCards[mainSrc] ~= nil then
+ local chairData = self.ServerCards[mainSrc].chairData
+ local cardsScene = CreateSynchronizedScene(chairData.chairCoords, chairData.chairRotation, 2)
+ PlaySynchronizedEntityAnim(self.cards[mainSrc][1], cardsScene, 'cards_play_card_a', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[mainSrc][2], cardsScene, 'cards_play_card_b', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[mainSrc][3], cardsScene, 'cards_play_card_c', Config.PlayerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ end
+ end
+
+ self.playerRandomIdleAnim = function()
+ local selectedIdleAnim = nil
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then -- female
+ local fmlIdles = {
+ 'female_idle_cardgames_var_01',
+ 'female_idle_cardgames_var_02',
+ 'female_idle_cardgames_var_03',
+ 'female_idle_cardgames_var_04',
+ 'female_idle_cardgames_var_05',
+ 'female_idle_cardgames_var_06',
+ 'female_idle_cardgames_var_07',
+ 'female_idle_cardgames_var_08'
+ }
+ selectedIdleAnim = fmlIdles[math.random(1, 8)]
+ else -- male or UFO
+ local mlIdles = {
+ 'idle_cardgames_var_01',
+ 'idle_cardgames_var_02',
+ 'idle_cardgames_var_03',
+ 'idle_cardgames_var_04',
+ 'idle_cardgames_var_05',
+ 'idle_cardgames_var_06',
+ 'idle_cardgames_var_07',
+ 'idle_cardgames_var_08',
+ 'idle_cardgames_var_09',
+ 'idle_cardgames_var_10',
+ 'idle_cardgames_var_11',
+ 'idle_cardgames_var_12',
+ 'idle_cardgames_var_13'
+ }
+ selectedIdleAnim = mlIdles[math.random(1, 13)]
+ end
+
+ if selectedIdleAnim ~= nil then
+ local playerIdleScene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), playerIdleScene, Config.PlayerAnimDictShared, selectedIdleAnim, 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(playerIdleScene)
+
+ while not HasAnimEventFired(PlayerPedId(), -1424880317) do
+ Citizen.Wait(1)
+ end
+
+ local playerIdleScene2 = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), playerIdleScene2, Config.PlayerAnimDictShared, 'idle_cardgames', 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(playerIdleScene2)
+ end
+ end
+
+ self.dealToSelf = function()
+ Config.DebugMsg('dealing dealer cards.')
+ local dealSelfScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, dealSelfScene, Config.DealerAnimDictPoker, 'female_deck_deal_self', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, dealSelfScene, Config.DealerAnimDictPoker, 'deck_deal_self', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ PlaySynchronizedEntityAnim(self.cards['dealer'][1], dealSelfScene, 'deck_deal_self_card_a', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][2], dealSelfScene, 'deck_deal_self_card_b', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][3], dealSelfScene, 'deck_deal_self_card_c', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+
+ while GetSynchronizedScenePhase(dealSelfScene) < 0.05 do
+ Citizen.Wait(1)
+ end
+
+ SetEntityVisible(self.cards['dealer'][1], true, false)
+ SetEntityVisible(self.cards['dealer'][2], true, false)
+ SetEntityVisible(self.cards['dealer'][3], true, false)
+
+ while GetSynchronizedScenePhase(dealSelfScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+ end
+
+ self.dealerStandingIdle = function()
+ local scene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, scene, Config.DealerAnimDictShared, 'female_idle', 1000.0, -2.0, -1.0, 33, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, scene, Config.DealerAnimDictShared, 'idle', 1000.0, -2.0, -1.0, 33, 1000.0, 0)
+ end
+ end
+
+ self.putDownDeck = function()
+ local scene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, scene, Config.DealerAnimDictPoker, 'female_deck_put_down', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, scene, Config.DealerAnimDictPoker, 'deck_put_down', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ while GetSynchronizedScenePhase(scene) < 0.99 do
+ Citizen.Wait(1)
+ end
+
+ if IsEntityAttachedToAnyPed(self.pakli) then
+ DetachEntity(self.pakli, true, true)
+ FreezeEntityPosition(self.pakli, true)
+ Config.DebugMsg('pakli detached')
+ end
+
+ self.dealerStandingIdle()
+ end
+
+ self.EnableRender = function(state)
+ if state then
+ activePokerTable = self.index
+ TriggerEvent('ShowPlayerHud', false)
+
+ Citizen.CreateThread(
+ function()
+ while activePokerTable do
+ Citizen.Wait(0)
+ DisableAllControlActions(0)
+
+ if buttonScaleform ~= nil then
+ -- DrawScaleformMovieFullscreen(buttonScaleform, 255, 255, 255, 255, 0)
+ exports['casinoUi']:DrawCasinoUi('show', "The Diamond Casino & Resort PokerCurrent Bet: "..currentBetInput.."Availble chips: "..PlayerOwnedChips)
+ end
+
+ EnableControlAction(0, 0, true) -- changing camera
+ EnableControlAction(0, 1, true) -- mouse cam
+ EnableControlAction(0, 2, true) -- mouse cam
+ EnableControlAction(0, 24, true)
+ EnableControlAction(0, 249, true)
+
+ -- if player betted then
+ if playerBetted and QBCore then
+ local reactiveText = ''
+
+ if currentHelpText then
+ reactiveText = reactiveText .. currentHelpText
+ end
+
+ if self.TimeLeft > 0 then
+ reactiveText = reactiveText .. _U('waiting_for_players')
+ end
+
+ if watchingCards then
+ if IsDisabledControlJustPressed(0, 38) then
+ clientTimer = nil
+ watchingCards = false
+ buttonScaleform = nil
+ StopGameplayCamShaking(true)
+ TriggerServerEvent('aquiverPoker:playCards', self.index, playerBetted)
+ end
+
+ if IsDisabledControlJustPressed(0, 177) then
+ clientTimer = nil
+ watchingCards = false
+ buttonScaleform = nil
+ StopGameplayCamShaking(true)
+ TriggerServerEvent('aquiverPoker:foldCards', self.index)
+ end
+ end
+
+ if string.len(reactiveText) > 0 then
+ ShowHelpNotification(reactiveText)
+ end
+ end
+
+ -- only enable standup if he did not bet
+ if playerBetted == nil then
+ if IsDisabledControlJustPressed(0, 177) then
+ self.EnableRender(false)
+ -- PlaySoundFrontend(-1, 'FocusOut', 'HintCamSounds', false)
+ end
+ end
+
+ if playerBetted == nil or playerPairPlus == nil then
+ if self.TimeLeft == nil or self.TimeLeft > 0 then
+ -- -- bet input
+ -- if IsDisabledControlJustPressed(0, 22) then --Custom Bet [space]
+ -- local tmpInput = getGenericTextInput('Tét')
+ -- if tonumber(tmpInput) then
+ -- tmpInput = tonumber(tmpInput)
+ -- if tmpInput > 0 then
+ -- if tmpInput > self.data.MaximumBet then
+ -- PlaySoundFrontend(-1, 'DLC_VW_ERROR_MAX', 'dlc_vw_table_games_frontend_sounds', true)
+ -- else
+ -- currentBetInput = tmpInput
+ -- PlaySoundFrontend(-1, 'DLC_VW_BET_HIGHLIGHT', 'dlc_vw_table_games_frontend_sounds', true)
+ -- end
+ -- end
+ -- end
+ -- end
+
+ if IsDisabledControlJustPressed(0, 176) then
+ if currentBetInput > 0 then
+ if currentBetInput >= self.data.MinimumBet and currentBetInput <= self.data.MaximumBet then
+ if playerBetted == nil then
+ TriggerServerEvent('aquiverPoker:betPlayer', self.index, activeChairData, currentBetInput)
+ else
+ if playerPairPlus == nil then
+ TriggerServerEvent('aquiverPoker:betPairPlusPlayer', self.index, currentBetInput)
+ end
+ end
+ else
+ PlaySoundFrontend(-1, 'DLC_VW_ERROR_MAX', 'dlc_vw_table_games_frontend_sounds', true)
+ end
+ else
+ QBCore.Functions.Notify("You did not set up a bet value.")
+ end
+ end
+
+ if IsDisabledControlJustPressed(0, 172) then -- up
+ local increase = Config.IncreaseAmounts(currentBetInput)
+ currentBetInput = currentBetInput + increase
+ if currentBetInput > self.data.MaximumBet then
+ PlaySoundFrontend(-1, 'DLC_VW_ERROR_MAX', 'dlc_vw_table_games_frontend_sounds', true)
+ currentBetInput = self.data.MaximumBet
+ else
+ PlaySoundFrontend(-1, 'DLC_VW_BET_UP', 'dlc_vw_table_games_frontend_sounds', true)
+ end
+ elseif IsDisabledControlJustPressed(0, 173) then -- down
+ if currentBetInput > 0 then
+ local increase = Config.IncreaseAmounts(currentBetInput)
+ currentBetInput = currentBetInput - increase
+ PlaySoundFrontend(-1, 'DLC_VW_BET_DOWN', 'dlc_vw_table_games_frontend_sounds', true)
+ if currentBetInput < 0 then
+ currentBetInput = 0
+ PlaySoundFrontend(-1, 'DLC_VW_ERROR_MAX', 'dlc_vw_table_games_frontend_sounds', true)
+ end
+ else
+ PlaySoundFrontend(-1, 'DLC_VW_ERROR_MAX', 'dlc_vw_table_games_frontend_sounds', true)
+ end
+ end
+ end
+ end
+ -- if self.Active then
+ -- if self.TimeLeft >= 10 then
+ -- -- DrawRect(0.944, 0.799, 0.081, 0.032, 0, 0, 0, 200)
+ -- -- DrawAdvancedNativeText(1.013, 0.806, 0.005, 0.0028, 0.29, _U('remaining_time'), 255, 255, 255, 255, 0, 0)
+ -- -- DrawAdvancedNativeText(1.05, 0.799, 0.005, 0.0028, 0.464, string.format('00:%s', self.TimeLeft), 255, 255, 255, 255, 0, 0)
+ -- else
+ -- if self.TimeLeft > 0 then
+ -- -- DrawAdvancedNativeText(1.013, 0.806, 0.005, 0.0028, 0.29, _U('remaining_time'), 255, 255, 255, 255, 0, 0)
+ -- -- DrawRect(0.944, 0.799, 0.081, 0.032, 0, 0, 0, 200)
+ -- -- DrawAdvancedNativeText(1.05, 0.799, 0.005, 0.0028, 0.464, string.format('00:0%s', self.TimeLeft), 255, 255, 255, 255, 0, 0)
+
+ -- else
+ -- if clientTimer ~= nil then
+ -- -- DrawAdvancedNativeText(1.013, 0.806, 0.005, 0.0028, 0.29, _U('remaining_time'), 255, 255, 255, 255, 0, 0)
+ -- -- DrawRect(0.944, 0.799, 0.081, 0.032, 0, 0, 0, 200)
+
+ -- if clientTimer >= 10 then
+ -- -- DrawAdvancedNativeText(1.05, 0.799, 0.005, 0.0028, 0.464, string.format('00:%s', clientTimer), 255, 255, 255, 255, 0, 0)
+
+ -- else
+ -- -- DrawAdvancedNativeText(1.05, 0.799, 0.005, 0.0028, 0.464, string.format('00:0%s', clientTimer), 255, 255, 255, 255, 0, 0)
+ -- end
+ -- end
+ -- end
+ -- end
+ -- end
+ -- exports['casinoUi']:DrawCasinoUi('show', "BET:"..currentBetInput.."CHIPS:"..PlayerOwnedChips.."MIN/MAX:"..self.data.MinimumBet.."/"..self.data.MaximumBet.."TIME:")
+ end
+ end
+ )
+ else
+ exports['casinoUi']:HideCasinoUi('hide')
+ exports["qb-core"]:HideText()
+
+
+ self.speakPed('MINIGAME_DEALER_LEAVE_NEUTRAL_GAME')
+ local sitExitScene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), sitExitScene, Config.PlayerAnimDictShared, 'sit_exit_left', 2.0, -2.0, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(sitExitScene)
+ Citizen.Wait(4000)
+ TriggerServerEvent('aquiverPoker:standUp', self.index, activeChairData.chairId)
+ TriggerEvent('ShowPlayerHud', true)
+ NetworkStopSynchronisedScene(mainScene)
+ NetworkStopSynchronisedScene(sitExitScene)
+ activePokerTable = nil
+ activeChairData = nil
+ end
+ end
+
+ self.revealSelfCards = function()
+ Citizen.CreateThread(
+ function()
+ if self.index == activePokerTable then
+ local offset = GetObjectOffsetFromCoords(self.data.Position, self.data.Heading, 0.0, -0.04, 1.35)
+
+ mainCamera = CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA', offset, -78.0, 0.0, self.data.Heading, 80.0, true, 2)
+ SetCamActive(mainCamera, true)
+ RenderScriptCams(true, 900, 900, true, false)
+ ShakeCam(mainCamera, 'HAND_SHAKE', 0.25)
+
+ Citizen.Wait(2500)
+
+ local dealerHandValue = Config.getHandAllValues(self.ServerCards['dealer'].Hand)
+ if dealerHandValue ~= nil then
+ Config.DebugMsg(string.format('Dealer hand value: %s', dealerHandValue))
+ local form = Config.formatHandValue(dealerHandValue)
+ if form ~= nil then
+ Citizen.CreateThread(
+ function()
+ while DoesCamExist(mainCamera) do
+ Citizen.Wait(0)
+
+ exports['casinoUi']:DrawCasinoUi('show', "The Diamond Casino & Resort PokerDealer hand: "..form)
+
+ -- drawText2d(0.5, 0.9, 0.45, form)
+ -- elseif
+ -- exports['casinoUi']:HideCasinoUi('hide')
+ end
+ end
+ )
+ -- else
+ -- exports['casinoUi']:HideCasinoUi('hide')
+ end
+ end
+
+ Citizen.Wait(7500)
+
+ if DoesCamExist(mainCamera) then
+ DestroyCam(mainCamera, false)
+ end
+ RenderScriptCams(false, 900, 900, true, false)
+ end
+ end
+ )
+ if self.ServerCards['dealer'] ~= nil then
+ local revealScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, revealScene, Config.DealerAnimDictPoker, 'female_reveal_self', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, revealScene, Config.DealerAnimDictPoker, 'reveal_self', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ PlaySynchronizedEntityAnim(self.cards['dealer'][1], revealScene, 'reveal_self_card_a', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][2], revealScene, 'reveal_self_card_b', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][3], revealScene, 'reveal_self_card_c', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ end
+ end
+
+ self.revealPlayerCards = function()
+ for targetSrc, data in pairs(self.ServerCards) do
+ if targetSrc ~= 'dealer' then
+ local playerAnimId = nil
+
+ if data.chairData.chairId == 4 then -- this is reverse because rockstar think differently no idea why
+ playerAnimId = 'p01'
+ elseif data.chairData.chairId == 3 then
+ playerAnimId = 'p02'
+ elseif data.chairData.chairId == 2 then
+ playerAnimId = 'p03'
+ elseif data.chairData.chairId == 1 then
+ playerAnimId = 'p04'
+ end
+
+ local mainAnimFormat = nil
+ local entityAnimFormatA = nil
+ local entityAnimFormatB = nil
+ local entityAnimFormatC = nil
+
+ if self.playersFolded[targetSrc] then -- if he or she folded the hand
+ if self.isPedFemale() then
+ mainAnimFormat = string.format('female_reveal_folded_%s', playerAnimId)
+ else
+ mainAnimFormat = string.format('reveal_folded_%s', playerAnimId)
+ end
+ entityAnimFormatA = string.format('reveal_folded_%s_card_a', playerAnimId)
+ entityAnimFormatB = string.format('reveal_folded_%s_card_b', playerAnimId)
+ entityAnimFormatC = string.format('reveal_folded_%s_card_c', playerAnimId)
+ else
+ if self.isPedFemale() then
+ mainAnimFormat = string.format('female_reveal_played_%s', playerAnimId)
+ else
+ mainAnimFormat = string.format('reveal_played_%s', playerAnimId)
+ end
+ entityAnimFormatA = string.format('reveal_played_%s_card_a', playerAnimId)
+ entityAnimFormatB = string.format('reveal_played_%s_card_b', playerAnimId)
+ entityAnimFormatC = string.format('reveal_played_%s_card_c', playerAnimId)
+ end
+
+ if mainAnimFormat ~= nil then
+ if activePokerTable == self.index then -- only show camera if he/she is sitting at the table.
+ if Config.ShowCardsAfterReveal then
+ local offset =
+ GetAnimInitialOffsetPosition(Config.PlayerAnimDictPoker, 'cards_play_card_b', data.chairData.chairCoords, data.chairData.chairRotation, 0.0, 2)
+
+ if DoesCamExist(mainCamera) then
+ DestroyCam(mainCamera, false)
+ end
+
+ mainCamera =
+ CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA', offset + vector3(0.0, 0.0, 0.45), -85.0, 0.0, data.chairData.chairRotation.z - 90.0, 80.0, true, 2)
+ SetCamActive(mainCamera, true)
+ RenderScriptCams(true, 900, 900, true, false)
+ ShakeCam(mainCamera, 'HAND_SHAKE', 0.25)
+ end
+ end
+
+ SetEntityVisible(self.cards[targetSrc][1], false, false)
+ SetEntityVisible(self.cards[targetSrc][2], false, false)
+ SetEntityVisible(self.cards[targetSrc][3], false, false)
+
+ local revealScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ TaskSynchronizedScene(self.ped, revealScene, Config.DealerAnimDictPoker, mainAnimFormat, 2.0, -2.0, 13, 16, 1000.0, 0)
+ PlaySynchronizedEntityAnim(self.cards[targetSrc][1], revealScene, entityAnimFormatA, Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[targetSrc][2], revealScene, entityAnimFormatB, Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards[targetSrc][3], revealScene, entityAnimFormatC, Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+
+ while GetSynchronizedScenePhase(revealScene) < 0.025 do
+ Citizen.Wait(1)
+ end
+
+ SetEntityVisible(self.cards[targetSrc][1], true, false)
+ SetEntityVisible(self.cards[targetSrc][2], true, false)
+ SetEntityVisible(self.cards[targetSrc][3], true, false)
+
+ while GetSynchronizedScenePhase(revealScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+
+ local ggScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, ggScene, Config.DealerAnimDictShared, string.format('female_acknowledge_%s', playerAnimId), 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, ggScene, Config.DealerAnimDictShared, string.format('acknowledge_%s', playerAnimId), 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ end
+ end
+ end
+ end
+
+ self.resetTable = function()
+
+ -- chips clearing
+ if #networkedChips > 0 then
+ for i = 1, #networkedChips, 1 do
+ if NetworkGetEntityOwner(networkedChips[i]) == PlayerId() then
+ DeleteObject(networkedChips[i])
+ end
+ end
+ end
+
+ Citizen.Wait(200) -- because i like timeouts -_-
+
+ for k, v in pairs(self.cards) do
+ for i = 1, #v, 1 do
+ DeleteObject(v[i])
+ end
+ end
+
+ Citizen.Wait(200) -- because i like timeouts -_-
+
+ self.cards = {}
+
+ if self.index == activePokerTable then
+ playerBetted = nil
+ playerPairPlus = nil
+ watchingCards = false
+ StopGameplayCamShaking(true)
+ playerDecidedChoice = false
+ clientTimer = nil
+ currentHelpText = nil
+ networkedChips = {}
+ currentBetInput = 0
+ buttonScaleform = setupFirstButtons('instructional_buttons')
+ end
+
+ self.ServerCards = {}
+ self.Active = false
+ self.TimeLeft = nil
+ self.playersPlaying = {}
+ self.playersFolded = {}
+
+ self.dealerStandingIdle()
+ end
+
+ self.clearTable = function()
+ self.speakPed('MINIGAME_DEALER_ANOTHER_GO')
+ -- exports["qb-core"]:HideText()
+ -- exports['casinoUi']:HideCasinoUi('hide')
+ -- deck picking up anim
+ local firstScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, firstScene, Config.DealerAnimDictPoker, 'female_deck_pick_up', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, firstScene, Config.DealerAnimDictPoker, 'deck_pick_up', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ while GetSynchronizedScenePhase(firstScene) < 0.99 do
+ if HasAnimEventFired(self.ped, 1691374422) then
+ if not IsEntityAttachedToAnyPed(self.pakli) then
+ FreezeEntityPosition(self.pakli, false)
+ AttachEntityToEntity(self.pakli, self.ped, GetPedBoneIndex(self.ped, 60309), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, false, false, false, true, 2, true)
+ end
+ end
+ Citizen.Wait(1)
+ end
+
+ -- collect player cards
+ for targetSrc, data in pairs(self.ServerCards) do
+ if targetSrc ~= 'dealer' then
+ local playerAnimId = nil
+
+ if data.chairData.chairId == 4 then -- this is reverse because rockstar think differently no idea why
+ playerAnimId = 'p01'
+ elseif data.chairData.chairId == 3 then
+ playerAnimId = 'p02'
+ elseif data.chairData.chairId == 2 then
+ playerAnimId = 'p03'
+ elseif data.chairData.chairId == 1 then
+ playerAnimId = 'p04'
+ end
+
+ local collectScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, collectScene, Config.DealerAnimDictPoker, string.format('female_cards_collect_%s', playerAnimId), 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, collectScene, Config.DealerAnimDictPoker, string.format('cards_collect_%s', playerAnimId), 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ PlaySynchronizedEntityAnim(
+ self.cards[targetSrc][1],
+ collectScene,
+ string.format('cards_collect_%s_card_a', playerAnimId),
+ Config.DealerAnimDictPoker,
+ 1000.0,
+ 0,
+ 0,
+ 1000.0
+ )
+ PlaySynchronizedEntityAnim(
+ self.cards[targetSrc][2],
+ collectScene,
+ string.format('cards_collect_%s_card_b', playerAnimId),
+ Config.DealerAnimDictPoker,
+ 1000.0,
+ 0,
+ 0,
+ 1000.0
+ )
+ PlaySynchronizedEntityAnim(
+ self.cards[targetSrc][3],
+ collectScene,
+ string.format('cards_collect_%s_card_c', playerAnimId),
+ Config.DealerAnimDictPoker,
+ 1000.0,
+ 0,
+ 0,
+ 1000.0
+ )
+ while GetSynchronizedScenePhase(collectScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+
+ DeleteObject(self.cards[targetSrc][1])
+ DeleteObject(self.cards[targetSrc][2])
+ DeleteObject(self.cards[targetSrc][3])
+ end
+ end
+
+ -- collect own dealer cards
+ if self.ServerCards['dealer'] then
+ local collectScene = CreateSynchronizedScene(self.data.Position, 0.0, 0.0, self.data.Heading, 2)
+ if self.isPedFemale() then
+ TaskSynchronizedScene(self.ped, collectScene, Config.DealerAnimDictPoker, 'female_cards_collect_self', 2.0, -2.0, 13, 16, 1000.0, 0)
+ else
+ TaskSynchronizedScene(self.ped, collectScene, Config.DealerAnimDictPoker, 'cards_collect_self', 2.0, -2.0, 13, 16, 1000.0, 0)
+ end
+ PlaySynchronizedEntityAnim(self.cards['dealer'][1], collectScene, 'cards_collect_self_card_a', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][2], collectScene, 'cards_collect_self_card_b', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ PlaySynchronizedEntityAnim(self.cards['dealer'][3], collectScene, 'cards_collect_self_card_c', Config.DealerAnimDictPoker, 1000.0, 0, 0, 1000.0)
+ SetBit(0)
+ while GetSynchronizedScenePhase(collectScene) < 0.99 do
+ Citizen.Wait(1)
+ end
+
+ DeleteObject(self.cards['dealer'][1])
+ DeleteObject(self.cards['dealer'][2])
+ DeleteObject(self.cards['dealer'][3])
+ end
+
+ self.putDownDeck()
+ end
+
+ self.playerPairPlusAnim = function(amount)
+ playerPairPlus = amount
+ buttonScaleform = nil
+
+ RequestAnimDict(Config.PlayerAnimDictPoker)
+ while not HasAnimDictLoaded(Config.PlayerAnimDictPoker) do
+ Citizen.Wait(1)
+ end
+
+ local offsetAlign = nil
+ if activeChairData.chairId == 4 then
+ offsetAlign = vector3(0.51655, 0.2268, 0.95)
+ elseif activeChairData.chairId == 3 then
+ offsetAlign = vector3(0.2163, -0.04745, 0.95)
+ elseif activeChairData.chairId == 2 then
+ offsetAlign = vector3(-0.2552, -0.031225, 0.95)
+ elseif activeChairData.chairId == 1 then
+ offsetAlign = vector3(-0.529875, 0.281425, 0.95)
+ end
+
+ if offsetAlign == nil then
+ Config.DebugMsg('Something error happened during the playerBetAnim function.')
+ return
+ end
+
+ local animName = 'bet_plus'
+ if amount >= 10000 then
+ animName = 'bet_plus_large'
+ end
+
+ local scene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, true, false, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, Config.PlayerAnimDictPoker, animName, 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(scene)
+
+ while not HasAnimEventFired(PlayerPedId(), -1424880317) do
+ Citizen.Wait(1)
+ end
+
+ local offset = GetObjectOffsetFromCoords(self.data.Position, self.data.Heading, offsetAlign)
+ local chipModel = getChipModelByAmount(amount)
+ RequestModel(chipModel)
+ while not HasModelLoaded(chipModel) do
+ Citizen.Wait(1)
+ end
+
+ local chipObj = CreateObjectNoOffset(chipModel, offset, true, false, true)
+ SetEntityCoordsNoOffset(chipObj, offset, false, false, true)
+ SetEntityHeading(chipObj, GetEntityHeading(PlayerPedId()))
+ table.insert(networkedChips, chipObj)
+
+ self.playerRandomIdleAnim()
+ end
+
+ self.playerBetAnim = function(amount)
+ playerBetted = amount
+ buttonScaleform = setupSecondButtons('instructional_buttons')
+
+ RequestAnimDict(Config.PlayerAnimDictPoker)
+ while not HasAnimDictLoaded(Config.PlayerAnimDictPoker) do
+ Citizen.Wait(1)
+ end
+
+ local offsetAlign = nil
+ if activeChairData.chairId == 4 then
+ offsetAlign = vector3(0.59535, 0.200875, 0.95)
+ elseif activeChairData.chairId == 3 then
+ offsetAlign = vector3(0.247825, -0.123625, 0.95)
+ elseif activeChairData.chairId == 2 then
+ offsetAlign = vector3(-0.2804, -0.109775, 0.95)
+ elseif activeChairData.chairId == 1 then
+ offsetAlign = vector3(-0.606975, 0.249675, 0.95)
+ end
+
+ if offsetAlign == nil then
+ Config.DebugMsg('Something error happened during the playerBetAnim function.')
+ return
+ end
+
+ local animName = 'bet_ante'
+ if amount >= 10000 then
+ animName = 'bet_ante_large'
+ end
+
+ local scene = NetworkCreateSynchronisedScene(activeChairData.chairCoords, activeChairData.chairRotation, 2, false, true, 1.0, 0.0, 1.0)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), scene, Config.PlayerAnimDictPoker, animName, 2.0, -2.0, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(scene)
+
+ while not HasAnimEventFired(PlayerPedId(), -1424880317) do
+ Citizen.Wait(1)
+ end
+
+ local offset = GetObjectOffsetFromCoords(self.data.Position, self.data.Heading, offsetAlign)
+ local chipModel = getChipModelByAmount(amount)
+ RequestModel(chipModel)
+ while not HasModelLoaded(chipModel) do
+ Citizen.Wait(1)
+ end
+
+ local chipObj = CreateObjectNoOffset(chipModel, offset, true, false, true)
+ SetEntityCoordsNoOffset(chipObj, offset, false, false, true)
+ SetEntityHeading(chipObj, GetEntityHeading(PlayerPedId()))
+ table.insert(networkedChips, chipObj)
+
+ self.playerRandomIdleAnim()
+ end
+
+ self.createDefaultPakli()
+ self.createPed()
+
+ SharedPokers[index] = self
+end
+
+Citizen.CreateThread(function()
+ while true do
+ local playerpos = GetEntityCoords(PlayerPedId())
+ closeToPokers = false
+ for k, v in pairs(Config.Pokers) do
+ if #(playerpos - v.Position) < 100.0 then
+ closeToPokers = true
+ end
+ end
+ Citizen.Wait(1000)
+ end
+end)
+
+Citizen.CreateThread(function()
+ while QBCore == nil do
+ Citizen.Wait(1)
+ end
+ while not closeToPokers do
+ Citizen.Wait(500)
+ end
+ RequestAnimDict(Config.DealerAnimDictShared)
+ RequestAnimDict(Config.DealerAnimDictPoker)
+ RequestAnimDict(Config.PlayerAnimDictShared)
+ RequestAnimDict(Config.PlayerAnimDictPoker)
+ Config.DebugMsg('Poker loading started..')
+ for index, data in pairs(Config.Pokers) do
+ AquiverPoker(index, data)
+ end
+end)
+
+Citizen.CreateThread(function()
+ local alreadyEnteredZone = false
+ while true do
+ local sleep = 5
+ local inZone = false
+ if QBCore and not InformationPlaying and activePokerTable == nil and activeChairData == nil then
+ local playerpos = GetEntityCoords(PlayerPedId())
+ for k, v in pairs(SharedPokers) do
+ local dist = #(playerpos - v.data.Position)
+ if dist < 3.0 then
+ for i = 1, #Config.Tables, 1 do
+ local tableObj = GetClosestObjectOfType(playerpos, 3.0, GetHashKey(Config.Tables[i]), false)
+ if DoesEntityExist(tableObj) then
+ for chairBone, chairId in pairs(Config.PokerChairs) do
+ local chaircoords = GetWorldPositionOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, chairBone))
+ if chaircoords then
+ if #(playerpos - chaircoords) < 1.5 then
+ wait = 5
+ inZone = true
+ text = "The Diamond Casino & ResortPokerPress E to sit"
+
+ local chairrotation = GetWorldRotationOfEntityBone(tableObj, GetEntityBoneIndexByName(tableObj, chairBone))
+ -- drawfreameeMarker(chaircoords + vector3(0.0, 0.0, 1.0))
+
+ if IsControlJustPressed(1, 51) then
+ v.sitDown(chairId, chaircoords, chairrotation)
+ end
+
+ break
+ end
+ end
+ end
+ break
+ end
+ end
+ end
+ end
+ end
+
+ if inZone and not alreadyEnteredZone then
+ alreadyEnteredZone = true
+ exports["qb-core"]:DrawText(text)
+ end
+ if not inZone and alreadyEnteredZone then
+ alreadyEnteredZone = false
+ exports["qb-core"]:HideText()
+ end
+ Wait(sleep)
+ end
+end)
+
+-- OTHERS
+
+function frm_setPedVoiceGroup(randomNumber, dealerPed)
+ if randomNumber == 0 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_WHITE_01'))
+ elseif randomNumber == 1 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_ASIAN_01'))
+ elseif randomNumber == 2 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_ASIAN_02'))
+ elseif randomNumber == 3 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_ASIAN_01'))
+ elseif randomNumber == 4 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_WHITE_01'))
+ elseif randomNumber == 5 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_WHITE_02'))
+ elseif randomNumber == 6 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_M_Y_Casino_01_WHITE_01'))
+ elseif randomNumber == 7 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_ASIAN_01'))
+ elseif randomNumber == 8 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_ASIAN_02'))
+ elseif randomNumber == 9 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_ASIAN_01'))
+ elseif randomNumber == 10 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_ASIAN_02'))
+ elseif randomNumber == 11 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_LATINA_01'))
+ elseif randomNumber == 12 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_LATINA_02'))
+ elseif randomNumber == 13 then
+ SetPedVoiceGroup(dealerPed, GetHashKey('S_F_Y_Casino_01_LATINA_01'))
+ end
+end
+
+function frm_setPedClothes(randomNumber, dealerPed)
+ if randomNumber == 0 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 1 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 2, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 2 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 3 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 4 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 2, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 5 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 6 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 1, 0, 0)
+ elseif randomNumber == 7 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 8 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 9 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 2, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 10 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 3, 3, 3, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 11 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 0, 1, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ SetPedPropIndex(dealerPed, 1, 0, 0, false)
+ elseif randomNumber == 12 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 3, 1, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 3, 1, 0)
+ SetPedComponentVariation(dealerPed, 3, 1, 1, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ elseif randomNumber == 13 then
+ SetPedDefaultComponentVariation(dealerPed)
+ SetPedComponentVariation(dealerPed, 0, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 1, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 2, 4, 0, 0)
+ SetPedComponentVariation(dealerPed, 3, 2, 1, 0)
+ SetPedComponentVariation(dealerPed, 4, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 6, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 7, 1, 0, 0)
+ SetPedComponentVariation(dealerPed, 8, 2, 0, 0)
+ SetPedComponentVariation(dealerPed, 10, 0, 0, 0)
+ SetPedComponentVariation(dealerPed, 11, 0, 0, 0)
+ SetPedPropIndex(dealerPed, 1, 0, 0, false)
+ end
+end
+
+function getChipModelByAmount(amount)
+ if amount <= 10 then
+ return GetHashKey('vw_prop_chip_10dollar_x1')
+ elseif amount > 10 and amount < 50 then
+ return GetHashKey('vw_prop_chip_10dollar_st')
+ elseif amount >= 50 and amount < 100 then
+ return GetHashKey('vw_prop_chip_50dollar_x1')
+ elseif amount >= 100 and amount < 200 then
+ return GetHashKey('vw_prop_chip_100dollar_x1')
+ elseif amount >= 200 and amount < 500 then
+ return GetHashKey('vw_prop_chip_100dollar_st')
+ elseif amount == 500 then
+ return GetHashKey('vw_prop_chip_500dollar_x1')
+ elseif amount > 500 and amount < 1000 then
+ return GetHashKey('vw_prop_chip_500dollar_st')
+ elseif amount == 1000 then
+ return GetHashKey('vw_prop_chip_1kdollar_x1')
+ elseif amount > 1000 and amount < 5000 then
+ return GetHashKey('vw_prop_chip_1kdollar_st')
+ elseif amount == 5000 then
+ return GetHashKey('vw_prop_plaq_5kdollar_x1')
+ elseif amount > 5000 and amount < 10000 then
+ return GetHashKey('vw_prop_plaq_5kdollar_st')
+ elseif amount == 10000 then
+ return GetHashKey('vw_prop_plaq_10kdollar_x1')
+ elseif amount > 10000 then
+ return GetHashKey('vw_prop_plaq_10kdollar_st')
+ end
+end
+
+function setupSecondButtons(scaleform)
+ -- to have the 'hint' sound effect
+ PlaySoundFrontend(-1, 'FocusIn', 'HintCamSounds', true)
+ ---
+ local scaleform = RequestScaleformMovie(scaleform)
+ while not HasScaleformMovieLoaded(scaleform) do
+ Citizen.Wait(0)
+ end
+ PushScaleformMovieFunction(scaleform, 'CLEAR_ALL')
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_CLEAR_SPACE')
+ PushScaleformMovieFunctionParameterInt(200)
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(1)
+ Button(GetControlInstructionalButton(0, 177, true)) -- The button to display
+ ButtonMessage(_U('leave_game'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(2)
+ Button(GetControlInstructionalButton(0, 172, true))
+ ButtonMessage(_U('raise_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(3)
+ Button(GetControlInstructionalButton(0, 173, true))
+ ButtonMessage(_U('reduce_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(4)
+ Button(GetControlInstructionalButton(0, 22, true))
+ ButtonMessage(_U('custom_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(5)
+ Button(GetControlInstructionalButton(0, 176, true))
+ ButtonMessage(_U('place_pair_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'DRAW_INSTRUCTIONAL_BUTTONS')
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_BACKGROUND_COLOUR')
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(80)
+ PopScaleformMovieFunctionVoid()
+
+ return scaleform
+end
+
+function setupFirstButtons(scaleform)
+ local scaleform = RequestScaleformMovie(scaleform)
+ while not HasScaleformMovieLoaded(scaleform) do
+ Citizen.Wait(0)
+ end
+ PushScaleformMovieFunction(scaleform, 'CLEAR_ALL')
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_CLEAR_SPACE')
+ PushScaleformMovieFunctionParameterInt(200)
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(1)
+ Button(GetControlInstructionalButton(0, 177, true)) -- The button to display
+ ButtonMessage(_U('leave_game'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(2)
+ Button(GetControlInstructionalButton(0, 172, true))
+ ButtonMessage(_U('raise_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(3)
+ Button(GetControlInstructionalButton(0, 173, true))
+ ButtonMessage(_U('reduce_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(4)
+ Button(GetControlInstructionalButton(0, 22, true))
+ ButtonMessage(_U('custom_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+ PushScaleformMovieFunctionParameterInt(5)
+ Button(GetControlInstructionalButton(0, 176, true))
+ ButtonMessage(_U('place_bet'))
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'DRAW_INSTRUCTIONAL_BUTTONS')
+ PopScaleformMovieFunctionVoid()
+
+ PushScaleformMovieFunction(scaleform, 'SET_BACKGROUND_COLOUR')
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(0)
+ PushScaleformMovieFunctionParameterInt(80)
+ PopScaleformMovieFunctionVoid()
+
+ return scaleform
+end
+
+function Button(ControlButton)
+ N_0xe83a3e3557a56640(ControlButton)
+end
+
+function ButtonMessage(text)
+ BeginTextCommandScaleformString('STRING')
+ AddTextComponentScaleform(text)
+ EndTextCommandScaleformString()
+end
+
+-- function setupThirdButtons(scaleform)
+-- -- to have the 'hint' sound effect
+-- PlaySoundFrontend(-1, 'FocusIn', 'HintCamSounds', true)
+-- ---
+
+-- local scaleform = RequestScaleformMovie(scaleform)
+-- while not HasScaleformMovieLoaded(scaleform) do
+-- Citizen.Wait(0)
+-- end
+-- PushScaleformMovieFunction(scaleform, 'CLEAR_ALL')
+-- PopScaleformMovieFunctionVoid()
+
+-- PushScaleformMovieFunction(scaleform, 'SET_CLEAR_SPACE')
+-- PushScaleformMovieFunctionParameterInt(200)
+-- PopScaleformMovieFunctionVoid()
+
+-- PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+-- PushScaleformMovieFunctionParameterInt(1)
+-- Button(GetControlInstructionalButton(0, 177, true)) -- The button to display
+-- ButtonMessage(_U('fold_cards'))
+-- PopScaleformMovieFunctionVoid()
+
+-- PushScaleformMovieFunction(scaleform, 'SET_DATA_SLOT')
+-- PushScaleformMovieFunctionParameterInt(2)
+-- Button(GetControlInstructionalButton(0, 38, true))
+-- ButtonMessage(_U('play_cards'))
+-- PopScaleformMovieFunctionVoid()
+
+-- PushScaleformMovieFunction(scaleform, 'DRAW_INSTRUCTIONAL_BUTTONS')
+-- PopScaleformMovieFunctionVoid()
+
+-- PushScaleformMovieFunction(scaleform, 'SET_BACKGROUND_COLOUR')
+-- PushScaleformMovieFunctionParameterInt(0)
+-- PushScaleformMovieFunctionParameterInt(0)
+-- PushScaleformMovieFunctionParameterInt(0)
+-- PushScaleformMovieFunctionParameterInt(80)
+-- PopScaleformMovieFunctionVoid()
+
+-- return scaleform
+-- end
+
+-- function drawText2d(x, y, sc, text)
+-- SetTextFont(0)
+-- SetTextScale(sc, sc)
+-- SetTextCentre(true)
+-- SetTextOutline()
+-- SetTextColour(254, 254, 254, 255)
+-- SetTextEntry('STRING')
+-- AddTextComponentString(text)
+-- DrawText(x, y)
+-- end
+
+-- function DrawAdvancedNativeText(x, y, w, h, sc, text, r, g, b, a, font, jus)
+-- SetTextFont(font)
+-- SetTextScale(sc, sc)
+-- N_0x4e096588b13ffeca(jus)
+-- SetTextColour(254, 254, 254, 255)
+-- SetTextEntry('STRING')
+-- AddTextComponentString(text)
+-- DrawText(x - 0.1 + w, y - 0.02 + h)
+-- end
+
+-- function getGenericTextInput(type)
+-- if type == nil then
+-- type = ''
+-- end
+-- AddTextEntry('FMMC_MPM_NA', tostring(type))
+-- DisplayOnscreenKeyboard(1, 'FMMC_MPM_NA', tostring(type), '', '', '', '', 30)
+-- while (UpdateOnscreenKeyboard() == 0) do
+-- DisableAllControlActions(0)
+-- Wait(0)
+-- end
+-- if (GetOnscreenKeyboardResult()) then
+-- local result = GetOnscreenKeyboardResult()
+-- if result then
+-- return result
+-- end
+-- end
+-- return false
+-- end
+
+-- function drawfreameeMarker(position)
+-- DrawMarker(20, position, 0.0, 0.0, 0.0, 180.0, 0.0, 0.0, 0.3, 0.3, 0.3, 255, 255, 255, 255, true, true, 2, true, nil, nil, false)
+-- end
+
+-- RMenu.Add('aquiver_poker', 'instructions', RageUI.CreateMenu('', 'test', 0, 100, 'CasinoUI_Cards_Three_High', 'CasinoUI_Cards_Three_High'))
+-- RMenu:Get('aquiver_poker', 'instructions'):SetSubtitle(_U('tcp'))
+
+-- function showHowTo()
+-- Citizen.CreateThread(
+-- function()
+-- local helps = {_U('desc_1'), _U('desc_2'), _U('desc_3')}
+
+-- InformationPlaying = true
+
+-- for i = 1, #helps, 1 do
+-- PlaySoundFrontend(-1, 'DLC_VW_CONTINUE', 'dlc_vw_table_games_frontend_sounds', true)
+-- BeginTextCommandDisplayHelp(helps[i])
+-- EndTextCommandDisplayHelp(0, false, false, Config.HowToSpeed)
+
+-- Citizen.Wait(Config.HowToSpeed)
+-- if helps[i + 1] == nil then
+-- InformationPlaying = false
+-- end
+-- end
+-- end
+-- )
+-- end
+
+-- function showRules()
+-- Citizen.CreateThread(
+-- function()
+-- local helps = {_U('rule_1'), _U('rule_2'), _U('rule_3'), _U('rule_4'), _U('rule_5')}
+-- local helpsHeader = {_U('rule_header_1'), _U('rule_header_2'), _U('rule_header_3'), _U('rule_header_4'), _U('rule_header_5')}
+
+-- InformationPlaying = true
+
+-- for i = 1, #helps, 1 do
+-- PlaySoundFrontend(-1, 'DLC_VW_CONTINUE', 'dlc_vw_table_games_frontend_sounds', true)
+-- BeginTextCommandDisplayHelp(helpsHeader[i])
+-- AddTextComponentSubstringTextLabel(helps[i])
+-- EndTextCommandDisplayHelp(0, false, false, Config.HowToSpeed)
+
+-- Citizen.Wait(Config.HowToSpeed)
+-- if helps[i + 1] == nil then
+-- InformationPlaying = false
+-- end
+-- end
+-- end
+-- )
+-- end
+
+-- You can use this command to implement your POKER TABLES
+-- You get the results out in the console, after you can register in the c onfig.
+--[[RegisterCommand(
+ 'getpokertable',
+ function()
+ local found = false
+
+ local playercoords = GetEntityCoords(PlayerPedId())
+ for i = 1, #Config.Tables, 1 do
+ local obj = GetClosestObjectOfType(playercoords, 3.0, GetHashKey(Config.Tables[i]), false, false, false)
+ if DoesEntityExist(obj) then
+ found = true
+ end
+ end
+
+ if not found then
+ print('none table found.')
+ end
+ end
+)--]]
diff --git a/resources/[qb]/[qb_casino]/casino-poker/config.lua b/resources/[qb]/[qb_casino]/casino-poker/config.lua
new file mode 100644
index 0000000..a751f30
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-poker/config.lua
@@ -0,0 +1,531 @@
+Config = {}
+Config.Locale = 'en'
+QBCore = exports['qb-core']:GetCoreObject()
+
+-- YOUR MAIN SETUPS
+Config.Debug = false -- enable debug messages in sv/cl console
+Config.TimeLeftAfter = 15 -- time remaining after one player betted (dealer actions start timeout)
+Config.PlayerDecideTime = 15 -- player decide time (when watching our cards)
+Config.HowToSpeed = 5000 -- x seconds to change to next
+Config.ShowCardsAfterReveal = true -- showing cameras on the players cards when revealing them
+
+Config.Pokers = {
+ [1] = {
+ Position = vector3(996.17, 51.69, 68.45),
+ Heading = 318.91,
+ MaximumBet = 2500,
+ MinimumBet = 50
+ },
+ [2] = {
+ Position = vector3(1000.66, 50.88, 68.45),
+ Heading = 6.73,
+ MaximumBet = 2500,
+ MinimumBet = 50
+ },
+ [3] = {
+ Position = vector3(984.97, 66.64, 69.25),
+ Heading = 3.39,
+ MaximumBet = 2000,
+ MinimumBet = 50
+ },
+ [4] = {
+ Position = vector3(998.44, 60.99, 68.45),
+ Heading = 191.77,
+ MaximumBet = 2000,
+ MinimumBet = 50
+ },
+ [5] = {
+ Position = vector3(994.89, 58.29, 68.45),
+ Heading = 237.13,
+ MaximumBet = 2000,
+ MinimumBet = 50
+ },
+ [6] = {
+ Position = vector3(988.45, 64.38, 69.25),
+ Heading = 278.52,
+ MaximumBet = 2000,
+ MinimumBet = 50
+ },
+ [7] = {
+ Position = vector3(991.56, 40.10, 69.25),
+ Heading = 200.84,
+ MaximumBet = 2000,
+ MinimumBet = 50
+ },
+ [8] = {
+ Position = vector3(993.20, 43.70, 69.25),
+ Heading = 279.25,
+ MaximumBet = 2000,
+ MinimumBet = 50
+ }
+}
+
+-- DO NOT WORRY ABOUT DOWNSIDE
+
+Config.Tables = {
+ 'h4_prop_casino_3cardpoker_01a',
+ 'h4_prop_casino_3cardpoker_01b',
+ 'h4_prop_casino_3cardpoker_01c',
+ 'h4_prop_casino_3cardpoker_01e',
+ 'vw_prop_casino_3cardpoker_01b',
+ 'vw_prop_casino_3cardpoker_01'
+}
+
+Config.DealerAnimDictShared = 'anim_casino_b@amb@casino@games@shared@dealer@'
+Config.DealerAnimDictPoker = 'anim_casino_b@amb@casino@games@threecardpoker@dealer'
+Config.PlayerAnimDictShared = 'anim_casino_b@amb@casino@games@shared@player@'
+Config.PlayerAnimDictPoker = 'anim_casino_b@amb@casino@games@threecardpoker@player'
+
+Config.IncreaseAmounts = function(currentAmount)
+ if currentAmount < 500 then
+ return 50
+ elseif currentAmount >= 500 and currentAmount < 2000 then
+ return 100
+ elseif currentAmount >= 2000 and currentAmount < 5000 then
+ return 200
+ elseif currentAmount >= 5000 and currentAmount < 10000 then
+ return 500
+ elseif currentAmount >= 10000 then
+ return 1000
+ else
+ return 50
+ end
+end
+
+Config.PokerChairs = {
+ ['Chair_Base_01'] = 1,
+ ['Chair_Base_02'] = 2,
+ ['Chair_Base_03'] = 3,
+ ['Chair_Base_04'] = 4
+}
+
+Config.GetCardType = function(cardArrayId)
+ if cardArrayId >= 1 and cardArrayId <= 13 then -- CLUBS
+ return 0
+ elseif cardArrayId >= 14 and cardArrayId <= 26 then -- DIAMOND
+ return 1
+ elseif cardArrayId >= 26 and cardArrayId <= 39 then -- HEARTS
+ return 2
+ elseif cardArrayId >= 39 and cardArrayId <= 52 then -- SPADES
+ return 3
+ end
+end
+
+Config.GetCardValue = function(cardArrayId)
+ local vals = {
+ -- 2
+ [2] = 2,
+ [15] = 2,
+ [28] = 2,
+ [41] = 2,
+ -- 3
+ [3] = 3,
+ [16] = 3,
+ [29] = 3,
+ [42] = 3,
+ -- 4
+ [4] = 4,
+ [17] = 4,
+ [30] = 4,
+ [43] = 4,
+ -- 5
+ [5] = 5,
+ [18] = 5,
+ [31] = 5,
+ [44] = 5,
+ -- 6
+ [6] = 6,
+ [19] = 6,
+ [32] = 6,
+ [45] = 6,
+ -- 7
+ [7] = 7,
+ [20] = 7,
+ [33] = 7,
+ [46] = 7,
+ -- 8
+ [8] = 8,
+ [21] = 8,
+ [34] = 8,
+ [47] = 8,
+ -- 9
+ [9] = 9,
+ [22] = 9,
+ [35] = 9,
+ [48] = 9,
+ -- 10
+ [10] = 10,
+ [23] = 10,
+ [36] = 10,
+ [49] = 10,
+ -- JACK
+ [11] = 11,
+ [24] = 11,
+ [37] = 11,
+ [50] = 11,
+ -- QUEEN
+ [12] = 12,
+ [25] = 12,
+ [38] = 12,
+ [51] = 12,
+ -- KING
+ [13] = 13,
+ [26] = 13,
+ [39] = 13,
+ [52] = 13,
+ -- ACE
+ [1] = 14,
+ [14] = 14,
+ [27] = 14,
+ [40] = 14
+ }
+
+ if vals[cardArrayId] then
+ return vals[cardArrayId]
+ else
+ return 0
+ end
+end
+
+Config.Cards = {
+ -- i kwow its a default array, not an object key array, i know what i am doing, its easier to see the numbers like this
+ [1] = 'vw_prop_vw_club_char_a_a',
+ [2] = 'vw_prop_vw_club_char_02a',
+ [3] = 'vw_prop_vw_club_char_03a',
+ [4] = 'vw_prop_vw_club_char_04a',
+ [5] = 'vw_prop_vw_club_char_05a',
+ [6] = 'vw_prop_vw_club_char_06a',
+ [7] = 'vw_prop_vw_club_char_07a',
+ [8] = 'vw_prop_vw_club_char_08a',
+ [9] = 'vw_prop_vw_club_char_09a',
+ [10] = 'vw_prop_vw_club_char_10a',
+ [11] = 'vw_prop_vw_club_char_j_a',
+ [12] = 'vw_prop_vw_club_char_q_a',
+ [13] = 'vw_prop_vw_club_char_k_a',
+ [14] = 'vw_prop_vw_dia_char_a_a',
+ [15] = 'vw_prop_vw_dia_char_02a',
+ [16] = 'vw_prop_vw_dia_char_03a',
+ [17] = 'vw_prop_vw_dia_char_04a',
+ [18] = 'vw_prop_vw_dia_char_05a',
+ [19] = 'vw_prop_vw_dia_char_06a',
+ [20] = 'vw_prop_vw_dia_char_07a',
+ [21] = 'vw_prop_vw_dia_char_08a',
+ [22] = 'vw_prop_vw_dia_char_09a',
+ [23] = 'vw_prop_vw_dia_char_10a',
+ [24] = 'vw_prop_vw_dia_char_j_a',
+ [25] = 'vw_prop_vw_dia_char_q_a',
+ [26] = 'vw_prop_vw_dia_char_k_a',
+ [27] = 'vw_prop_vw_hrt_char_a_a',
+ [28] = 'vw_prop_vw_hrt_char_02a',
+ [29] = 'vw_prop_vw_hrt_char_03a',
+ [30] = 'vw_prop_vw_hrt_char_04a',
+ [31] = 'vw_prop_vw_hrt_char_05a',
+ [32] = 'vw_prop_vw_hrt_char_06a',
+ [33] = 'vw_prop_vw_hrt_char_07a',
+ [34] = 'vw_prop_vw_hrt_char_08a',
+ [35] = 'vw_prop_vw_hrt_char_09a',
+ [36] = 'vw_prop_vw_hrt_char_10a',
+ [37] = 'vw_prop_vw_hrt_char_j_a',
+ [38] = 'vw_prop_vw_hrt_char_q_a',
+ [39] = 'vw_prop_vw_hrt_char_k_a',
+ [40] = 'vw_prop_vw_spd_char_a_a',
+ [41] = 'vw_prop_vw_spd_char_02a',
+ [42] = 'vw_prop_vw_spd_char_03a',
+ [43] = 'vw_prop_vw_spd_char_04a',
+ [44] = 'vw_prop_vw_spd_char_05a',
+ [45] = 'vw_prop_vw_spd_char_06a',
+ [46] = 'vw_prop_vw_spd_char_07a',
+ [47] = 'vw_prop_vw_spd_char_08a',
+ [48] = 'vw_prop_vw_spd_char_09a',
+ [49] = 'vw_prop_vw_spd_char_10a',
+ [50] = 'vw_prop_vw_spd_char_j_a',
+ [51] = 'vw_prop_vw_spd_char_q_a',
+ [52] = 'vw_prop_vw_spd_char_k_a'
+}
+
+Config.getHandAllValues = function(handTable, bool_1, bool_2)
+ if type(handTable) == 'table' then
+ local c1, c2, c3 = Config.GetCardValue(handTable[1]), Config.GetCardValue(handTable[2]), Config.GetCardValue(handTable[3])
+
+ local handValue = 0
+
+ -- FIRST CHECK
+ if (c1 ~= c2 and c1 ~= c3) and c2 ~= c3 then
+ local Flush = false
+
+ handValue = c1 + c2 + c3
+
+ if handValue == 19 then
+ if (c1 == 14 or c1 == 2 or c1 == 3) and (c2 == 14 or c2 == 2 or c2 == 3) and (c3 == 14 or c3 == 2 or c3 == 3) then
+ Flush = true
+ end
+ elseif handValue == 9 then
+ if (c1 == 2 or c1 == 3 or c1 == 4) and (c2 == 2 or c2 == 3 or c2 == 4) and (c3 == 2 or c3 == 3 or c3 == 4) then
+ Flush = true
+ end
+ elseif handValue == 12 then
+ if (c1 == 3 or c1 == 4 or c1 == 5) and (c2 == 3 or c2 == 4 or c2 == 5) and (c3 == 3 or c3 == 4 or c3 == 5) then
+ Flush = true
+ end
+ elseif handValue == 15 then
+ if (c1 == 4 or c1 == 5 or c1 == 6) and (c2 == 4 or c2 == 5 or c2 == 6) and (c3 == 4 or c3 == 5 or c3 == 6) then
+ Flush = true
+ end
+ elseif handValue == 18 then
+ if (c1 == 5 or c1 == 6 or c1 == 7) and (c2 == 5 or c2 == 6 or c2 == 7) and (c3 == 5 or c3 == 6 or c3 == 7) then
+ Flush = true
+ end
+ elseif handValue == 21 then
+ if (c1 == 6 or c1 == 7 or c1 == 8) and (c2 == 6 or c2 == 7 or c2 == 8) and (c3 == 6 or c3 == 7 or c3 == 8) then
+ Flush = true
+ end
+ elseif handValue == 24 then
+ if (c1 == 7 or c1 == 8 or c1 == 9) and (c2 == 7 or c2 == 8 or c2 == 9) and (c3 == 7 or c3 == 8 or c3 == 9) then
+ Flush = true
+ end
+ elseif handValue == 27 then
+ if (c1 == 8 or c1 == 9 or c1 == 10) and (c2 == 8 or c2 == 9 or c2 == 10) and (c3 == 8 or c3 == 9 or c3 == 10) then
+ Flush = true
+ end
+ elseif handValue == 30 then
+ if (c1 == 9 or c1 == 10 or c1 == 11) and (c2 == 9 or c2 == 10 or c2 == 11) and (c3 == 9 or c3 == 10 or c3 == 11) then
+ Flush = true
+ end
+ elseif handValue == 33 then
+ if (c1 == 10 or c1 == 11 or c1 == 12) and (c2 == 10 or c2 == 11 or c2 == 12) and (c3 == 10 or c3 == 11 or c3 == 12) then
+ Flush = true
+ end
+ elseif handValue == 36 then
+ if (c1 == 11 or c1 == 12 or c1 == 13) and (c2 == 11 or c2 == 12 or c3 == 13) and (c3 == 11 or c3 == 12 or c3 == 13) then
+ --something true
+ Flush = true
+ end
+ elseif handValue == 39 then
+ if (c1 == 12 or c1 == 13 or c1 == 14) and (c2 == 12 or c2 == 13 or c2 == 14) and (c3 == 12 or c3 == 13 or c3 == 14) then
+ --something true
+ Flush = true
+ end
+ end
+
+ if Flush then
+ if handValue == 19 then
+ handValue = 6
+ end
+
+ if Config.GetCardType(handTable[1]) == Config.GetCardType(handTable[2]) and Config.GetCardType(handTable[1]) == Config.GetCardType(handTable[3]) then
+ return handValue + 500
+ end
+
+ return handValue + 300
+ end
+ end
+
+ handValue = 0
+
+ -- SECOND CHECK
+ if (c1 == c2) and c1 ~= c3 then -- pairs
+ if not bool_1 and not bool_2 then
+ return (c1 + c2) + 100
+ else
+ return c3
+ end
+ elseif (c2 == c3) and c2 ~= c1 then -- pairs
+ if not bool_1 and not bool_2 then
+ return (c2 + c3) + 100
+ else
+ return c1
+ end
+ elseif (c3 == c1) and c3 ~= c2 then -- pairs
+ if not bool_1 and not bool_2 then
+ return (c1 + c3) + 100
+ else
+ return c2
+ end
+ elseif c1 == c2 and c1 == c3 then -- 3 of a kind
+ return c1 + c2 + c3 + 400
+ elseif Config.GetCardType(handTable[1]) == Config.GetCardType(handTable[2]) and Config.GetCardType(handTable[1]) == Config.GetCardType(handTable[3]) then
+ handValue = 200
+ end
+
+ -- third check if it runs here
+
+ if c1 > c2 and c1 > c3 then
+ if bool_1 then
+ if c2 > c3 then
+ return handValue + c2
+ else
+ return handValue + c3
+ end
+ elseif bool_2 then
+ if c2 > c3 then
+ return handValue + c3
+ else
+ return handValue + c2
+ end
+ end
+
+ return handValue + c1
+ elseif c2 > c1 and c2 > c3 then
+ if bool_1 then
+ if c1 > c3 then
+ return handValue + c1
+ else
+ return handValue + c3
+ end
+ elseif bool_2 then
+ if c1 > c3 then
+ return handValue + c3
+ else
+ return handValue + c1
+ end
+ end
+
+ return handValue + c2
+ elseif c3 > c1 and c3 > c2 then
+ if bool_1 then
+ if c1 > c2 then
+ return handValue + c1
+ else
+ return handValue + c2
+ end
+ elseif bool_2 then
+ if c1 > c2 then
+ return handValue + c2
+ else
+ return handValue + c1
+ end
+ end
+
+ return handValue + c3
+ end
+
+ return handValue
+ else
+ return 0
+ end
+end
+
+Config.GetPairMultiplier = function(handValue)
+ if handValue > 500 then
+ return 40
+ elseif handValue > 400 then
+ return 30
+ elseif handValue > 300 then
+ return 6
+ elseif handValue > 200 then
+ return 4
+ elseif handValue > 100 then
+ return 1
+ end
+
+ return 0
+end
+
+Config.GetAnteMultiplier = function(handValue)
+ if handValue > 500 then
+ return 5
+ elseif handValue > 400 then
+ return 4
+ elseif handValue > 300 then
+ return 1
+ end
+
+ return 0
+end
+
+Config.formatHandValue = function(handValue)
+ if handValue > 500 then
+ return 'Straight flush'
+ elseif handValue > 400 then
+ return '3 of a kind'
+ elseif handValue > 300 then
+ return 'Straight'
+ elseif handValue > 200 then
+ return 'Flush'
+ elseif handValue > 100 then
+ if handValue == 128 then
+ return 'Pair Ace'
+ elseif handValue == 104 then
+ return 'Pair 2'
+ elseif handValue == 106 then
+ return 'Pair 3'
+ elseif handValue == 108 then
+ return 'Pair 4'
+ elseif handValue == 110 then
+ return 'Pair 5'
+ elseif handValue == 112 then
+ return 'Pair 6'
+ elseif handValue == 114 then
+ return 'Pair 7'
+ elseif handValue == 116 then
+ return 'Pair 8'
+ elseif handValue == 118 then
+ return 'Pair 9'
+ elseif handValue == 120 then
+ return 'Pair 10'
+ elseif handValue == 122 then
+ return 'Pair Jack'
+ elseif handValue == 124 then
+ return 'Pair Queen'
+ elseif handValue == 126 then
+ return 'Pair King'
+ end
+ elseif handValue == 5 then
+ return 'High Card 5'
+ elseif handValue == 6 then
+ return 'High Card 6'
+ elseif handValue == 7 then
+ return 'High Card 7'
+ elseif handValue == 8 then
+ return 'High Card 8'
+ elseif handValue == 9 then
+ return 'High Card 9'
+ elseif handValue == 10 then
+ return 'High Card 10'
+ elseif handValue == 11 then
+ return 'High Card Jack'
+ elseif handValue == 12 then
+ return 'High Card Queen'
+ elseif handValue == 13 then
+ return 'High Card King'
+ else
+ return 'High Card Ace'
+ end
+
+ return ''
+end
+
+Config.canDealerPlay = function(handValue)
+ if handValue >= 12 then
+ return true
+ else
+ return false
+ end
+end
+
+Config.DebugMsg = function(msg)
+ if Config.Debug then
+ print(msg)
+ end
+end
+
+Locales = {}
+function _(str, ...) -- Translate string
+
+ if Locales[Config.Locale] ~= nil then
+
+ if Locales[Config.Locale][str] ~= nil then
+ return string.format(Locales[Config.Locale][str], ...)
+ else
+ return 'Translation [' .. Config.Locale .. '][' .. str .. '] does not exist'
+ end
+
+ else
+ return 'Locale [' .. Config.Locale .. '] does not exist'
+ end
+
+end
+
+function _U(str, ...) -- Translate string first char uppercase
+ return tostring(_(str, ...):gsub("^%l", string.upper))
+end
diff --git a/resources/[qb]/[qb_casino]/casino-poker/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-poker/fxmanifest.lua
new file mode 100644
index 0000000..6bbcb63
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-poker/fxmanifest.lua
@@ -0,0 +1,19 @@
+shared_scripts {
+ 'config.lua'
+}
+
+client_scripts {
+ 'locales/*.lua',
+ 'client/*.lua',
+}
+
+server_scripts {
+ -- 'config.lua',
+ 'locales/*.lua',
+ 'server/sv_main.lua'
+}
+
+
+
+game 'gta5'
+fx_version 'cerulean'
diff --git a/resources/[qb]/[qb_casino]/casino-poker/locales/en.lua b/resources/[qb]/[qb_casino]/casino-poker/locales/en.lua
new file mode 100644
index 0000000..e19d5d0
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-poker/locales/en.lua
@@ -0,0 +1,58 @@
+Locales['en'] = {
+ -- notifications
+ ['chair_occupied'] = 'This seat is occupied.',
+ ['no_react'] = 'You did not respond for the dealer ask in time, you have folded your hand.',
+ ['no_bet_input'] = 'You did not set up a bet value.',
+ ['not_enough_chips'] = 'You do not have enough chips.',
+ ['not_enough_chips_next'] = 'You do not have enough chips to bet on the Pair Plus, because you would not have enough chips for the playing.',
+ ['not_enough_chips_third'] = 'You can not put that amount of chips because you would not have enough for playing your hand.',
+ ['not_enough_chips_toplay'] = 'You do not have enough chips to play!',
+ ['already_betted']= 'You already betted.',
+ ['lose'] = 'You lose!',
+ -- formatted notif
+ ['dealer_not_qual'] = 'Draw.\nThe Dealer did not qualify for the game.\nYou got %s chips back.',
+ ['dealer_not_qual_ante'] = 'Draw.\nThe Dealer did not qualify for the game.\nYou got %s chips back. (Ante multiplier: x%s)',
+ ['player_won_ante'] = 'Your hand won!\nYou got %s chips. (Ante multiplier: x%s)',
+ ['player_won'] = 'Your hand won!\nYou got %s chips.',
+ ['pair_won'] = 'You won %s chips with your Pair Plus bet! (Pair multiplier: x%s)',
+ -- hud
+ -- ['current_bet_input'] = 'BET:',
+ -- ['current_player_chips'] = 'CHIPS:',
+ -- ['table_min_max'] = 'MIN/MAX:',
+ -- ['remaining_time'] = 'TIME:',
+ -- top left
+ ['waiting_for_players'] = 'Waiting for players...',
+ ['clearing_table'] = 'Clearing the table...Next game starting soon.',
+ ['dealer_showing_hand'] = 'The Dealer is showing their hand.',
+ ['players_showing_hands'] = 'Revealing player hands...',
+ ['dealing_cards'] = 'Dealing cards to players...',
+ -- inputs
+ ['fold_cards'] = 'Fold',
+ ['play_cards'] = 'Play',
+ -- ['leave_game'] = 'Leave game',
+ -- ['raise_bet'] = 'Raise bet',
+ -- ['reduce_bet'] = 'Reduce bet',
+ -- ['custom_bet'] = 'Custom bet',
+ -- ['place_bet'] = 'Place bet',
+ ['place_pair_bet'] = 'Place Pair Plus bet',
+ -- gtao ui
+ -- ['tcp'] = '[Aquiver] ~b~Three Card Poker',
+ -- ['sit_down_table'] = '~h~Play ~b~Three Card Poker',
+ -- ['description'] = 'Game Description',
+ -- ['desc_1'] = 'TCP_DIS1', -- this is Rockstar Setuped default, this will automaticly change if you are using german language etc.
+ -- ['desc_2'] = 'TCP_DIS2',
+ -- ['desc_3'] = 'TCP_DIS3',
+ -- ['description_info'] = 'How is the game working?',
+ -- ['rule_1'] = 'TCP_RULE_1',
+ -- ['rule_2'] = 'TCP_RULE_2',
+ -- ['rule_3'] = 'TCP_RULE_3',
+ -- ['rule_4'] = 'TCP_RULE_4',
+ -- ['rule_5'] = 'TCP_RULE_5',
+ -- ['rule_header_1'] = 'TCP_RULE_1T',
+ -- ['rule_header_2'] = 'TCP_RULE_2T',
+ -- ['rule_header_3'] = 'TCP_RULE_3T',
+ -- ['rule_header_4'] = 'TCP_RULE_4T',
+ -- ['rule_header_5'] = 'TCP_RULE_5T',
+ -- ['rules'] = 'Game Rules',
+ -- ['rules_info'] = 'Game rules or anything you should know.'
+}
diff --git a/resources/[qb]/[qb_casino]/casino-poker/server/sv_main.lua b/resources/[qb]/[qb_casino]/casino-poker/server/sv_main.lua
new file mode 100644
index 0000000..0996d21
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-poker/server/sv_main.lua
@@ -0,0 +1,484 @@
+QBCore = exports['qb-core']:GetCoreObject()
+
+
+function getPlayerChips(source)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player then
+ if Player.Functions.GetItemByName('casino_redchip') ~= nil then
+ return Player.Functions.GetItemByName('casino_redchip').amount
+ else
+ return 0
+ end
+ else
+ return 0
+ end
+end
+
+function giveChips(source, amount)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player then
+ Player.Functions.AddItem("casino_redchip", amount, nil, nil, false, GetCurrentResourceName(), "", "", "")
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items['casino_redchip'], "add", amount)
+ updatePlayerChips(source)
+ end
+end
+
+function removeChips(source, amount)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player then
+ Player.Functions.RemoveItem("casino_redchip", amount)
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items['casino_redchip'], "remove", amount)
+ updatePlayerChips(source)
+ end
+end
+
+--//////////////////////////--//////////////////////////--//////////////////////////
+
+ServerPokers = {}
+
+RegisterNetEvent('aquiverPoker:standUp')
+RegisterNetEvent('aquiverPoker:betPlayer')
+RegisterNetEvent('aquiverPoker:playCards')
+RegisterNetEvent('aquiverPoker:foldCards')
+RegisterNetEvent('aquiverPoker:betPairPlusPlayer')
+
+AddEventHandler(
+ 'aquiverPoker:foldCards',
+ function(tableId)
+ local source = source
+ if ServerPokers[tableId] ~= nil then
+ ServerPokers[tableId].PlayersFolded[source] = true
+ TriggerClientEvent('aquiverPoker:playerFoldCards', -1, source, tableId)
+ end
+ end
+)
+AddEventHandler(
+ 'aquiverPoker:playCards',
+ function(tableId, bettedAmount)
+ local source = source
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player then
+ if ServerPokers[tableId] ~= nil then
+ if getPlayerChips(source) >= bettedAmount then
+ TriggerClientEvent('aquiverPoker:playerPlayCards', -1, source, tableId)
+ removeChips(source, bettedAmount)
+ else
+ TriggerClientEvent('QBCore:Notify', source, _U('not_enough_chips_toplay'), 'error')
+ end
+ end
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:standUp',
+ function(tableId, chairId)
+ local source = source
+ if ServerPokers[tableId] ~= nil and ServerPokers[tableId].ChairsUsed[chairId] ~= nil then
+ ServerPokers[tableId].ChairsUsed[chairId] = nil
+ Config.DebugMsg('player standup')
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:betPairPlusPlayer',
+ function(tableId, betAmount)
+ local source = source
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player then
+ if ServerPokers[tableId] ~= nil then
+ if ServerPokers[tableId].PairPlusBets[source] == nil then
+ if getPlayerChips(source) < betAmount then
+ TriggerClientEvent('QBCore:Notify', source, _U('not_enough_chips'), 'error')
+ return
+ end
+
+ -- checking if he is able to bet the pair plus without lowering the bets < 0
+ local currentAnteBetAmount = getPlayerBetAmount(source, tableId)
+ if getPlayerChips(source) < (currentAnteBetAmount + betAmount) then
+ TriggerClientEvent('QBCore:Notify', source, _U('not_enough_chips_next'), 'error')
+ return
+ end
+
+ ----------------
+
+ if ServerPokers[tableId].TimeLeft ~= nil and ServerPokers[tableId].TimeLeft > 0 then
+ ServerPokers[tableId].PairPlusBets[source] = betAmount
+ TriggerClientEvent('aquiverPoker:playerPairPlusAnim', Player.PlayerData.source, betAmount)
+ removeChips(source, betAmount)
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', source, _U('already_betted'), 'error')
+ end
+ end
+ end
+ end
+)
+
+AddEventHandler(
+ 'aquiverPoker:betPlayer',
+ function(tableId, chairData, betAmount)
+ local source = source
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player then
+ if ServerPokers[tableId] ~= nil then
+ if ServerPokers[tableId].PlayerBets[source] == nil then
+ if getPlayerChips(source) < betAmount then
+ TriggerClientEvent('QBCore:Notify', source, _U('not_enough_chips'), 'error')
+
+ return
+ end
+
+ -- check the doubled value of the bet for the play deny
+ if getPlayerChips(source) < betAmount * 2 then
+ TriggerClientEvent('QBCore:Notify', source, _U('not_enough_chips_third'), 'error')
+ return
+ end
+
+ ---------------------
+ if ServerPokers[tableId].Active == false then -- really important here
+ -- important to have it after
+ ServerPokers[tableId].TimeLeft = Config.TimeLeftAfter
+ ServerPokers[tableId].Active = true
+ TriggerClientEvent('aquiverPoker:updateState', -1, tableId, ServerPokers[tableId].Active, ServerPokers[tableId].TimeLeft)
+ end
+
+ ------------------------------------------
+
+ if ServerPokers[tableId].TimeLeft ~= nil and ServerPokers[tableId].TimeLeft > 0 then
+ ServerPokers[tableId].PlayerBets[source] = betAmount
+ TriggerClientEvent('aquiverPoker:playerBetAnim', Player.PlayerData.source, betAmount)
+ removeChips(source, betAmount)
+
+ if ServerPokers[tableId].Cards['dealer'] == nil then -- generating dealer hands if not exist
+ ServerPokers[tableId].Cards['dealer'] = {
+ Hand = generateHand(tableId)
+ }
+ end
+
+ if ServerPokers[tableId].Cards[source] == nil then -- generating player hands if not exist
+ ServerPokers[tableId].Cards[source] = {
+ Hand = generateHand(tableId),
+ chairData = chairData
+ }
+ end
+
+ TriggerClientEvent('aquiverPoker:updateCards', -1, tableId, ServerPokers[tableId].Cards)
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', source, _U('already_betted'), 'error')
+ end
+ end
+ end
+ end
+)
+
+-- generating hand function
+function generateHand(tableId)
+ local handTable = {}
+
+ if ServerPokers[tableId] ~= nil then
+ for i = 1, 3, 1 do
+ local randomCard = math.random(1, #Config.Cards)
+
+ while ServerPokers[tableId].UsedCards[randomCard] ~= nil do
+ randomCard = math.random(1, #Config.Cards)
+ end
+
+ ServerPokers[tableId].UsedCards[randomCard] = true
+ handTable[i] = randomCard
+ end
+
+ return handTable
+ end
+end
+
+Citizen.CreateThread(
+ function()
+ while true do
+ Citizen.Wait(1000)
+
+ for tableId, _ in pairs(ServerPokers) do
+ if ServerPokers[tableId].Active then
+ if ServerPokers[tableId].TimeLeft > 0 then
+ ServerPokers[tableId].TimeLeft = ServerPokers[tableId].TimeLeft - 1
+ TriggerClientEvent('aquiverPoker:updateState', -1, tableId, ServerPokers[tableId].Active, ServerPokers[tableId].TimeLeft)
+
+ if ServerPokers[tableId].TimeLeft < 1 then
+ if ServerPokers[tableId].Stage == 0 then
+ Citizen.CreateThread(
+ function()
+ TriggerClientEvent('aquiverPoker:Stage:1', -1, tableId) -- first ACTION
+
+ Citizen.Wait(9000)
+
+ TriggerClientEvent('aquiverPoker:Stage:2', -1, tableId) -- dealing PLAYER cards
+
+ local activePlayers = getTablePlayersCount(tableId)
+ Config.DebugMsg(string.format('Active poker players: %s', activePlayers))
+
+ Citizen.Wait(4000 * activePlayers)
+
+ TriggerClientEvent('aquiverPoker:Stage:3', -1, tableId) -- dealing DEALER cards
+
+ Citizen.Wait(8000)
+
+ TriggerClientEvent('aquiverPoker:Stage:4', -1, tableId) -- PLAYERS watching cards
+
+ Citizen.Wait((Config.PlayerDecideTime * 1000) + 5000)
+
+ TriggerClientEvent('aquiverPoker:Stage:5', -1, tableId) -- reveal PLAYER cards
+
+ local activePlayers = getTablePlayersCount(tableId)
+ Citizen.Wait(2000 + (5000 * activePlayers))
+
+ TriggerClientEvent('aquiverPoker:Stage:6', -1, tableId) -- reveal DEALER cards
+ Citizen.Wait(10000)
+ CheckWinners(tableId) -- checking winners on server side
+ Citizen.Wait(1500)
+
+ TriggerClientEvent('aquiverPoker:Stage:7', -1, tableId) -- clearing table
+
+ Citizen.Wait(8000 + (4000 * activePlayers))
+
+ TriggerClientEvent('aquiverPoker:resetTable', -1, tableId)
+ ServerPokers[tableId].PlayerBets = {}
+ ServerPokers[tableId].Active = false
+ ServerPokers[tableId].Cards = {}
+ ServerPokers[tableId].UsedCards = {}
+ ServerPokers[tableId].Stage = 0
+ ServerPokers[tableId].TimeLeft = nil
+ ServerPokers[tableId].PlayersFolded = {}
+ ServerPokers[tableId].PairPlusBets = {}
+ end
+ )
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+)
+
+function CheckWinners(tableId)
+ if ServerPokers[tableId] ~= nil then
+ local dealerHand = 0
+ local dealerHand_second = 0
+ local dealerHand_third = 0
+
+ -- dh means dealerhand
+ local dH = ServerPokers[tableId].Cards['dealer']
+ if dH then
+ dealerHand = Config.getHandAllValues(dH.Hand)
+ dealerHand_second = Config.getHandAllValues(dH.Hand, true, false)
+ dealerHand_third = Config.getHandAllValues(dH.Hand, false, true)
+ end
+
+ Config.DebugMsg(string.format('Dealer hand value: %s', dealerHand))
+
+ for targetSrc, data in pairs(ServerPokers[tableId].Cards) do
+ if targetSrc ~= 'dealer' and playerStillExist(targetSrc) then
+ -- check that the player folded their hand or not
+ if ServerPokers[tableId].PlayersFolded[targetSrc] == nil then
+ local playerHand = Config.getHandAllValues(data.Hand)
+ local playerHand_second = Config.getHandAllValues(data.Hand, true, false)
+ local playerHand_third = Config.getHandAllValues(data.Hand, false, true)
+
+ if Config.canDealerPlay(dealerHand) then
+ if playerHand > dealerHand then -- win
+ playerWon(targetSrc, tableId, playerHand)
+ elseif playerHand < dealerHand then -- lose
+ playerLost(targetSrc, tableId, playerHand)
+ elseif playerHand == dealerHand then
+ if playerHand_second == dealerHand_second then -- if equals going more
+ if playerHand_third > dealerHand_third then
+ playerWon(targetSrc, tableId, playerHand)
+ elseif playerHand_third == dealerHand_third then
+ playerDraw(targetSrc, tableId, playerHand)
+ else
+ playerLost(targetSrc, tableId, playerHand)
+ end
+ elseif playerHand_second > dealerHand_second then -- if bigger then win
+ playerWon(targetSrc, tableId, playerHand)
+ else
+ playerLost(targetSrc, tableId, playerHand)
+ end
+ end
+ else
+ playerDraw(targetSrc, tableId, playerHand)
+ Config.DebugMsg('Díler kártyái nem játszottak.')
+ end
+
+ local pairMultiplier = Config.GetPairMultiplier(playerHand)
+ if pairMultiplier > 0 then
+ playerPairPlusWon(targetSrc, tableId, pairMultiplier)
+ end
+ end
+ end
+ end
+ end
+end
+
+function playerPairPlusWon(targetSrc, tableId, pairMultiplier)
+ local betAmount = getPlayerPairPlusBetAmount(targetSrc, tableId)
+ if betAmount > 0 then
+ local Player = QBCore.Functions.GetPlayer(targetSrc)
+ if Player then
+ local plusChips = math.floor(betAmount * pairMultiplier)
+ if plusChips > 0 then
+ TriggerClientEvent('QBCore:Notify', targetSrc, _('pair_won', plusChips, pairMultiplier), 'error')
+ giveChips(targetSrc, plusChips)
+ end
+ end
+ end
+end
+
+
+
+
+function playerWon(targetSrc, tableId, handValue)
+ local betAmount = getPlayerBetAmount(targetSrc, tableId)
+ if betAmount > 0 then
+ local Player = QBCore.Functions.GetPlayer(targetSrc)
+ if Player then
+ local plusChips = math.floor((betAmount * 2) * 2)
+
+ local AnteMultiplier = Config.GetAnteMultiplier(handValue)
+ if AnteMultiplier > 0 then
+ plusChips = math.floor(plusChips + (AnteMultiplier * betAmount))
+ TriggerClientEvent('QBCore:Notify', targetSrc, _('player_won_ante', plusChips, AnteMultiplier), 'error')
+ else
+ TriggerClientEvent('QBCore:Notify', targetSrc, _('player_won', plusChips), 'error')
+ end
+
+ giveChips(targetSrc, plusChips)
+
+ TriggerClientEvent('aquiverPoker:playerWin', targetSrc, tableId)
+ end
+ end
+end
+
+function playerDraw(targetSrc, tableId, handValue)
+ local betAmount = getPlayerBetAmount(targetSrc, tableId)
+ if betAmount > 0 then
+ local plusChips = math.floor(betAmount * 2)
+
+ local Player = QBCore.Functions.GetPlayer(targetSrc)
+ if Player then
+ -- you will get your ante bet bonus even if you loss or draw
+ local AnteMultiplier = Config.GetAnteMultiplier(handValue)
+ if AnteMultiplier > 0 then
+ plusChips = math.floor(plusChips + ((betAmount / 2) * AnteMultiplier))
+ TriggerClientEvent('QBCore:Notify', targetSrc, _('dealer_not_qual_ante', plusChips, AnteMultiplier), 'error')
+ else
+ TriggerClientEvent('QBCore:Notify', targetSrc, _('dealer_not_qual', plusChips), 'error')
+ end
+ end
+
+ giveChips(targetSrc, plusChips)
+ TriggerClientEvent('aquiverPoker:playerDraw', targetSrc, tableId)
+ end
+end
+
+function playerLost(targetSrc, tableId, handValue)
+ local betAmount = getPlayerBetAmount(targetSrc, tableId)
+ if betAmount > 0 then
+ local Player = QBCore.Functions.GetPlayer(targetSrc)
+ if Player then
+ TriggerClientEvent('QBCore:Notify', targetSrc, _U('lose'), 'error')
+ end
+ TriggerClientEvent('aquiverPoker:playerLost', targetSrc, tableId)
+ end
+end
+
+function updatePlayerChips(targetSrc)
+ TriggerClientEvent('aquiverPoker:updatePlayerChips', targetSrc, getPlayerChips(targetSrc))
+end
+
+function getPlayerPairPlusBetAmount(targetSrc, tableId)
+ if ServerPokers[tableId] ~= nil then
+ if ServerPokers[tableId].PairPlusBets ~= nil and ServerPokers[tableId].PairPlusBets[targetSrc] ~= nil then
+ return ServerPokers[tableId].PairPlusBets[targetSrc]
+ end
+ end
+
+ return 0
+end
+
+function getPlayerBetAmount(targetSrc, tableId)
+ if ServerPokers[tableId] ~= nil then
+ if ServerPokers[tableId].PlayerBets ~= nil and ServerPokers[tableId].PlayerBets[targetSrc] ~= nil then
+ return ServerPokers[tableId].PlayerBets[targetSrc]
+ end
+ end
+
+ return 0
+end
+
+function playerStillExist(source)
+ if GetPlayerName(source) == nil then
+ return false
+ else
+ return true
+ end
+end
+
+function getTablePlayersCount(tableId)
+ local playersCount = 0
+ if ServerPokers[tableId] ~= nil then
+ for targetSrc, _ in pairs(ServerPokers[tableId].Cards) do
+ if playerStillExist(targetSrc) then
+ playersCount = playersCount + 1
+ end
+ end
+ end
+
+ return playersCount
+end
+
+QBCore.Functions.CreateCallback(
+ 'aquiverPoker:sitDown',
+ function(source, cb, tableId, chairId)
+ if ServerPokers[tableId] == nil then
+ ServerPokers[tableId] = {
+ ChairsUsed = {}, -- chairs used, for disable sitting
+ PlayerBets = {}, -- player bets ofc.
+ Active = false,
+ Cards = {}, -- player / dealer cards, etc.
+ UsedCards = {}, -- which card was used, so we can not pick the same
+ PlayersFolded = {}, -- following who folded their cards
+ PairPlusBets = {},
+ Stage = 0, -- following the stages
+ TimeLeft = nil
+ }
+ end
+
+ if ServerPokers[tableId].ChairsUsed[chairId] == nil then
+ ServerPokers[tableId].ChairsUsed[chairId] = source
+ Config.DebugMsg('player sit down')
+ updatePlayerChips(source)
+ cb(true)
+ else
+ cb(false)
+ end
+ end
+)
+
+AddEventHandler(
+ 'playerDropped',
+ function(reason)
+ local source = source
+
+ for k, v in pairs(ServerPokers) do
+ if v.ChairsUsed ~= nil then
+ for chairId, chairOwner in pairs(v.ChairsUsed) do
+ if chairOwner == source then
+ ServerPokers[k].ChairsUsed[chairId] = nil
+ end
+ end
+ end
+ end
+ end
+)
diff --git a/resources/[qb]/[qb_casino]/casino-roulette/client/cl_main.lua b/resources/[qb]/[qb_casino]/casino-roulette/client/cl_main.lua
new file mode 100644
index 0000000..66ff0ff
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-roulette/client/cl_main.lua
@@ -0,0 +1,1362 @@
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+SITTING_SCENE = nil
+CURRENT_CHAIR_DATA = nil
+SELECTED_CHAIR_ID = nil
+selectedRulett = nil
+Rulettek = {}
+closetoRulett = false
+currentBetAmount = 0
+idleTimer = 0
+aimingAtBet = -1
+lastAimedBet = -1
+
+---------------------------------------------------------
+-- local rouletteTables = {
+-- 'vw_prop_casino_roulette_01',
+-- 'vw_prop_casino_roulette_01b'
+
+-- }
+
+-- Citizen.CreateThread(function()
+-- while true do
+-- for i=1, #rouletteTables do
+-- local coords = GetEntityCoords(PlayerPedId(), false)
+-- local gate = GetClosestObjectOfType(coords.x, coords.y, coords.z, 250.0, GetHashKey(rouletteTables[i]), 0, 0, 0)
+-- if gate ~= 0 then
+-- SetEntityAsMissionEntity(gate, 1, 1)
+-- DeleteObject(gate)
+-- SetEntityAsNoLongerNeeded(gate)
+-- end
+-- end
+-- Citizen.Wait(2500)
+-- end
+-- end)
+
+
+-- CreateThread(function()
+-- local removeOldRouletteTables = CircleZone:Create(vector3(993.005, 55.232, 69.435), 12.0, {
+-- name="OldRouletteTables",
+-- heading=160,
+-- debugPoly=true,
+-- useZ=true,
+-- })
+-- removeOldRouletteTables:onPlayerInOut(function(isPointInside)
+-- if isPointInside then
+
+-- -- local table = `vw_prop_casino_roulette_01`
+-- local table = GetHashKey('vw_prop_casino_roulette_01b')
+-- RequestModel(table)
+-- SetEntityAsMissionEntity(table, 1, 1)
+-- DeleteObject(table)
+-- SetEntityAsNoLongerNeeded(table)
+-- QBCore.Functions.Notify('Remove: '..table,'success')
+-- else
+-- end
+-- end)
+-- end)
+---------------------------------------------------------
+
+createRulettAsztal = function(index, data)
+ local self = {}
+
+ self.index = index
+ self.data = data
+
+ Config.DebugMsg(string.format('Rulett table creating.. %s', self.index))
+
+ RequestModel(GetHashKey('vw_prop_casino_roulette_01'))
+ while not HasModelLoaded(GetHashKey('vw_prop_casino_roulette_01')) do
+ Wait(1)
+ end
+
+ self.tableObject = CreateObject(GetHashKey('vw_prop_casino_roulette_01'), data.position, false)
+ SetEntityHeading(self.tableObject, data.rot)
+
+ RequestModel(GetHashKey('S_F_Y_Casino_01'))
+ while not HasModelLoaded(GetHashKey('S_F_Y_Casino_01')) do
+ Wait(1)
+ end
+
+ local pedOffset = GetObjectOffsetFromCoords(data.position.x, data.position.y, data.position.z, data.rot, 0.0, 0.7, 1.0)
+ self.ped = CreatePed(2, GetHashKey('S_F_Y_Casino_01'), pedOffset, data.rot + 180.0, false, true)
+
+ SetEntityCanBeDamaged(self.ped, 0)
+ SetPedAsEnemy(self.ped, 0)
+ SetBlockingOfNonTemporaryEvents(self.ped, 1)
+ SetPedResetFlag(self.ped, 249, 1)
+ SetPedConfigFlag(self.ped, 185, true)
+ SetPedConfigFlag(self.ped, 108, true)
+ SetPedCanEvasiveDive(self.ped, 0)
+ SetPedCanRagdollFromPlayerImpact(self.ped, 0)
+ SetPedConfigFlag(self.ped, 208, true)
+
+ -- 1.0.1
+ SetPedVoiceGroup(self.ped, 'S_M_Y_Casino_01_WHITE_01')
+ addRandomClothes(self.ped)
+
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'idle', 3.0, 3.0, -1, 2, 0, true, true, true)
+
+ self.numbersData = {}
+ self.betData = {}
+ self.hoverObjects = {}
+ self.betObjects = {}
+ self.ballObject = nil
+
+ self.rulettCam = nil
+ self.cameraMode = 1
+
+ self.enableCamera = function(state)
+ if state then
+ self.speakPed('MINIGAME_DEALER_GREET')
+ TriggerEvent('ShowPlayerHud', false)
+ -- SendNUIMessage(
+ -- {
+ -- action = 'showRulettNui',
+ -- state = true
+ -- }
+ -- )
+ -- SendNUIMessage(
+ -- {
+ -- action = 'setBetAmount',
+ -- amount = currentBetAmount
+ -- }
+ -- )
+ casinoNuiUpdateGame(self.index, self.ido, self.statusz)
+
+ Config.DebugMsg('creating camera..')
+ local rot = vector3(270.0, -90.0, self.data.rot + 270.0)
+ self.rulettCam =
+ CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA', self.data.position.x, self.data.position.y, self.data.position.z + 2.0, rot.x, rot.y, rot.z, 80.0, true, 2)
+ SetCamActive(self.rulettCam, true)
+ RenderScriptCams(true, 900, 900, true, false)
+ Config.DebugMsg('camera setted active.')
+
+ selectedRulett = self.index
+ self.betRenderState(true)
+
+ playRulettIdle()
+
+ CreateThread(function()
+ while selectedRulett ~= nil do
+ Wait(1000)
+ if idleTimer ~= nil then
+ idleTimer = idleTimer - 1
+ if idleTimer < 1 then
+ Config.DebugMsg('start idle')
+ idleTimer = nil
+ playRulettIdle()
+ end
+ end
+ end
+ end)
+
+ CreateThread(function()
+ while selectedRulett ~= nil do
+ Wait(1)
+ if self.betObjects then
+ for i = 1, #self.betObjects, 1 do
+ local bet = self.betObjects[i]
+ if DoesEntityExist(bet.obj) then
+ local coords = GetEntityCoords(bet.obj)
+ if bet.playerSrc == GetPlayerServerId(PlayerId()) then
+ Draw3DText(coords, string.format('~w~%s', bet.betAmount), 0.10, 0)
+ end
+ end
+ end
+ end
+ end
+ end)
+
+ CreateThread(function()
+ while selectedRulett ~= nil do
+ Wait(125)
+
+ if IsDisabledControlPressed(0, 172) then
+ currentBetAmount = currentBetAmount + 10
+ changeBetAmount(currentBetAmount)
+ -- QBCore.Functions.Notify('+'..currentBetAmount.." bet [raised]",'success')
+
+ elseif IsDisabledControlPressed(0, 173) then
+ if currentBetAmount > 0 then
+ currentBetAmount = currentBetAmount - 10
+
+ if currentBetAmount < 0 then
+ currentBetAmount = 0
+ end
+ changeBetAmount(currentBetAmount)
+ -- QBCore.Functions.Notify('-'..currentBetAmount.." bet [lowered]",'primary')
+
+ end
+ end
+ end
+ end)
+
+ CreateThread(function()
+ while selectedRulett ~= nil do
+ Wait(0)
+ DisableAllControlActions(0)
+ if IsDisabledControlJustPressed(0, 202) then
+ self.enableCamera(false)
+ end
+ if IsDisabledControlJustPressed(0, 38) then
+ self.changeKameraMode()
+ end
+
+ if Config.allowCustomBet then
+ if IsDisabledControlJustPressed(0, 22) then --Custom Bet [space]
+ local tmpInput = getGenericTextInput('How many chips you would like to bet?')
+ if tonumber(tmpInput) then
+ tmpInput = tonumber(tmpInput)
+ if tmpInput > 0 then
+ changeBetAmount(tmpInput)
+ QBCore.Functions.Notify('Custom Bet: '..currentBetAmount..' chips','success')
+ end
+ end
+ end
+ else
+
+ end
+ end
+ end)
+
+ Wait(1000)
+ else
+ TriggerServerEvent('casino:rulett:notUsing', selectedRulett)
+ if DoesCamExist(self.rulettCam) then
+ DestroyCam(self.rulettCam, false)
+ end
+ RenderScriptCams(false, 900, 900, true, false)
+ self.betRenderState(false)
+ Config.DebugMsg('camera deleted.')
+ selectedRulett = nil
+ self.speakPed('MINIGAME_DEALER_LEAVE_NEUTRAL_GAME')
+
+ NetworkStopSynchronisedScene(SITTING_SCENE)
+
+ local endingDict = 'anim_casino_b@amb@casino@games@shared@player@'
+ RequestAnimDict(endingDict)
+ while not HasAnimDictLoaded(endingDict) do
+ Wait(1)
+ end
+
+ local whichAnim = nil
+ if SELECTED_CHAIR_ID == 1 then
+ whichAnim = 'sit_exit_left'
+ elseif SELECTED_CHAIR_ID == 2 then
+ whichAnim = 'sit_exit_right'
+ elseif SELECTED_CHAIR_ID == 3 then
+ whichAnim = ({'sit_exit_left', 'sit_exit_right'})[math.random(1, 2)]
+ elseif SELECTED_CHAIR_ID == 4 then
+ whichAnim = 'sit_exit_left'
+ end
+
+ TaskPlayAnim(PlayerPedId(), endingDict, whichAnim, 1.0, 1.0, 2500, 0)
+ SetPlayerControl(PlayerId(), 0, 0)
+ hideUi()
+ Wait(3600)
+ SetPlayerControl(PlayerId(), 1, 0)
+ end
+ end
+
+ self.changeKameraMode = function()
+ if DoesCamExist(self.rulettCam) then
+ if self.cameraMode == 1 then
+ DoScreenFadeOut(200)
+ while not IsScreenFadedOut() do
+ Wait(1)
+ end
+ self.cameraMode = 2
+ local camOffset = GetOffsetFromEntityInWorldCoords(self.tableObject, -1.45, -0.15, 1.45)
+ SetCamCoord(self.rulettCam, camOffset)
+ SetCamRot(self.rulettCam, -25.0, 0.0, self.data.rot + 270.0, 2)
+ SetCamFov(self.rulettCam, 40.0)
+ ShakeCam(self.rulettCam, 'HAND_SHAKE', 0.3)
+ DoScreenFadeIn(200)
+ elseif self.cameraMode == 2 then
+ DoScreenFadeOut(200)
+ while not IsScreenFadedOut() do
+ Wait(1)
+ end
+ self.cameraMode = 3
+ local camOffset = GetOffsetFromEntityInWorldCoords(self.tableObject, 1.45, -0.15, 2.15)
+ SetCamCoord(self.rulettCam, camOffset)
+ SetCamRot(self.rulettCam, -58.0, 0.0, self.data.rot + 90.0, 2)
+ ShakeCam(self.rulettCam, 'HAND_SHAKE', 0.3)
+ SetCamFov(self.rulettCam, 80.0)
+ DoScreenFadeIn(200)
+ elseif self.cameraMode == 3 then
+ DoScreenFadeOut(200)
+ while not IsScreenFadedOut() do
+ Wait(1)
+ end
+ self.cameraMode = 4
+ local camOffset = GetWorldPositionOfEntityBone(self.tableObject, GetEntityBoneIndexByName(self.tableObject, 'Roulette_Wheel'))
+ local rot = vector3(270.0, -90.0, self.data.rot + 270.0)
+ SetCamCoord(self.rulettCam, camOffset + vector3(0.0, 0.0, 0.5))
+ SetCamRot(self.rulettCam, rot, 2)
+ StopCamShaking(self.rulettCam, false)
+ SetCamFov(self.rulettCam, 80.0)
+ DoScreenFadeIn(200)
+ elseif self.cameraMode == 4 then
+ DoScreenFadeOut(200)
+ while not IsScreenFadedOut() do
+ Wait(1)
+ end
+ self.cameraMode = 1
+ local rot = vector3(270.0, -90.0, self.data.rot + 270.0)
+ SetCamCoord(self.rulettCam, self.data.position + vector3(0.0, 0.0, 2.0))
+ SetCamRot(self.rulettCam, rot, 2)
+ SetCamFov(self.rulettCam, 80.0)
+ StopCamShaking(self.rulettCam, false)
+ DoScreenFadeIn(200)
+ end
+ end
+ end
+
+ self.loadTableData = function()
+ Config.DebugMsg('Table data creating, loading..')
+ self.numbersData = {}
+ self.betData = {}
+ local e = 1
+ for i = 0, 11, 1 do
+ for j = 0, 2, 1 do
+ table.insert(
+ self.numbersData,
+ {
+ name = e + 1,
+ hoverPos = GetOffsetFromEntityInWorldCoords(self.tableObject, (0.081 * i) - 0.057, (0.167 * j) - 0.192, 0.9448),
+ hoverObject = 'vw_prop_vw_marker_02a'
+ }
+ )
+ local offset = nil
+ if j == 0 then
+ offset = 0.155
+ elseif j == 1 then
+ offset = 0.171
+ elseif j == 2 then
+ offset = 0.192
+ end
+
+ table.insert(
+ self.betData,
+ {
+ betId = e,
+ name = e + 1,
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, (0.081 * i) - 0.057, (0.167 * j) - 0.192, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.081 * i - 0.057, 0.167 * j - 0.192, 0.9448),
+ hoverNumbers = {e}
+ }
+ )
+
+ e = e + 1
+ end
+ end
+ table.insert(
+ self.numbersData,
+ {
+ name = 'Zero',
+ hoverPos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.137, -0.148, 0.9448),
+ hoverObject = 'vw_prop_vw_marker_01a'
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = 'Zero',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.137, -0.148, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.137, -0.148, 0.9448),
+ hoverNumbers = {#self.numbersData}
+ }
+ )
+ table.insert(
+ self.numbersData,
+ {
+ name = 'Double Zero',
+ hoverPos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.133, 0.107, 0.9448),
+ hoverObject = 'vw_prop_vw_marker_01a'
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = 'Double Zero',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.133, 0.107, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.133, 0.107, 0.9448),
+ hoverNumbers = {#self.numbersData}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = 'RED',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.3, -0.4, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.3, -0.4, 0.9448),
+ hoverNumbers = {1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = 'BLACK',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.5, -0.4, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.5, -0.4, 0.9448),
+ hoverNumbers = {0, 2, 4, 6, 8, 9, 11, 13, 15, 18, 20, 22, 24, 26, 27, 29, 31, 33, 35}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = 'EVEN',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.15, -0.4, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.15, -0.4, 0.9448),
+ hoverNumbers = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = 'ODD',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.65, -0.4, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.65, -0.4, 0.9448),
+ hoverNumbers = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '1to18',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.02, -0.4, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, -0.02, -0.4, 0.9448),
+ hoverNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '19to36',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.78, -0.4, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.78, -0.4, 0.9448),
+ hoverNumbers = {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '1st 12',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.05, -0.3, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.05, -0.3, 0.9448),
+ hoverNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '2nd 12',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.4, -0.3, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.4, -0.3, 0.9448),
+ hoverNumbers = {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '3rd 12',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.75, -0.3, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.75, -0.3, 0.9448),
+ hoverNumbers = {25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '2to1',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.91, -0.15, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.91, -0.15, 0.9448),
+ hoverNumbers = {1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '2to1',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.91, 0.0, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.91, 0.0, 0.9448),
+ hoverNumbers = {2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35}
+ }
+ )
+ table.insert(
+ self.betData,
+ {
+ betId = #self.betData,
+ name = '2to1',
+ pos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.91, 0.15, 0.9448),
+ objectPos = GetOffsetFromEntityInWorldCoords(self.tableObject, 0.91, 0.15, 0.9448),
+ hoverNumbers = {3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36}
+ }
+ )
+
+ Config.DebugMsg('Table data successfully created..')
+ end
+
+ self.speakPed = function(speakName)
+ PlayPedAmbientSpeechNative(self.ped, speakName, 'SPEECH_PARAMS_FORCE_NORMAL_CLEAR', 1)
+ end
+
+ self.createBetObjects = function(bets)
+ for i = 1, #self.betObjects, 1 do
+ if DoesEntityExist(self.betObjects[i].obj) then
+ DeleteObject(self.betObjects[i].obj)
+ end
+ end
+
+ self.betObjects = {}
+
+ local existBetId = {}
+
+ for i = 1, #bets, 1 do
+ local t = self.betData[bets[i].betId]
+
+ if existBetId[bets[i].betId] == nil then
+ existBetId[bets[i].betId] = 0
+ else
+ existBetId[bets[i].betId] = existBetId[bets[i].betId] + 1
+ end
+
+ if t ~= nil then
+ local betModelObject = getBetObjectType(bets[i].betAmount)
+
+ if betModelObject ~= nil then
+ RequestModel(betModelObject)
+ while not HasModelLoaded(betModelObject) do
+ Wait(0)
+ end
+
+ local obj = CreateObject(betModelObject, t.objectPos.x, t.objectPos.y, t.objectPos.z + (existBetId[bets[i].betId] * 0.0081), false)
+ SetEntityHeading(obj, self.data.rot)
+ table.insert(
+ self.betObjects,
+ {
+ obj = obj,
+ betAmount = bets[i].betAmount,
+ playerSrc = bets[i].playerSrc
+ }
+ )
+ end
+ end
+ end
+ end
+
+ self.hoverNumbers = function(hoveredNumbers)
+ for i = 1, #self.hoverObjects, 1 do
+ if DoesEntityExist(self.hoverObjects[i]) then
+ DeleteObject(self.hoverObjects[i])
+ end
+ end
+
+ self.hoverObjects = {}
+
+ for i = 1, #hoveredNumbers, 1 do
+ local t = self.numbersData[hoveredNumbers[i]]
+ if t ~= nil then
+ RequestModel(GetHashKey(t.hoverObject))
+ while not HasModelLoaded(GetHashKey(t.hoverObject)) do
+ Wait(1)
+ end
+
+ local obj = CreateObject(GetHashKey(t.hoverObject), t.hoverPos, false)
+ SetEntityHeading(obj, self.data.rot)
+
+ table.insert(self.hoverObjects, obj)
+ end
+ end
+ end
+
+ self.betRenderState = function(state)
+ enabledBetRender = state
+
+ Config.DebugMsg('Bet rendering turned: %s', enabledBetRender)
+
+ if state then
+ CreateThread(
+ function()
+ while enabledBetRender do
+ Wait(8)
+
+ if aimingAtBet ~= -1 and lastAimedBet ~= aimingAtBet then
+ Config.DebugMsg('aimed at different bet.')
+ lastAimedBet = aimingAtBet
+ local bettingData = self.betData[aimingAtBet]
+ if bettingData ~= nil then
+ self.hoverNumbers(bettingData.hoverNumbers)
+ else
+ self.hoverNumbers({})
+ end
+ end
+
+ if aimingAtBet == -1 and lastAimedBet ~= -1 then
+ self.hoverNumbers({})
+ end
+ end
+ end
+ )
+
+ CreateThread(
+ function()
+ while enabledBetRender do
+ Wait(0)
+
+ ShowCursorThisFrame()
+
+ local e = Rulettek[selectedRulett]
+ if e ~= nil then
+ local cx, cy = GetNuiCursorPosition()
+ local rx, ry = GetActiveScreenResolution()
+
+ local n = 30 -- this is for the cursor point, how much to tolerate in range, increasing it you will find it easier to click on the bets.
+
+ local foundBet = false
+
+ for i = 1, #self.betData, 1 do
+ local bettingData = self.betData[i]
+ local onScreen, screenX, screenY = World3dToScreen2d(bettingData.pos.x, bettingData.pos.y, bettingData.pos.z)
+ local l = math.sqrt(math.pow(screenX * rx - cx, 2) + math.pow(screenY * ry - cy, 2))
+ if l < n then
+ aimingAtBet = i
+ foundBet = true
+
+ if IsDisabledControlJustPressed(0, 24) then
+ if currentBetAmount > 0 then
+ if Config.RulettTables[selectedRulett] ~= nil then
+ if currentBetAmount >= Config.RulettTables[selectedRulett].minBet and currentBetAmount <= Config.RulettTables[selectedRulett].maxBet then
+ PlaySoundFrontend(-1, 'DLC_VW_BET_DOWN', 'dlc_vw_table_games_frontend_sounds', true)
+ TriggerServerEvent('casino:taskBetRulett', selectedRulett, aimingAtBet, currentBetAmount)
+ else
+ QBCore.Functions.Notify('Your bet it too low or too high for this table.','error')
+
+ end
+ end
+ else
+ QBCore.Functions.Notify('Bet needs to be raised','error')
+ end
+ end
+ end
+ end
+
+ if not foundBet then
+ aimingAtBet = -1
+ end
+ end
+ end
+ end
+ )
+ end
+ end
+
+ self.spinRulett = function(tickRate)
+ Config.DebugMsg(self.index)
+ if DoesEntityExist(self.tableObject) and DoesEntityExist(self.ped) then
+ Config.DebugMsg('spinRulett event 1')
+
+ self.speakPed('MINIGAME_DEALER_CLOSED_BETS')
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'no_more_bets', 3.0, 3.0, -1, 0, 0, true, true, true)
+
+ Wait(1500)
+
+ if DoesEntityExist(self.ballObject) then
+ DeleteObject(self.ballObject)
+ end
+
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'spin_wheel', 3.0, 3.0, -1, 0, 0, true, true, true)
+
+ RequestModel(GetHashKey('vw_prop_roulette_ball'))
+ while not HasModelLoaded(GetHashKey('vw_prop_roulette_ball')) do
+ Wait(1)
+ end
+
+ local ballOffset = GetWorldPositionOfEntityBone(self.tableObject, GetEntityBoneIndexByName(self.tableObject, 'Roulette_Wheel'))
+
+ Config.DebugMsg('spinRulett event 2')
+
+ local LIB = 'anim_casino_b@amb@casino@games@roulette@table'
+ RequestAnimDict(LIB)
+ while not HasAnimDictLoaded(LIB) do
+ Wait(1)
+ end
+
+ Wait(3000)
+
+ self.ballObject = CreateObject(GetHashKey('vw_prop_roulette_ball'), ballOffset, false)
+ SetEntityHeading(self.ballObject, self.data.rot)
+ SetEntityCoordsNoOffset(self.ballObject, ballOffset, false, false, false)
+ local h = GetEntityRotation(self.ballObject)
+ SetEntityRotation(self.ballObject, h.x, h.y, h.z + 90.0, 2, false)
+
+ if DoesEntityExist(self.tableObject) and DoesEntityExist(self.ped) then
+ Config.DebugMsg('spinRulett event 3')
+
+ PlayEntityAnim(self.ballObject, 'intro_ball', LIB, 1000.0, false, true, true, 0, 136704)
+ PlayEntityAnim(self.ballObject, 'loop_ball', LIB, 1000.0, false, true, false, 0, 136704)
+
+ PlayEntityAnim(self.tableObject, 'intro_wheel', LIB, 1000.0, false, true, true, 0, 136704)
+ PlayEntityAnim(self.tableObject, 'loop_wheel', LIB, 1000.0, false, true, false, 0, 136704)
+
+ PlayEntityAnim(self.ballObject, string.format('exit_%s_ball', tickRate), LIB, 1000.0, false, true, false, 0, 136704)
+ PlayEntityAnim(self.tableObject, string.format('exit_%s_wheel', tickRate), LIB, 1000.0, false, true, false, 0, 136704)
+
+ Wait(11e3)
+
+ if DoesEntityExist(self.tableObject) and DoesEntityExist(self.ped) then
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'clear_chips_zone1', 3.0, 3.0, -1, 0, 0, true, true, true)
+ Wait(1500)
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'clear_chips_zone2', 3.0, 3.0, -1, 0, 0, true, true, true)
+ Wait(1500)
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'clear_chips_zone3', 3.0, 3.0, -1, 0, 0, true, true, true)
+
+ Wait(2000)
+ if DoesEntityExist(self.tableObject) and DoesEntityExist(self.ped) then
+ TaskPlayAnim(self.ped, 'anim_casino_b@amb@casino@games@roulette@dealer_female', 'idle', 3.0, 3.0, -1, 0, 0, true, true, true)
+ end
+
+ Config.DebugMsg('spinRulett event ending')
+
+ if DoesEntityExist(self.ballObject) then
+ DeleteObject(self.ballObject)
+ end
+ end
+ end
+ end
+ end
+
+ self.loadTableData()
+ Config.DebugMsg(string.format('Rulett table created %s id', self.index))
+ Rulettek[self.index] = self
+end
+
+function Draw3DText(coords, text, size, font)
+ coords = vector3(coords.x, coords.y, coords.z)
+
+ local camCoords = GetGameplayCamCoords()
+ local distance = #(coords - camCoords)
+
+ if not size then
+ size = 1
+ end
+ if not font then
+ font = 0
+ end
+
+ local scale = (size / distance) * 2
+ local fov = (1 / GetGameplayCamFov()) * 100
+ scale = scale * fov
+
+ SetTextScale(0.0 * scale, 0.55 * scale)
+ SetTextFont(font)
+ SetTextColour(255, 255, 255, 255)
+ SetTextDropshadow(0, 0, 0, 0, 255)
+ SetTextDropShadow()
+ SetTextOutline()
+ SetTextCentre(true)
+
+ SetDrawOrigin(coords, 0)
+ BeginTextCommandDisplayText('STRING')
+ AddTextComponentSubstringPlayerName(text)
+ EndTextCommandDisplayText(0.0, 0.0)
+ ClearDrawOrigin()
+end
+
+function hideUi()
+ exports["qb-core"]:HideText()
+ exports['casinoUi']:HideCasinoUi('hide')
+end
+
+function changeBetAmount(amount)
+ currentBetAmount = amount
+ PlaySoundFrontend(-1, 'DLC_VW_BET_HIGHLIGHT', 'dlc_vw_table_games_frontend_sounds', true)
+end
+
+
+function getGenericTextInput(type)
+ if type == nil then
+ type = ''
+ end
+ AddTextEntry('FMMC_MPM_NA', tostring(type))
+ DisplayOnscreenKeyboard(1, 'FMMC_MPM_NA', tostring(type), '', '', '', '', 30)
+ while (UpdateOnscreenKeyboard() == 0) do
+ DisableAllControlActions(0)
+ Wait(0)
+ end
+ if (GetOnscreenKeyboardResult()) then
+ local result = GetOnscreenKeyboardResult()
+ if result then
+ return result
+ end
+ end
+ return false
+end
+
+CreateThread(
+ function()
+ while true do
+ local playerCoords = GetEntityCoords(GetPlayerPed(-1))
+ closetoRulett = false
+ for k, v in pairs(Config.RulettTables) do
+ if #(playerCoords - Config.RulettTables[k].position) < 100.0 then
+ closetoRulett = true
+ end
+ end
+ Wait(1000)
+ end
+ end
+)
+
+CreateThread(
+ function()
+ while not closetoRulett do
+ Wait(0)
+ end
+
+ for rulettIndex, data in pairs(Config.RulettTables) do
+ createRulettAsztal(rulettIndex, data)
+
+ RequestAnimDict('anim_casino_b@amb@casino@games@roulette@table')
+ RequestAnimDict('anim_casino_b@amb@casino@games@roulette@dealer_female')
+ RequestAnimDict('anim_casino_b@amb@casino@games@shared@player@')
+ RequestAnimDict('anim_casino_b@amb@casino@games@roulette@player')
+ end
+ Config.DebugMsg('Casino rulett loaded.')
+ end
+)
+
+-- CreateThread(function()
+-- while true do
+-- local sleep = 5
+-- local playerpos = GetEntityCoords(PlayerPedId())
+
+-- if closetoRulett and selectedRulett == nil then
+-- for k, v in pairs(Rulettek) do
+-- if DoesEntityExist(v.tableObject) then
+-- local objcoords = GetEntityCoords(v.tableObject)
+-- local dist = Vdist(playerpos, objcoords)
+-- if dist < 2.4 then
+-- if dist < 2.3 then
+-- -- exports['textUi']:DrawTextUi('show',"Diamond Casino RoulettePress [E] to sit down")
+-- exports["qb-core"]:DrawText("The Diamond Casino & ResortRoulettePress E to sit")
+-- local closestChairData = getClosestChairData(v.tableObject)
+
+-- if closestChairData == nil then
+-- break
+-- end
+-- if IsControlJustPressed(0, 38) then
+-- -- QBCore.Functions.TriggerCallback('doj:server:HasCasinoMembership', function(HasItem)
+-- -- if HasItem then
+-- TriggerServerEvent('server_remote:rulett:taskSitDown', k, closestChairData)
+-- -- else
+-- -- QBCore.Functions.Notify('You are not a member of the casino', 'error', 3500)
+-- -- end
+-- -- end)
+-- end
+-- break
+-- end
+-- hideUi()
+-- end
+-- end
+-- end
+-- end
+-- Wait(sleep)
+-- end
+-- end)
+
+
+
+
+
+Citizen.CreateThread(function()
+ local alreadyEnteredZone = false
+ local text = nil
+ while true do
+ if closetoRulett and selectedRulett == nil then
+ wait = 5
+ local inZone = false
+
+ local playerpos = GetEntityCoords(PlayerPedId())
+ for k, v in pairs(Rulettek) do
+ if DoesEntityExist(v.tableObject) then
+ local objcoords = GetEntityCoords(v.tableObject)
+ local dist = Vdist(playerpos, objcoords)
+ if dist <= 2.0 then
+ wait = 5
+ inZone = true
+ text = "The Diamond Casino & ResortRoulettePress E to sit"
+ local closestChairData = getClosestChairData(v.tableObject)
+ if closestChairData == nil then
+ break
+ end
+ if IsControlJustPressed(0, 38) then
+ TriggerServerEvent('server_remote:rulett:taskSitDown', k, closestChairData)
+ end
+ -- break
+ -- else
+ -- wait = 2000
+ end
+ if inZone and not alreadyEnteredZone then
+ alreadyEnteredZone = true
+ exports["qb-core"]:DrawText(text)
+ end
+ if not inZone and alreadyEnteredZone then
+ alreadyEnteredZone = false
+ exports["qb-core"]:HideText()
+ end
+ end
+ end
+ end
+ Wait(wait)
+ end
+end)
+
+
+
+
+RegisterNetEvent('client_callback:rulett:taskSitDown',function(rulettIndex, chairData)
+ -- exports['progressBars']:drawBar(4000, 'Sitting...')
+ -- QBCore.Functions.Notify("Sitting...", "primary", 3200)
+ exports["qb-core"]:HideText()
+ SELECTED_CHAIR_ID = chairData.chairId
+ CURRENT_CHAIR_DATA = chairData
+ SITTING_SCENE = NetworkCreateSynchronisedScene(chairData.position, chairData.rotation, 2, 1, 0, 1065353216, 0, 1065353216)
+ RequestAnimDict('anim_casino_b@amb@casino@games@shared@player@')
+ while not HasAnimDictLoaded('anim_casino_b@amb@casino@games@shared@player@') do
+ Wait(1)
+ end
+ local randomSit = ({'sit_enter_left', 'sit_enter_right'})[math.random(1, 2)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), SITTING_SCENE, 'anim_casino_b@amb@casino@games@shared@player@', randomSit, 2.0, -2.0, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(SITTING_SCENE)
+ SetPlayerControl(PlayerId(), 0, 0)
+ startRulett(rulettIndex, chairData.chairId)
+ Wait(4000)
+ SetPlayerControl(PlayerId(), 1, 0)
+end)
+
+function startRulett(index, chairId)
+ if Rulettek[index] then
+ TriggerServerEvent('casino:taskStartRoulette', index, chairId)
+ end
+end
+
+RegisterNetEvent('client:casino:openRulett')
+AddEventHandler('client:casino:openRulett',function(rulettIndex)
+ if Rulettek[rulettIndex] ~= nil then
+ Wait(4000)
+ Rulettek[rulettIndex].enableCamera(true)
+ end
+end)
+
+RegisterNetEvent('casino:rulett:startSpin')
+AddEventHandler(
+ 'casino:rulett:startSpin',
+ function(rulettIndex, tickRate)
+
+ if Rulettek[rulettIndex] ~= nil then
+
+ Config.DebugMsg(string.format('rulett table index: %s, tickrate: %s', rulettIndex, tickRate))
+ Rulettek[rulettIndex].spinRulett(tickRate)
+
+ if selectedRulett == rulettIndex then
+ Config.DebugMsg('impartial anim play')
+ playImpartial()
+ end
+ end
+ end
+)
+
+RegisterNetEvent('client:rulett:updateStatusz')
+AddEventHandler(
+ 'client:rulett:updateStatusz',
+ function(rulettIndex, ido, statusz)
+
+ if Rulettek[rulettIndex] ~= nil then
+ Rulettek[rulettIndex].ido = ido
+ Rulettek[rulettIndex].statusz = statusz
+ casinoNuiUpdateGame(rulettIndex, ido, statusz)
+ end
+ end
+)
+
+RegisterNetEvent('client:rulett:updateTableBets')
+AddEventHandler(
+ 'client:rulett:updateTableBets',
+ function(rulettIndex, bets)
+ if Rulettek[rulettIndex] ~= nil then
+ Rulettek[rulettIndex].createBetObjects(bets)
+ end
+ end
+)
+
+function casinoNuiUpdateGame(rulettIndex, ido, statusz)
+ QBCore.Functions.TriggerCallback('roulette:server:ChipsAmount', function(result)
+ retval = result
+ if selectedRulett == rulettIndex then
+ if not statusz then
+ exports['casinoUi']:DrawCasinoUi('show', "Diamond Casino RouletteTime Left: "..ido.."Current Bet: "..currentBetAmount.."Availble chips: "..math.floor(retval))
+ if Config.allowCustomBet then
+ exports["qb-core"]:DrawText("Place Bet: LEFT CLICKAdjust Bet: ↑/↓Exit: ←Custom Amount: SPACEBAR")
+ else
+ exports["qb-core"]:DrawText("Place Bet: LEFT CLICKAdjust Bet: ↑/↓Exit: ←")
+ end
+ else
+ exports["qb-core"]:DrawText("The game is starting..")
+ hideUi()
+ end
+ end
+ end)
+end
+
+
+function getClosestChairData(tableObject)
+ local localPlayer = PlayerPedId()
+ local playerpos = GetEntityCoords(localPlayer)
+ if DoesEntityExist(tableObject) then
+ local chairs = {'Chair_Base_01', 'Chair_Base_02', 'Chair_Base_03', 'Chair_Base_04'}
+ for i = 1, #chairs, 1 do
+ local objcoords = GetWorldPositionOfEntityBone(tableObject, GetEntityBoneIndexByName(tableObject, chairs[i]))
+ local dist = Vdist(playerpos, objcoords)
+ if dist < 1.7 then
+ return {
+ position = objcoords,
+ rotation = GetWorldRotationOfEntityBone(tableObject, GetEntityBoneIndexByName(tableObject, chairs[i])),
+ chairId = Config.ChairIds[chairs[i]]
+ }
+ end
+ end
+ end
+end
+
+function getBetObjectType(betAmount)
+ if betAmount < 10 then
+ return GetHashKey('vw_prop_vw_coin_01a')
+ elseif betAmount >= 10 and betAmount < 50 then
+ return GetHashKey('vw_prop_chip_10dollar_x1')
+ elseif betAmount >= 50 and betAmount < 100 then
+ return GetHashKey('vw_prop_chip_50dollar_x1')
+ elseif betAmount >= 100 and betAmount < 500 then
+ return GetHashKey('vw_prop_chip_100dollar_x1')
+ elseif betAmount >= 500 and betAmount < 1000 then
+ return GetHashKey('vw_prop_chip_500dollar_x1')
+ elseif betAmount >= 1000 and betAmount < 5000 then
+ return GetHashKey('vw_prop_chip_1kdollar_x1')
+ elseif betAmount >= 5000 then
+ return GetHashKey('vw_prop_plaq_10kdollar_x1')
+ else -- this should never happen, but yeah.
+ return GetHashKey('vw_prop_plaq_10kdollar_x1')
+ end
+
+ -- these are deprecated, it looks cool, but it hides some data, you can put it in you like the big chip piles.
+
+ -- elseif bets[i].betAmount >= 10000 and bets[i].betAmount < 25000 then
+ -- return GetHashKey('vw_prop_vw_chips_pile_01a')
+ -- elseif bets[i].betAmount >= 25000 and bets[i].betAmount < 50000 then
+ -- return GetHashKey('vw_prop_vw_chips_pile_02a')
+ -- elseif bets[i].betAmount >= 50000 then
+ -- return GetHashKey('vw_prop_vw_chips_pile_03a')
+ -- end
+end
+
+RegisterNetEvent('client:rulett:playBetAnim')
+AddEventHandler(
+ 'client:rulett:playBetAnim',
+ function(chairId)
+ local sex = 0
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then
+ sex = 1
+ end
+
+ local rot = CURRENT_CHAIR_DATA.rotation
+
+ if chairId == 4 then
+ rot = rot + vector3(0.0, 0.0, 90.0)
+ elseif chairId == 3 then
+ rot = rot + vector3(0.0, 0.0, -180.0)
+ elseif chairId == 2 then
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ elseif chairId == 1 then
+ chairId = 1
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ end
+
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_male@seat_%s@regular@0%sa@play@v01', chairId, chairId)
+ if sex == 1 then
+ L = string.format('anim_casino_b@amb@casino@games@roulette@ped_female@seat_%s@regular@0%sa@play@v01', chairId, chairId)
+ end
+
+ RequestAnimDict(L)
+ while not HasAnimDictLoaded(L) do
+ Wait(1)
+ end
+
+ if CURRENT_CHAIR_DATA ~= nil then
+ local currentScene = NetworkCreateSynchronisedScene(CURRENT_CHAIR_DATA.position, rot, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(
+ PlayerPedId(),
+ currentScene,
+ L,
+ ({'place_bet_zone1', 'place_bet_zone2', 'place_bet_zone3'})[math.random(1, 3)],
+ 4.0,
+ -2.0,
+ 13,
+ 16,
+ 1148846080,
+ 0
+ )
+ NetworkStartSynchronisedScene(currentScene)
+
+ idleTimer = 8
+ end
+ end
+)
+
+RegisterNetEvent('client:rulett:playWinAnim')
+AddEventHandler(
+ 'client:rulett:playWinAnim',
+ function(chairId)
+ local rot = CURRENT_CHAIR_DATA.rotation
+
+ if chairId == 4 then
+ rot = rot + vector3(0.0, 0.0, 90.0)
+ elseif chairId == 3 then
+ rot = rot + vector3(0.0, 0.0, -180.0)
+ elseif chairId == 2 then
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ elseif chairId == 1 then
+ chairId = 1
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ end
+
+ local sex = 0
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_male@seat_%s@regular@0%sa@reacts@v01', chairId, chairId)
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then
+ sex = 1
+ end
+
+ if sex == 1 then
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_female@seat_%s@regular@0%sa@reacts@v01', chairId, chairId)
+ end
+
+ RequestAnimDict(L)
+ while not HasAnimDictLoaded(L) do
+ Wait(1)
+ end
+
+ if CURRENT_CHAIR_DATA ~= nil then
+ local currentScene = NetworkCreateSynchronisedScene(CURRENT_CHAIR_DATA.position, rot, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, L, 'reaction_great', 4.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+
+ idleTimer = 8
+ end
+ end
+)
+
+RegisterNetEvent('client:rulett:playLossAnim',function(chairId)
+ local rot = CURRENT_CHAIR_DATA.rotation
+
+ if chairId == 4 then
+ rot = rot + vector3(0.0, 0.0, 90.0)
+ elseif chairId == 3 then
+ rot = rot + vector3(0.0, 0.0, -180.0)
+ elseif chairId == 2 then
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ elseif chairId == 1 then
+ chairId = 1
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ end
+
+ local sex = 0
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_male@seat_%s@regular@0%sa@reacts@v01', chairId, chairId)
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then
+ sex = 1
+ end
+
+ if sex == 1 then
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_female@seat_%s@regular@0%sa@reacts@v01', chairId, chairId)
+ end
+
+ RequestAnimDict(L)
+ while not HasAnimDictLoaded(L) do
+ Wait(1)
+ end
+
+ if CURRENT_CHAIR_DATA ~= nil then
+ local currentScene = NetworkCreateSynchronisedScene(CURRENT_CHAIR_DATA.position, rot, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(
+ PlayerPedId(),
+ currentScene,
+ L,
+ ({'reaction_bad_var01', 'reaction_bad_var02', 'reaction_terrible'})[math.random(1, 3)],
+ 4.0,
+ -2.0,
+ 13,
+ 16,
+ 1148846080,
+ 0
+ )
+ NetworkStartSynchronisedScene(currentScene)
+
+ idleTimer = 8
+ end
+end)
+
+function playImpartial()
+ local rot = CURRENT_CHAIR_DATA.rotation
+
+ if SELECTED_CHAIR_ID == 4 then
+ rot = rot + vector3(0.0, 0.0, 90.0)
+ elseif SELECTED_CHAIR_ID == 3 then
+ rot = rot + vector3(0.0, 0.0, -180.0)
+ elseif SELECTED_CHAIR_ID == 2 then
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ elseif SELECTED_CHAIR_ID == 1 then
+ SELECTED_CHAIR_ID = 1
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ end
+
+ local sex = 0
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_male@seat_%s@regular@0%sa@reacts@v01', SELECTED_CHAIR_ID, SELECTED_CHAIR_ID)
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then
+ sex = 1
+ end
+
+ if sex == 1 then
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_female@seat_%s@regular@0%sa@reacts@v01', SELECTED_CHAIR_ID, SELECTED_CHAIR_ID)
+ end
+
+ RequestAnimDict(L)
+ while not HasAnimDictLoaded(L) do
+ Wait(1)
+ end
+
+ if CURRENT_CHAIR_DATA ~= nil then
+ local currentScene = NetworkCreateSynchronisedScene(CURRENT_CHAIR_DATA.position, rot, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(
+ PlayerPedId(),
+ currentScene,
+ L,
+ ({'reaction_impartial_var01', 'reaction_impartial_var02', 'reaction_impartial_var03'})[math.random(1, 3)],
+ 4.0,
+ -2.0,
+ 13,
+ 16,
+ 1148846080,
+ 0
+ )
+ NetworkStartSynchronisedScene(currentScene)
+
+ idleTimer = 8
+ end
+end
+
+function playRulettIdle()
+ local rot = CURRENT_CHAIR_DATA.rotation
+
+ if SELECTED_CHAIR_ID == 4 then
+ rot = rot + vector3(0.0, 0.0, 90.0)
+ elseif SELECTED_CHAIR_ID == 3 then
+ rot = rot + vector3(0.0, 0.0, -180.0)
+ elseif SELECTED_CHAIR_ID == 2 then
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ elseif SELECTED_CHAIR_ID == 1 then
+ SELECTED_CHAIR_ID = 1
+ rot = rot + vector3(0.0, 0.0, -90.0)
+ end
+
+ local sex = 0
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_male@seat_%s@regular@0%sa@idles', SELECTED_CHAIR_ID, SELECTED_CHAIR_ID)
+
+ if GetEntityModel(PlayerPedId()) == GetHashKey('mp_f_freemode_01') then
+ sex = 1
+ end
+
+ if sex == 1 then
+ local L = string.format('anim_casino_b@amb@casino@games@roulette@ped_female@seat_%s@regular@0%sa@idles', SELECTED_CHAIR_ID, SELECTED_CHAIR_ID)
+ end
+
+ RequestAnimDict(L)
+ while not HasAnimDictLoaded(L) do
+ Wait(1)
+ end
+
+ if CURRENT_CHAIR_DATA ~= nil then
+ local currentScene = NetworkCreateSynchronisedScene(CURRENT_CHAIR_DATA.position, rot, 2, 1, 0, 1065353216, 0, 1065353216)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), currentScene, L, ({'idle_a', 'idle_b', 'idle_c', 'idle_d'})[math.random(1, 4)], 1.0, -2.0, 13, 16, 1148846080, 0)
+ NetworkStartSynchronisedScene(currentScene)
+ end
+end
+
+function addRandomClothes(ped)
+ local r = math.random(1, 5)
+
+ if r == 1 then
+ SetPedComponentVariation(ped, 0, 4, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 2, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 1, 0, 0)
+ SetPedComponentVariation(ped, 8, 2, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ SetPedPropIndex(ped, 1, 0, 0, false)
+ elseif r == 2 then
+ SetPedComponentVariation(ped, 0, 3, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 1, 0)
+ SetPedComponentVariation(ped, 3, 1, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ elseif r == 3 then
+ SetPedComponentVariation(ped, 0, 3, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 1, 0, 0)
+ SetPedComponentVariation(ped, 8, 0, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ SetPedPropIndex(ped, 1, 0, 0, false)
+ elseif r == 4 then
+ SetPedComponentVariation(ped, 0, 2, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 1, 0)
+ SetPedComponentVariation(ped, 3, 3, 3, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ end
+end
diff --git a/resources/[qb]/[qb_casino]/casino-roulette/config.lua b/resources/[qb]/[qb_casino]/casino-roulette/config.lua
new file mode 100644
index 0000000..541ec9d
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-roulette/config.lua
@@ -0,0 +1,304 @@
+Config = {}
+Config.TranslationSelected = 'en'
+
+Config.Debug = false -- enable debug messages in sv/cl console
+Config.TestTicker = nil -- need for testing the numbers, you can change the fix roulette tick by /rultick [1-38]
+
+Config.allowCustomBet = false -- allow playes to enter a custom bet
+
+Config.RouletteStart = 40 -- how many seconds to start the rulett after you sit down
+
+
+Config.RulettTables = {
+ -- you can implement tables easily or delete them.
+ [0] = {
+ position = vector3(1001.53, 56.479, 68.433), --Test Loc
+ rot = 102.133,
+ minBet = 10,
+ maxBet = 1000
+ },
+ [1] = {
+ position = vector3(997.595, 55.573, 68.433),
+ rot = 280.612,
+ minBet = 10,
+ maxBet = 1000
+ },
+ -- [3] = {
+ -- position = vector3(984.6, 56.603, 70.238),
+ -- rot = 162.406,
+ -- minBet = 250,
+ -- maxBet = 1000
+ -- },
+ -- [4] = {
+ -- position = vector3(986.43, 48.482, 70.238),
+ -- rot = 42.96,
+ -- minBet = 250,
+ -- maxBet = 1000
+ -- },
+ -- [5] = {
+ -- position = vector3(982.953, 52.36, 70.238),
+ -- rot = 103.648,
+ -- minBet = 250,
+ -- maxBet = 1000
+ -- }
+}
+
+Config.ChairIds = {
+ ['Chair_Base_01'] = 1,
+ ['Chair_Base_02'] = 2,
+ ['Chair_Base_03'] = 3,
+ ['Chair_Base_04'] = 4
+}
+
+Config.rouletteSzamok = {
+ [1] = '00',
+ [2] = '27',
+ [3] = '10',
+ [4] = '25',
+ [5] = '29',
+ [6] = '12',
+ [7] = '8',
+ [8] = '19',
+ [9] = '31',
+ [10] = '18',
+ [11] = '6',
+ [12] = '21',
+ [13] = '33',
+ [14] = '16',
+ [15] = '4',
+ [16] = '23',
+ [17] = '35',
+ [18] = '14',
+ [19] = '2',
+ [20] = '0',
+ [21] = '28',
+ [22] = '9',
+ [23] = '26',
+ [24] = '30',
+ [25] = '11',
+ [26] = '7',
+ [27] = '20',
+ [28] = '32',
+ [29] = '17',
+ [30] = '5',
+ [31] = '22',
+ [32] = '34',
+ [33] = '15',
+ [34] = '3',
+ [35] = '24',
+ [36] = '36',
+ [37] = '13',
+ [38] = '1'
+}
+
+Config.DebugMsg = function(msg)
+ if Config.Debug then
+ print(msg)
+ end
+end
+
+RULETT_NUMBERS = {}
+RULETT_NUMBERS.Pirosak = {
+ ['1'] = true,
+ ['3'] = true,
+ ['5'] = true,
+ ['7'] = true,
+ ['9'] = true,
+ ['12'] = true,
+ ['14'] = true,
+ ['16'] = true,
+ ['18'] = true,
+ ['19'] = true,
+ ['21'] = true,
+ ['23'] = true,
+ ['25'] = true,
+ ['27'] = true,
+ ['30'] = true,
+ ['32'] = true,
+ ['34'] = true,
+ ['36'] = true
+}
+RULETT_NUMBERS.Feketek = {
+ ['2'] = true,
+ ['4'] = true,
+ ['6'] = true,
+ ['8'] = true,
+ ['10'] = true,
+ ['11'] = true,
+ ['13'] = true,
+ ['15'] = true,
+ ['17'] = true,
+ ['20'] = true,
+ ['22'] = true,
+ ['24'] = true,
+ ['26'] = true,
+ ['28'] = true,
+ ['29'] = true,
+ ['31'] = true,
+ ['33'] = true,
+ ['35'] = true
+}
+RULETT_NUMBERS.Parosak = {
+ ['2'] = true,
+ ['4'] = true,
+ ['6'] = true,
+ ['8'] = true,
+ ['10'] = true,
+ ['12'] = true,
+ ['14'] = true,
+ ['16'] = true,
+ ['18'] = true,
+ ['20'] = true,
+ ['22'] = true,
+ ['24'] = true,
+ ['26'] = true,
+ ['28'] = true,
+ ['30'] = true,
+ ['32'] = true,
+ ['34'] = true,
+ ['36'] = true
+}
+RULETT_NUMBERS.Paratlanok = {
+ ['1'] = true,
+ ['3'] = true,
+ ['5'] = true,
+ ['7'] = true,
+ ['9'] = true,
+ ['11'] = true,
+ ['13'] = true,
+ ['15'] = true,
+ ['17'] = true,
+ ['19'] = true,
+ ['21'] = true,
+ ['23'] = true,
+ ['25'] = true,
+ ['27'] = true,
+ ['29'] = true,
+ ['31'] = true,
+ ['33'] = true,
+ ['35'] = true
+}
+RULETT_NUMBERS.to18 = {
+ ['1'] = true,
+ ['2'] = true,
+ ['3'] = true,
+ ['4'] = true,
+ ['5'] = true,
+ ['6'] = true,
+ ['7'] = true,
+ ['8'] = true,
+ ['9'] = true,
+ ['10'] = true,
+ ['11'] = true,
+ ['12'] = true,
+ ['13'] = true,
+ ['14'] = true,
+ ['15'] = true,
+ ['16'] = true,
+ ['17'] = true,
+ ['18'] = true
+}
+RULETT_NUMBERS.to36 = {
+ ['19'] = true,
+ ['20'] = true,
+ ['21'] = true,
+ ['22'] = true,
+ ['23'] = true,
+ ['24'] = true,
+ ['25'] = true,
+ ['26'] = true,
+ ['27'] = true,
+ ['28'] = true,
+ ['29'] = true,
+ ['30'] = true,
+ ['31'] = true,
+ ['32'] = true,
+ ['33'] = true,
+ ['34'] = true,
+ ['35'] = true,
+ ['36'] = true
+}
+RULETT_NUMBERS.st12 = {
+ ['1'] = true,
+ ['2'] = true,
+ ['3'] = true,
+ ['4'] = true,
+ ['5'] = true,
+ ['6'] = true,
+ ['7'] = true,
+ ['8'] = true,
+ ['9'] = true,
+ ['10'] = true,
+ ['11'] = true,
+ ['12'] = true
+}
+RULETT_NUMBERS.sn12 = {
+ ['13'] = true,
+ ['14'] = true,
+ ['15'] = true,
+ ['16'] = true,
+ ['17'] = true,
+ ['18'] = true,
+ ['19'] = true,
+ ['20'] = true,
+ ['21'] = true,
+ ['22'] = true,
+ ['23'] = true,
+ ['24'] = true
+}
+RULETT_NUMBERS.rd12 = {
+ ['25'] = true,
+ ['26'] = true,
+ ['27'] = true,
+ ['28'] = true,
+ ['29'] = true,
+ ['30'] = true,
+ ['31'] = true,
+ ['32'] = true,
+ ['33'] = true,
+ ['34'] = true,
+ ['35'] = true,
+ ['36'] = true
+}
+RULETT_NUMBERS.ket_to_1 = {
+ ['1'] = true,
+ ['4'] = true,
+ ['7'] = true,
+ ['10'] = true,
+ ['13'] = true,
+ ['16'] = true,
+ ['19'] = true,
+ ['22'] = true,
+ ['25'] = true,
+ ['28'] = true,
+ ['31'] = true,
+ ['34'] = true
+}
+RULETT_NUMBERS.ket_to_2 = {
+ ['2'] = true,
+ ['5'] = true,
+ ['8'] = true,
+ ['11'] = true,
+ ['14'] = true,
+ ['17'] = true,
+ ['20'] = true,
+ ['23'] = true,
+ ['26'] = true,
+ ['29'] = true,
+ ['32'] = true,
+ ['35'] = true
+}
+RULETT_NUMBERS.ket_to_3 = {
+ ['3'] = true,
+ ['6'] = true,
+ ['9'] = true,
+ ['12'] = true,
+ ['15'] = true,
+ ['18'] = true,
+ ['21'] = true,
+ ['24'] = true,
+ ['27'] = true,
+ ['30'] = true,
+ ['33'] = true,
+ ['36'] = true
+}
diff --git a/resources/[qb]/[qb_casino]/casino-roulette/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-roulette/fxmanifest.lua
new file mode 100644
index 0000000..8330866
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-roulette/fxmanifest.lua
@@ -0,0 +1,23 @@
+version '1.0.2'
+author 'freamee'
+decription 'Aquiver rulett'
+
+
+client_scripts {
+ 'config.lua',
+ '@PolyZone/client.lua',
+ '@PolyZone/BoxZone.lua',
+ '@PolyZone/EntityZone.lua',
+ '@PolyZone/CircleZone.lua',
+ '@PolyZone/ComboZone.lua',
+ 'client/cl_main.lua'
+}
+
+server_scripts {
+ 'config.lua',
+ -- 'translations.lua',
+ 'server/sv_main.lua'
+}
+
+game 'gta5'
+fx_version 'cerulean'
diff --git a/resources/[qb]/[qb_casino]/casino-roulette/server/sv_main.lua b/resources/[qb]/[qb_casino]/casino-roulette/server/sv_main.lua
new file mode 100644
index 0000000..0dd65e2
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-roulette/server/sv_main.lua
@@ -0,0 +1,335 @@
+
+local QBCore = exports['qb-core']:GetCoreObject()
+
+local aktivRulettek = {}
+
+
+function getPlayerChips(source)
+ -- local Player = QBCore.Functions.GetPlayer(source)
+ -- local Chips = Player.Functions.GetItemByName("casino_redchip")
+ -- if Chips ~= nil then
+ -- if Chips.amount >= 10 then
+ -- return Chips.amount
+ -- else end
+ -- else end
+
+ local Player = QBCore.Functions.GetPlayer(source)
+ local retval = 0
+ local Item = Player.Functions.GetItemByName('casino_redchip')
+ if Item then
+ retval = Item.amount
+ end
+ return retval
+end
+
+function giveChips(source, amount)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.Functions.AddItem("casino_redchip", amount, nil, nil, false, GetCurrentResourceName(), "", "", "") then
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items['casino_redchip'], "add")
+ TriggerClientEvent('QBCore:Notify', source, "+ "..amount.." Chips")
+ end
+end
+
+function removeChips(source, amount)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.Functions.RemoveItem("casino_redchip", amount) then
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items['casino_redchip'], "remove")
+ TriggerClientEvent('QBCore:Notify', source, "- "..amount.." Chips")
+ end
+end
+
+
+local ItemList = {
+ ["casino_redchip"] = 1
+}
+QBCore.Functions.CreateCallback('roulette:server:ChipsAmount', function(source, cb)
+ local retval = 0
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.PlayerData.items ~= nil and next(Player.PlayerData.items) ~= nil then
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ retval = retval + (ItemList[Player.PlayerData.items[k].name] * Player.PlayerData.items[k].amount)
+ end
+ end
+ end
+ end
+ cb(retval)
+end)
+--//////////////////////////--//////////////////////////--//////////////////////////
+
+function isPlayerExist(source)
+ if GetPlayerName(source) ~= nil then
+ return true
+ else
+ return false
+ end
+end
+
+RegisterNetEvent('server_remote:rulett:taskSitDown',function(rulettIndex, chairData)
+ local source = source
+ local chairId = chairData.chairId
+
+ if aktivRulettek[rulettIndex] ~= nil then
+ if aktivRulettek[rulettIndex].chairsUsed[chairId] ~= nil then
+ return TriggerClientEvent('QBCore:Notify', source, 'This chair is occupied.','error')
+ else
+ TriggerClientEvent('client_callback:rulett:taskSitDown', source, rulettIndex, chairData)
+ end
+ else
+ TriggerClientEvent('client_callback:rulett:taskSitDown', source, rulettIndex, chairData)
+ end
+end)
+
+RegisterNetEvent('casino:taskStartRoulette',function(rulettIndex, chairId)
+ local source = source
+ if aktivRulettek[rulettIndex] == nil then
+ aktivRulettek[rulettIndex] = {
+ statusz = false,
+ ido = Config.RouletteStart,
+ bets = {},
+ chairsUsed = {}
+ }
+
+ Config.DebugMsg(string.format('created rulett on serverside. table: %s', rulettIndex))
+ end
+ if aktivRulettek[rulettIndex].chairsUsed[chairId] == nil then
+ aktivRulettek[rulettIndex].chairsUsed[chairId] = source
+ TriggerClientEvent('client:casino:openRulett', source, rulettIndex)
+ else
+ TriggerClientEvent('QBCore:Notify', source, 'This chair is occupied.','error')
+ end
+end)
+
+function countTablePlayers(rulettIndex)
+ local count = 0
+ if aktivRulettek[rulettIndex] ~= nil then
+ for chairId, _ in pairs(aktivRulettek[rulettIndex].chairsUsed) do
+ count = count + 1
+ end
+ return count
+ else
+ return count
+ end
+end
+
+RegisterNetEvent('casino:rulett:notUsing')
+AddEventHandler('casino:rulett:notUsing',function(rulettIndex)
+ local source = source
+ if aktivRulettek[rulettIndex] ~= nil then
+ for chairId, src in pairs(aktivRulettek[rulettIndex].chairsUsed) do
+ if src == source then
+ aktivRulettek[rulettIndex].chairsUsed[chairId] = nil
+ end
+ end
+ end
+end)
+
+AddEventHandler('playerDropped',function(reason)
+ local source = source
+ for rulettIndex, v in pairs(aktivRulettek) do
+ for chairId, src in pairs(v.chairsUsed) do
+ if src == source then
+ aktivRulettek[rulettIndex].chairsUsed[chairId] = nil
+ end
+ end
+ end
+end)
+
+Citizen.CreateThread(
+ function()
+ while true do
+ Citizen.Wait(1000)
+
+ for rulettIndex, v in pairs(aktivRulettek) do
+ if v.statusz == false then
+ if v.ido > 0 then
+ aktivRulettek[rulettIndex].ido = v.ido - 1
+ TriggerClientEvent('client:rulett:updateStatusz', -1, rulettIndex, v.ido, v.statusz)
+ end
+
+ if v.ido < 1 then
+ local randomSpinNumber = math.random(1, 38) -- do not modify this you idiot
+ if Config.TestTicker ~= nil then
+ randomSpinNumber = Config.TestTicker
+ end
+ local WinningBetIndex = Config.rouletteSzamok[randomSpinNumber]
+
+ Config.DebugMsg(string.format('Rulett randomSpinNumber: %s, which is number: %s', randomSpinNumber, WinningBetIndex))
+
+ aktivRulettek[rulettIndex].statusz = true
+ aktivRulettek[rulettIndex].WinningBetIndex = WinningBetIndex
+ TriggerClientEvent('client:rulett:updateStatusz', -1, rulettIndex, v.ido, v.statusz)
+
+ Citizen.CreateThread(
+ function()
+ Config.DebugMsg('time remaining 0, starting the spin events.')
+ TriggerClientEvent('casino:rulett:startSpin', -1, rulettIndex, randomSpinNumber)
+ Citizen.Wait(15500)
+
+ if #v.bets > 0 then
+ CheckWinners(v.bets, aktivRulettek[rulettIndex].WinningBetIndex)
+ aktivRulettek[rulettIndex].statusz = false
+ aktivRulettek[rulettIndex].ido = Config.RouletteStart
+ aktivRulettek[rulettIndex].WinningBetIndex = nil
+ aktivRulettek[rulettIndex].bets = {} -- reset the bets on the table, very importante
+ TriggerClientEvent('client:rulett:updateTableBets', -1, rulettIndex, aktivRulettek[rulettIndex].bets)
+ else
+ if countTablePlayers(rulettIndex) < 1 then
+ aktivRulettek[rulettIndex] = nil -- deleting the table from srv
+ Config.DebugMsg(string.format('Rulett table id %s, stopped because no one using it.', rulettIndex))
+ TriggerClientEvent('client:rulett:updateStatusz', -1, rulettIndex, nil, nil)
+ else
+ aktivRulettek[rulettIndex].statusz = false
+ aktivRulettek[rulettIndex].ido = Config.RouletteStart
+ aktivRulettek[rulettIndex].WinningBetIndex = nil
+ aktivRulettek[rulettIndex].bets = {} -- reset the bets on the table, very importante
+ TriggerClientEvent('client:rulett:updateTableBets', -1, rulettIndex, aktivRulettek[rulettIndex].bets)
+ end
+ end
+ end
+ )
+ end
+ end
+ end
+ end
+ end
+)
+
+function CheckWinners(bets, WinningBetIndex)
+ local playersWon = {}
+ local playersLoss = {}
+
+ for i = 1, #bets, 1 do
+ local betData = bets[i]
+
+ local targetSrc = betData.playerSrc
+ local PLAYER_HANDLE = isPlayerExist(targetSrc)
+ if PLAYER_HANDLE then
+ betData.betId = tostring(betData.betId)
+ if (WinningBetIndex == '0' and betData.betId == '37') or (WinningBetIndex == '00' and betData.betId == '38') then -- dbl zero, and zero
+ giveWinningChips(targetSrc, betData.betAmount, 35)
+ playersWon[targetSrc] = true
+ if playersLoss[targetSrc] then
+ playersWon[targetSrc] = nil
+ end
+ elseif
+ (betData.betId == '39' and RULETT_NUMBERS.Pirosak[WinningBetIndex]) or (betData.betId == '40' and RULETT_NUMBERS.Feketek[WinningBetIndex]) or
+ (betData.betId == '41' and RULETT_NUMBERS.Parosak[WinningBetIndex]) or
+ (betData.betId == '42' and RULETT_NUMBERS.Paratlanok[WinningBetIndex]) or
+ (betData.betId == '43' and RULETT_NUMBERS.to18[WinningBetIndex]) or
+ (betData.betId == '44' and RULETT_NUMBERS.to36[WinningBetIndex])
+ then
+ giveWinningChips(targetSrc, betData.betAmount, 2)
+ playersWon[targetSrc] = true
+ if playersLoss[targetSrc] then
+ playersWon[targetSrc] = nil
+ end
+ elseif betData.betId <= '36' and WinningBetIndex == betData.betId then -- the numbers
+ giveWinningChips(targetSrc, betData.betAmount, 35)
+ playersWon[targetSrc] = true
+ if playersLoss[targetSrc] then
+ playersWon[targetSrc] = nil
+ end
+ elseif
+ (betData.betId == '45' and RULETT_NUMBERS.st12[WinningBetIndex]) or (betData.betId == '46' and RULETT_NUMBERS.sn12[WinningBetIndex]) or
+ (betData.betId == '47' and RULETT_NUMBERS.rd12[WinningBetIndex]) or
+ (betData.betId == '48' and RULETT_NUMBERS.ket_to_1[WinningBetIndex]) or
+ (betData.betId == '49' and RULETT_NUMBERS.ket_to_2[WinningBetIndex]) or
+ (betData.betId == '50' and RULETT_NUMBERS.ket_to_3[WinningBetIndex])
+ then
+ giveWinningChips(targetSrc, betData.betAmount, 3)
+ playersWon[targetSrc] = true
+
+ if playersLoss[targetSrc] then
+ playersWon[targetSrc] = nil
+ end
+ else -- LOSS
+ if playersWon[targetSrc] == nil then
+ playersLoss[targetSrc] = true
+ else
+ playersLoss[targetSrc] = nil
+ end
+ end
+ end
+ end
+
+ for targetSrc, _ in pairs(playersLoss) do
+ local chairId = getPlayerTableSeat(targetSrc)
+ if chairId ~= nil then
+ TriggerClientEvent('client:rulett:playLossAnim', targetSrc, chairId)
+ TriggerClientEvent('QBCore:Notify', targetSrc, 'You Lost... Better luck next time', "error")
+ end
+ end
+
+ for targetSrc, _ in pairs(playersWon) do
+ local chairId = getPlayerTableSeat(targetSrc)
+ if chairId ~= nil then
+ TriggerClientEvent('client:rulett:playWinAnim', targetSrc, chairId)
+ end
+ end
+end
+
+function giveWinningChips(source, amount, szorzo)
+ amount = math.floor(amount * szorzo)
+ if amount > 0 then
+ giveChips(source, amount)
+ end
+end
+
+RegisterNetEvent('casino:taskBetRulett',function(rulettIndex, betId, betAmount)
+ local src = source
+ if aktivRulettek[rulettIndex] ~= nil then
+ if aktivRulettek[rulettIndex].statusz then
+ return TriggerClientEvent('QBCore:Notify', src, 'The game started, you can not bet at the moment.', "error")
+ end
+ local chipsAmount = getPlayerChips(src)
+ if chipsAmount ~= nil then
+ if chipsAmount >= betAmount then
+ removeChips(src, betAmount)
+ -- TriggerClientEvent('QBCore:Notify', src, betAmount..' chips bet on ['..betId..']')
+ Config.DebugMsg(string.format('player %s betted %s chips on betId: %s', GetPlayerName(src), betAmount, betId))
+ local exist = false
+ for i = 1, #aktivRulettek[rulettIndex].bets, 1 do
+ local d = aktivRulettek[rulettIndex].bets[i]
+ if d.betId == betId and d.playerSrc == src then
+ exist = true
+ aktivRulettek[rulettIndex].bets[i].betAmount = aktivRulettek[rulettIndex].bets[i].betAmount + betAmount
+ end
+ end
+ if not exist then
+ table.insert(
+ aktivRulettek[rulettIndex].bets,
+ {
+ betId = betId,
+ playerSrc = src,
+ betAmount = betAmount
+ }
+ )
+ end
+ TriggerClientEvent('client:rulett:updateTableBets', -1, rulettIndex, aktivRulettek[rulettIndex].bets)
+ local chairId = getPlayerTableSeat(src)
+ if chairId ~= nil then
+ Config.DebugMsg(string.format('%s chair betanim play', chairId))
+ TriggerClientEvent('client:rulett:playBetAnim', src, chairId)
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'You do not have enough Casino chips to place bet.', "error")
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'You dont have any caino chips', 'error')
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'error', 'An error occurred on a non-existent roulette table server side?')
+ end
+end)
+
+function getPlayerTableSeat(source)
+ for rulettIndex, v in pairs(aktivRulettek) do
+ for chairId, src in pairs(v.chairsUsed) do
+ if src == source then
+ return chairId
+ end
+ end
+ end
+end
diff --git a/resources/[qb]/[qb_casino]/casino-slots/client.lua b/resources/[qb]/[qb_casino]/casino-slots/client.lua
new file mode 100644
index 0000000..d9a4c00
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-slots/client.lua
@@ -0,0 +1,489 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+local Slot
+local SlotCoords
+local ClosestSlot
+local ClosestSlotCoord = vector3(0, 0, 0)
+local ClosestSlotRotation
+local NearbySlot
+local EnteredSlot
+local IsSpinning
+local ReelLocation1
+local ReelLocation2
+local ReelLocation3
+local ClosestSlotForwardX
+local ClosestSlotForwardY
+local ShouldDrawScaleForm = false
+local Scaleform
+local ClosestSlotModel
+local AnimDict = 'anim_casino_a@amb@casino@games@slots@male'
+local Sounds = {
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'no_win', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'small_win', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'big_win', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'jackpot', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'place_bet', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'place_max_bet', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'spinning', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'start_spin', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'wheel_stop_clunk', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'wheel_stop_on_prize', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'welcome_stinger', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'spin_wheel', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end,
+ function() local SoundId = GetSoundId() PlaySoundFromCoord(SoundId, 'spin_wheel_win', ClosestSlotCoord, SlotReferences[ClosestSlotModel].sound, false, 20, false) ReleaseSoundId(SoundId) end
+}
+local Slots = {
+ 2362925439,
+ 2775323096,
+ 3863977906,
+ 654385216,
+ 161343630,
+ 1096374064,
+ 207578973,
+ 3807744938
+}
+local RandomEnter = {
+ 'enter_left',
+ 'enter_right',
+ 'enter_left_short',
+ 'enter_right_short'
+}
+local RandomLeave = {
+ 'exit_left',
+ 'exit_right'
+}
+local RandomIdle = {
+ 'base_idle_a',
+ 'base_idle_b',
+ 'base_idle_c',
+ 'base_idle_d',
+ 'base_idle_e',
+ 'base_idle_f'
+}
+local RandomSpin = {
+ 'press_spin_a',
+ 'press_spin_b',
+ 'pull_spin_a',
+ 'pull_spin_b'
+}
+local RandomSpinningIdle = {
+ 'spinning_a',
+ 'spinning_b',
+ 'spinning_c'
+}
+local RandomWin = {
+ 'win_a',
+ 'win_b',
+ 'win_c',
+ 'win_d',
+ 'win_e',
+ 'win_f',
+ 'win_g',
+ 'win_spinning_wheel'
+}
+local RandomLose = {
+ 'lose_a',
+ 'lose_b',
+ 'lose_c',
+ 'lose_d',
+ 'lose_e',
+ 'lose_f',
+ 'lose_cruel_a',
+ 'lose_cruel_b'
+}
+local RandomBigWin = {
+ 'win_big_a',
+ 'win_big_b',
+ 'win_big_c'
+}
+local RandomEnterMessage = {
+ 'Daring today?',
+ 'Spin to win',
+ 'You will lose money!',
+ 'Feelin lucky punk?!',
+ 'Test your might',
+ 'You have coins?'
+}
+local ChosenBetAmount = 1
+
+local function DrawText3D(x, y, z, text)
+ SetTextScale(0.35, 0.35)
+ SetTextFont(4)
+ SetTextProportional(1)
+ SetTextColour(255, 255, 255, 215)
+ SetTextEntry("STRING")
+ SetTextCentre(true)
+ AddTextComponentString(text)
+ SetDrawOrigin(x,y,z, 0)
+ DrawText(0.0, 0.0)
+ local factor = (string.len(text)) / 370
+ DrawRect(0.0, 0.0+0.0125, 0.017+ factor, 0.03, 0, 0, 0, 75)
+ ClearDrawOrigin()
+end
+
+local function LoadAnimDict(dict) while not HasAnimDictLoaded(dict) do RequestAnimDict(dict) Wait(0) end end
+
+local function StartIdleScene(CurrentAnimation)
+ Wait(GetAnimDuration(AnimDict, CurrentAnimation) * 800)
+ local IdleScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ local RandomAnimName = RandomIdle[math.random(1, #RandomIdle)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), IdleScene, AnimDict, RandomAnimName, 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(IdleScene)
+end
+
+local function CreateNamedRenderTargetForModel(name, model)
+ local handle = 0
+ if not IsNamedRendertargetRegistered(name) then
+ RegisterNamedRendertarget(name, 0)
+ end
+ if not IsNamedRendertargetLinked(model) then
+ LinkNamedRendertarget(model)
+ end
+ if IsNamedRendertargetRegistered(name) then
+ handle = GetNamedRendertargetRenderId(name)
+ end
+ return handle
+end
+
+local function CallScaleformMethod(method, ...)
+ local t
+ local args = { ... }
+ BeginScaleformMovieMethod(Scaleform, method)
+ for _, v in ipairs(args) do
+ t = type(v)
+ if t == 'string' then
+ PushScaleformMovieMethodParameterString(v)
+ elseif t == 'number' then
+ if string.match(tostring(v), "%.") then
+ PushScaleformMovieFunctionParameterFloat(v)
+ else
+ PushScaleformMovieFunctionParameterInt(v)
+ end
+ elseif t == 'boolean' then
+ PushScaleformMovieMethodParameterBool(v)
+ end
+ end
+ EndScaleformMovieMethod()
+end
+
+local function SetupScaleform()
+ CreateThread(function()
+ Scaleform = RequestScaleformMovie('SLOT_MACHINE')
+ while not HasScaleformMovieLoaded(Scaleform) do Wait(0) end
+ if SlotReferences[ClosestSlotModel].theme then CallScaleformMethod('SET_THEME', SlotReferences[ClosestSlotModel].theme) else CallScaleformMethod('SET_THEME') end
+ local model = ClosestSlotModel
+ local handle = CreateNamedRenderTargetForModel("machine_"..SlotReferences[ClosestSlotModel].scriptrt, model)
+ while ShouldDrawScaleForm do
+ N_0x32f34ff7f617643b(Scaleform, 1)
+ SetTextRenderId(handle) -- Sets the render target to the handle we grab above
+ SetScriptGfxDrawOrder(4)
+ SetScriptGfxDrawBehindPausemenu(true)
+ DrawScaleformMovie(Scaleform, 0.401, 0.09, 0.805, 0.195, 255, 255, 255, 255, 0)
+ SetTextRenderId(GetDefaultScriptRendertargetRenderId()) -- Resets the render target
+ Wait(0)
+ end
+ end)
+end
+
+local function SlotMachineHandler()
+ local LeverScene = 0
+ local IdleScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ local RandomAnimName = RandomIdle[math.random(1, #RandomIdle)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), IdleScene, AnimDict, RandomAnimName, 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(IdleScene)
+ exports['qb-core']:DrawText('Spin: ↵ Leave: ← Adjust Bet: ↑')
+ CreateThread(function()
+ while true do
+ QBCore.Functions.TriggerCallback('doj:server:CasinoChipsAmount', function(result)
+ exports['casinoUi']:DrawCasinoUi('show', "The Diamond Casino & Resort Slots"..SlotReferences[ClosestSlotModel].name.."Availble chips: "..math.floor(result))
+ end)
+ if not IsSpinning then
+ if IsControlJustPressed(0, 202) then -- BACKSPACE
+ local LeaveScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ RandomAnimName = RandomLeave[math.random(1, #RandomLeave)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), LeaveScene, AnimDict, RandomAnimName, 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(LeaveScene)
+ Wait(GetAnimDuration(AnimDict, RandomAnimName) * 700)
+ NetworkStopSynchronisedScene(LeaveScene)
+ EnteredSlot = false
+ ShouldDrawScaleForm = false
+ exports['qb-core']:HideText()
+ exports['casinoUi']:HideCasinoUi('hide')
+ CallScaleformMethod('SET_BET')
+ CallScaleformMethod('SET_LAST_WIN')
+ CallScaleformMethod('SET_MESSAGE', '')
+ TriggerServerEvent('dc-casino:slots:server:leave')
+ break
+ elseif IsControlJustPressed(0, 201) then -- ENTER
+ local SpinScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ RandomAnimName = RandomSpin[math.random(1, #RandomSpin)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), SpinScene, AnimDict, RandomAnimName, 2.0, -1.5, 13, 16, 1000.0, 0)
+ NetworkStartSynchronisedScene(SpinScene)
+ local AnimationDuration = GetAnimDuration(AnimDict, RandomAnimName)
+ if RandomAnimName == 'pull_spin_a' then
+ LeverScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ N_0x45f35c0edc33b03b(LeverScene, GetEntityModel(ClosestSlot), ClosestSlotCoord, AnimDict, 'pull_spin_a_SLOTMACHINE', 2.0, -1.5, 13.0)
+ NetworkStartSynchronisedScene(LeverScene)
+ Wait(AnimationDuration * 320)
+ elseif RandomAnimName == 'pull_spin_b' then
+ LeverScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ N_0x45f35c0edc33b03b(LeverScene, GetEntityModel(ClosestSlot), ClosestSlotCoord, AnimDict, 'pull_spin_b_SLOTMACHINE', 2.0, -1.5, 13.0)
+ NetworkStartSynchronisedScene(LeverScene)
+ Wait(AnimationDuration * 320)
+ end
+ Wait(AnimationDuration * 180)
+ Sounds[8]()
+ TriggerServerEvent('dc-casino:slots:server:spin', ChosenBetAmount)
+ Wait(AnimationDuration * 500)
+ local SpinningScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), SpinningScene, AnimDict, RandomSpinningIdle[math.random(1, #RandomSpinningIdle)], 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(SpinningScene)
+ NetworkStopSynchronisedScene(LeverScene) --- Has to be stopped otherwise it will only work 50% of the time
+ FreezeEntityPosition(ClosestSlot, true) --- N_0x45f35c0edc33b03b will prevent the machine being stuck to their position for some reason?
+ elseif IsControlJustPressed(0, 172) then -- UP ARROW
+ Sounds[5]()
+ if not SlotReferences[ClosestSlotModel].betamounts[ChosenBetAmount + 1] then ChosenBetAmount = 1 else ChosenBetAmount = ChosenBetAmount + 1 end
+ local BetOneScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), BetOneScene, AnimDict, 'press_betone_a', 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(BetOneScene)
+ Wait(GetAnimDuration(AnimDict, 'press_betone_a') * 200)
+ CallScaleformMethod('SET_BET', SlotReferences[ClosestSlotModel].betamounts[ChosenBetAmount])
+ StartIdleScene('press_betone_a')
+ elseif IsControlJustPressed(0, 45) then -- R
+ Sounds[6]()
+ ChosenBetAmount = #SlotReferences[ClosestSlotModel].betamounts
+ local BetMaxScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), BetMaxScene, AnimDict, 'press_betmax_a', 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(BetMaxScene)
+ Wait(GetAnimDuration(AnimDict, 'press_betmax_a') * 200)
+ CallScaleformMethod('SET_BET', SlotReferences[ClosestSlotModel].betamounts[ChosenBetAmount])
+ StartIdleScene('press_betmax_a')
+ elseif IsEntityDead(PlayerPedId()) then
+ EnteredSlot = false
+ ShouldDrawScaleForm = false
+ exports['qb-core']:HideText()
+ CallScaleformMethod('SET_BET')
+ CallScaleformMethod('SET_MESSAGE', '')
+ TriggerServerEvent('dc-casino:slots:server:leave')
+ break
+ end
+ end
+ Wait(0)
+ end
+ end)
+end
+
+CreateThread(function()
+ while not RequestScriptAudioBank("dlc_vinewood/casino_slot_machines_01", 0) do Wait(0) end
+ while not RequestScriptAudioBank("dlc_vinewood/casino_slot_machines_02", 0) do Wait(0) end
+ while not RequestScriptAudioBank("dlc_vinewood/casino_slot_machines_03", 0) do Wait(0) end
+ while true do
+ local PlayerCoords = GetEntityCoords(PlayerPedId())
+ for i = 1, #Slots do
+ Slot = GetClosestObjectOfType(PlayerCoords, 1.2, Slots[i], true)
+ if Slot ~= 0 then
+ SlotCoords = GetEntityCoords(Slot)
+ local CurrentDistance = #(PlayerCoords - SlotCoords)
+ if CurrentDistance < 1.9 and CurrentDistance < #(PlayerCoords - ClosestSlotCoord) then
+ NearbySlot = true
+ ClosestSlot = Slot
+ ClosestSlotCoord = SlotCoords
+ ClosestSlotForwardX = GetEntityForwardX(ClosestSlot)
+ ClosestSlotForwardY = GetEntityForwardY(ClosestSlot)
+ ClosestSlotModel = GetEntityModel(ClosestSlot)
+ ClosestSlotRotation = GetEntityRotation(ClosestSlot)
+ ReelLocation1 = GetObjectOffsetFromCoords(ClosestSlotCoord, GetEntityHeading(ClosestSlot), -0.115, 0.047, 0.906)
+ ReelLocation2 = GetObjectOffsetFromCoords(ClosestSlotCoord, GetEntityHeading(ClosestSlot), 0.005, 0.047, 0.906)
+ ReelLocation3 = GetObjectOffsetFromCoords(ClosestSlotCoord, GetEntityHeading(ClosestSlot), 0.125, 0.047, 0.906)
+ end
+ elseif #(PlayerCoords - ClosestSlotCoord) > 1.9 then
+ NearbySlot = false
+ end
+ end
+ Wait(600)
+ end
+end)
+
+-- CreateThread(function()
+-- while true do
+-- local WaitTime = 500
+-- if NearbySlot and not EnteredSlot then
+-- WaitTime = 0
+-- -- exports['qb-core']:DrawText('Diamond Casino Slots'..SlotReferences[ClosestSlotModel].name..'Press [E] to sit')
+-- DrawText3D(ClosestSlotCoord.x - ClosestSlotForwardX, ClosestSlotCoord.y - ClosestSlotForwardY, ClosestSlotCoord.z + 1, "[E] - Play ~b~"..SlotReferences[ClosestSlotModel].name)
+-- if IsControlJustReleased(0, 38) then
+
+-- QBCore.Functions.TriggerCallback('doj:server:HasCasinoMembership', function(HasItem)
+-- if HasItem then
+-- local netID = NetworkGetEntityIsNetworked(ClosestSlot) and NetworkGetNetworkIdFromEntity(ClosestSlot)
+-- if not netID then
+-- NetworkRegisterEntityAsNetworked(ClosestSlot)
+-- netID = NetworkGetNetworkIdFromEntity(ClosestSlot)
+-- NetworkUseHighPrecisionBlending(netID, false)
+-- SetNetworkIdExistsOnAllMachines(netID, true)
+-- SetNetworkIdCanMigrate(netID, true)
+-- end
+-- NetworkRequestControlOfEntity(ClosestSlot)
+-- TriggerServerEvent('dc-casino:slots:server:enter', netID, ReelLocation1, ReelLocation2, ReelLocation3)
+-- else
+-- QBCore.Functions.Notify('You are not a member of the casino!', 'error', 3500)
+-- end
+-- end)
+-- end
+-- -- elseif not NearbySlot then
+-- -- exports["qb-core"]:HideText()
+-- end
+-- Wait(WaitTime)
+-- end
+-- end)
+
+
+
+Citizen.CreateThread(function()
+ local alreadyEnteredZone = false
+ local text = nil
+ while true do
+ if NearbySlot and not EnteredSlot then
+ wait = 5
+ local pedCo = GetEntityCoords(PlayerPedId())
+ local dist = #(pedCo - ClosestSlotCoord)
+ local inZone = false
+ if dist <= 2.0 then
+ wait = 5
+ inZone = true
+ text = 'The Diamond Casino & ResortSlot: '..SlotReferences[ClosestSlotModel].name..'Press E to sit'
+ if IsControlJustPressed(0, 38) then
+ local netID = NetworkGetEntityIsNetworked(ClosestSlot) and NetworkGetNetworkIdFromEntity(ClosestSlot)
+ if not netID then
+ NetworkRegisterEntityAsNetworked(ClosestSlot)
+ netID = NetworkGetNetworkIdFromEntity(ClosestSlot)
+ NetworkUseHighPrecisionBlending(netID, false)
+ SetNetworkIdExistsOnAllMachines(netID, true)
+ SetNetworkIdCanMigrate(netID, true)
+ end
+ NetworkRequestControlOfEntity(ClosestSlot)
+ TriggerServerEvent('dc-casino:slots:server:enter', netID, ReelLocation1, ReelLocation2, ReelLocation3)
+ end
+ else
+ wait = 2000
+ end
+ if inZone and not alreadyEnteredZone then
+ alreadyEnteredZone = true
+ exports["qb-core"]:DrawText(text)
+ end
+ if not inZone and alreadyEnteredZone then
+ alreadyEnteredZone = false
+ exports["qb-core"]:HideText()
+ end
+ end
+ Wait(wait)
+ end
+end)
+
+RegisterNetEvent('dc-casino:slots:client:enter', function()
+ local Ped = PlayerPedId()
+ exports["qb-core"]:HideText()
+ if GetEntityModel(Ped) == `mp_f_freemode_01` then AnimDict = 'anim_casino_a@amb@casino@games@slots@female' end
+ local EnterScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ local RandomAnimName = RandomEnter[math.random(1, #RandomEnter)]
+ NetworkAddPedToSynchronisedScene(Ped, EnterScene, AnimDict, RandomAnimName, 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(EnterScene)
+ EnteredSlot = true
+ ShouldDrawScaleForm = true
+ SetupScaleform()
+ Wait(GetAnimDuration(AnimDict, RandomAnimName) * 1000)
+ CallScaleformMethod('SET_MESSAGE', RandomEnterMessage[math.random(1, #RandomEnterMessage)])
+ CallScaleformMethod('SET_BET', SlotReferences[ClosestSlotModel].betamounts[ChosenBetAmount])
+ Sounds[11]()
+ SlotMachineHandler()
+end)
+
+RegisterNetEvent('dc-casino:slots:client:spinreels', function(SpinTime, ReelRewards, BlurryReelID1, BlurryReelID2, BlurryReelID3, ReelID1, ReelID2, ReelID3, RewardMultiplier)
+ local EndTime = GetGameTimer() + SpinTime
+ local FirstReelStop = SpinTime * math.random(2, 4) / 10
+ local SecondReelStop = SpinTime * math.random(5, 7) / 10
+ local ReelReward1 = ReelRewards[1] * 22.5
+ local ReelReward2 = ReelRewards[2] * 22.5
+ local ReelReward3 = ReelRewards[3] * 22.5
+ local SlotHeading = GetEntityHeading(ClosestSlot)
+ local BlurryReel1 = NetworkGetEntityFromNetworkId(BlurryReelID1)
+ local BlurryReel2 = NetworkGetEntityFromNetworkId(BlurryReelID2)
+ local BlurryReel3 = NetworkGetEntityFromNetworkId(BlurryReelID3)
+ local Reel1 = NetworkGetEntityFromNetworkId(ReelID1)
+ local Reel2 = NetworkGetEntityFromNetworkId(ReelID2)
+ local Reel3 = NetworkGetEntityFromNetworkId(ReelID3)
+ while not NetworkRequestControlOfEntity(BlurryReel1) do Wait(0) end
+ while not NetworkRequestControlOfEntity(BlurryReel2) do Wait(0) end
+ while not NetworkRequestControlOfEntity(BlurryReel3) do Wait(0) end
+ while not NetworkRequestControlOfEntity(Reel1) do Wait(0) end
+ while not NetworkRequestControlOfEntity(Reel2) do Wait(0) end
+ while not NetworkRequestControlOfEntity(Reel3) do Wait(0) end
+
+ IsSpinning = true
+ SetEntityVisible(Reel1, false)
+ SetEntityVisible(Reel2, false)
+ SetEntityVisible(Reel3, false)
+ Sounds[7]()
+ while GetGameTimer() < EndTime do
+ SetEntityRotation(BlurryReel1, math.random(0, 15) * 22.5 + math.random(1, 60), 0.0, SlotHeading, 2, true)
+ if EndTime - GetGameTimer() > FirstReelStop then
+ SetEntityRotation(BlurryReel2, math.random(0, 15) * 22.5 + math.random(1, 60), 0.0, SlotHeading, 2, true)
+ if EndTime - GetGameTimer() < FirstReelStop + 15 then
+ if ReelRewards[2] == math.floor(ReelRewards[2]) then Sounds[9]() else Sounds[10]() end
+ DeleteObject(BlurryReel2)
+ SetEntityRotation(Reel2, ReelReward2, 0.0, SlotHeading, 2, true)
+ SetEntityVisible(Reel2, true)
+ end
+ if EndTime - GetGameTimer() > SecondReelStop then
+ SetEntityRotation(BlurryReel3, math.random(0, 15) * 22.5 + math.random(1, 60), 0.0, SlotHeading, 2, true)
+ if EndTime - GetGameTimer() < SecondReelStop + 15 then
+ if ReelRewards[3] == math.floor(ReelRewards[3]) then Sounds[9]() else Sounds[10]() end
+ DeleteObject(BlurryReel3)
+ SetEntityRotation(Reel3, ReelReward3, 0.0, SlotHeading, 2, true)
+ SetEntityVisible(Reel3, true)
+ end
+ end
+ end
+ Wait(0)
+ end
+ DeleteObject(BlurryReel1)
+ SetEntityRotation(Reel1, ReelReward1, 0.0, SlotHeading, 2, true)
+ SetEntityVisible(Reel1, true)
+ CallScaleformMethod('SET_LAST_WIN', SlotReferences[ClosestSlotModel].betamounts[ChosenBetAmount] * RewardMultiplier)
+ if ReelRewards[1] == math.floor(ReelRewards[1]) then Sounds[9]() else Sounds[10]() end
+ if RewardMultiplier == 0 then
+ Sounds[1]()
+ QBCore.Functions.Notify('You Lose', 'error', 3500)
+ -- exports['qb-core']:DrawText('You Lose)
+ local LoseScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ local RandomAnim = RandomLose[math.random(1, #RandomLose)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), LoseScene, AnimDict, RandomLose[math.random(1, #RandomLose)], 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(LoseScene)
+ StartIdleScene(RandomAnim)
+ elseif RewardMultiplier > 7 then
+ if ReelReward1 == 5 and ReelReward2 == 5 and ReelReward3 == 5 then Sounds[4]() else Sounds[3]() end
+ local BigWinScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ local RandomAnim = RandomBigWin[math.random(1, #RandomBigWin)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), BigWinScene, AnimDict, RandomBigWin[math.random(1, #RandomBigWin)], 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(BigWinScene)
+ StartIdleScene(RandomAnim)
+ else
+ Sounds[2]()
+ local WinScene = NetworkCreateSynchronisedScene(ClosestSlotCoord, ClosestSlotRotation, 2, 2, 0, 1.0, 0, 1.0)
+ LoadAnimDict(AnimDict)
+ local RandomAnim = RandomWin[math.random(1, #RandomWin)]
+ NetworkAddPedToSynchronisedScene(PlayerPedId(), WinScene, AnimDict, RandomAnim, 2.0, -1.5, 13, 16, 2.0, 0)
+ NetworkStartSynchronisedScene(WinScene)
+ StartIdleScene(RandomAnim)
+ end
+ IsSpinning = false
+end)
diff --git a/resources/[qb]/[qb_casino]/casino-slots/config.lua b/resources/[qb]/[qb_casino]/casino-slots/config.lua
new file mode 100644
index 0000000..e009bba
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-slots/config.lua
@@ -0,0 +1,234 @@
+SlotReferences = {
+ [-1932041857] = {
+ sound = 'dlc_vw_casino_slot_machine_ak_npc_sounds',
+ texture = 'CasinoUI_Slots_Angel',
+ name = 'Angel And The Knight',
+ reela = `vw_prop_casino_slot_01a_reels`,
+ reelb = `vw_prop_casino_slot_01b_reels`,
+ scriptrt = '01a',
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [-1519644200] = {
+ sound = 'dlc_vw_casino_slot_machine_ir_npc_sounds',
+ texture = 'CasinoUI_Slots_Impotent',
+ name = 'Impotent Rage',
+ reela = `vw_prop_casino_slot_02a_reels`,
+ reelb = `vw_prop_casino_slot_02b_reels`,
+ scriptrt = '02a',
+ theme = 2,
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [-430989390] = {
+ sound = 'dlc_vw_casino_slot_machine_rsr_npc_sounds',
+ texture = 'CasinoUI_Slots_Ranger',
+ name = 'Republican Space Rangers',
+ reela = `vw_prop_casino_slot_03a_reels`,
+ reelb = `vw_prop_casino_slot_03b_reels`,
+ scriptrt = '03a',
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [654385216] = {
+ sound = 'dlc_vw_casino_slot_machine_fs_npc_sounds',
+ texture = 'CasinoUI_Slots_Fame',
+ name = 'Fame Or Shame',
+ reela = `vw_prop_casino_slot_04a_reels`,
+ reelb = `vw_prop_casino_slot_04b_reels`,
+ scriptrt = '04a',
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [161343630] = {
+ sound = 'dlc_vw_casino_slot_machine_ds_npc_sounds',
+ texture = 'CasinoUI_Slots_Deity',
+ name = 'Deity Of The Sun',
+ reela = `vw_prop_casino_slot_05a_reels`,
+ reelb = `vw_prop_casino_slot_05b_reels`,
+ scriptrt = '05a',
+ theme = 5,
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [1096374064] = {
+ sound = 'dlc_vw_casino_slot_machine_kd_npc_sounds',
+ texture = 'CasinoUI_Slots_Knife',
+ name = 'Twilight Knife',
+ reela = `vw_prop_casino_slot_06a_reels`,
+ reelb = `vw_prop_casino_slot_06b_reels`,
+ scriptrt = '06a',
+ theme = 6,
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [207578973] = {
+ sound = 'dlc_vw_casino_slot_machine_td_npc_sounds',
+ texture = 'CasinoUI_Slots_Diamond',
+ name = 'Diamond Miner',
+ reela = `vw_prop_casino_slot_07a_reels`,
+ reelb = `vw_prop_casino_slot_07b_reels`,
+ scriptrt = '07a',
+ theme = 7,
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+ [-487222358] = {
+ sound = 'dlc_vw_casino_slot_machine_hz_npc_sounds',
+ texture = 'CasinoUI_Slots_Evacuator',
+ name = 'Evacuator',
+ reela = `vw_prop_casino_slot_08a_reels`,
+ reelb = `vw_prop_casino_slot_08b_reels`,
+ scriptrt = '08a',
+ theme = 8,
+ misschance = math.random(10, 40),
+ betamounts = {
+ 50,
+ 100,
+ 150,
+ 250,
+ 500
+ }
+ },
+}
+
+Rewards = {
+ [{0, 0, 0}] = 10.0, --- Sevens
+ [{0, 0, 8}] = 10.0, --- Sevens
+ [{0, 8, 0}] = 10.0, --- Sevens
+ [{8, 0, 0}] = 10.0, --- Sevens
+ [{0, 8, 8}] = 10.0, --- Sevens
+ [{8, 0, 8}] = 10.0, --- Sevens
+ [{8, 8, 0}] = 10.0, --- Sevens
+ [{8, 8, 8}] = 10.0, --- Sevens
+
+ [{1, 1, 1}] = 1.5, --- Plums
+ [{1, 1, 9}] = 1.5, --- Plums
+ [{1, 9, 1}] = 1.5, --- Plums
+ [{9, 1, 1}] = 1.5, --- Plums
+ [{1, 1, 12}] = 1.5, --- Plums
+ [{1, 12, 1}] = 1.5, --- Plums
+ [{12, 1, 1}] = 1.5, --- Plums
+ [{1, 9, 9}] = 1.5, --- Plums
+ [{9, 1, 9}] = 1.5, --- Plums
+ [{9, 9, 1}] = 1.5, --- Plums
+ [{1, 9, 12}] = 1.5, --- Plums
+ [{1, 12, 9}] = 1.5, --- Plums
+ [{9, 1, 12}] = 1.5, --- Plums
+ [{9, 12, 1}] = 1.5, --- Plums
+ [{12, 1, 9}] = 1.5, --- Plums
+ [{12, 9, 1}] = 1.5, --- Plums
+ [{1, 12, 12}] = 1.5, --- Plums
+ [{12, 1, 12}] = 1.5, --- Plums
+ [{12, 12, 1}] = 1.5, --- Plums
+ [{9, 9, 9}] = 1.5, --- Plums
+ [{9, 9, 12}] = 1.5, --- Plums
+ [{9, 12, 9}] = 1.5, --- Plums
+ [{12, 9, 9}] = 1.5, --- Plums
+ [{9, 12, 12}] = 1.5, --- Plums
+ [{12, 9, 12}] = 1.5, --- Plums
+ [{12, 12, 9}] = 1.5, --- Plums
+ [{12, 12, 12}] = 1.5, --- Plums
+
+ [{2, 2, 2}] = 2.5, --- Cherries
+ [{2, 2, 6}] = 2.5, --- Cherries
+ [{2, 6, 2}] = 2.5, --- Cherries
+ [{6, 2, 2}] = 2.5, --- Cherries
+ [{2, 2, 14}] = 2.5, --- Cherries
+ [{2, 14, 2}] = 2.5, --- Cherries
+ [{14, 2, 2}] = 2.5, --- Cherries
+ [{2, 6, 6}] = 2.5, --- Cherries
+ [{6, 2, 6}] = 2.5, --- Cherries
+ [{6, 6, 2}] = 2.5, --- Cherries
+ [{2, 6, 14}] = 2.5, --- Cherries
+ [{2, 14, 6}] = 2.5, --- Cherries
+ [{6, 2, 14}] = 2.5, --- Cherries
+ [{6, 14, 2}] = 2.5, --- Cherries
+ [{14, 2, 6}] = 2.5, --- Cherries
+ [{14, 6, 2}] = 2.5, --- Cherries
+ [{2, 14, 14}] = 2.5, --- Cherries
+ [{14, 2, 14}] = 2.5, --- Cherries
+ [{14, 14, 2}] = 2.5, --- Cherries
+ [{6, 6, 6}] = 2.5, --- Cherries
+ [{6, 6, 14}] = 2.5, --- Cherries
+ [{6, 14, 6}] = 2.5, --- Cherries
+ [{14, 6, 6}] = 2.5, --- Cherries
+ [{6, 14, 14}] = 2.5, --- Cherries
+ [{14, 6, 14}] = 2.5, --- Cherries
+ [{14, 14, 6}] = 2.5, --- Cherries
+ [{14, 14, 14}] = 2.5, --- Cherries
+
+ [{3, 3, 3}] = 5.0, --- Melons
+ [{3, 3, 10}] = 5.0, --- Melons
+ [{3, 10, 3}] = 5.0, --- Melons
+ [{10, 3, 3}] = 5.0, --- Melons
+ [{3, 10, 10}] = 5.0, --- Melons
+ [{10, 3, 10}] = 5.0, --- Melons
+ [{10, 10, 3}] = 5.0, --- Melons
+ [{10, 10, 10}] = 5.0, --- Melons
+
+ [{7, 7, 7}] = 7.5, --- Bells
+ [{7, 7, 13}] = 7.5, --- Bells
+ [{7, 13, 7}] = 7.5, --- Bells
+ [{13, 7, 7}] = 7.5, --- Bells
+ [{7, 13, 13}] = 7.5, --- Bells
+ [{13, 7, 13}] = 7.5, --- Bells
+ [{13, 13, 7}] = 7.5, --- Bells
+ [{13, 13, 13}] = 7.5, --- Bells
+
+ [{5, 5, 5}] = 25.0, --- Jackpot
+}
+
+--- E.g. Diamond slot | Only one diamond will give 1.0x, 2 diamonds will give 3.5x, 3 will give 9.0x.
+SpecialReward = {
+ 1.0,
+ 3.5,
+ 9.0
+}
+
+UseCash = false
+UseBank = false
+UseItem = true
+ItemName = 'casino_redchip'
diff --git a/resources/[qb]/[qb_casino]/casino-slots/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-slots/fxmanifest.lua
new file mode 100644
index 0000000..cb7b052
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-slots/fxmanifest.lua
@@ -0,0 +1,13 @@
+fx_version 'cerulean'
+game 'gta5'
+
+author 'Disabled Coding'
+description 'A casino resource for which you do not have to sell a kidney for'
+version '1.0.0'
+repository 'https://github.com/Disabled-Coding/dc-casino'
+
+shared_script 'config.lua'
+client_script 'client.lua'
+server_script 'server.lua'
+
+lua54 'yes'
diff --git a/resources/[qb]/[qb_casino]/casino-slots/server.lua b/resources/[qb]/[qb_casino]/casino-slots/server.lua
new file mode 100644
index 0000000..bc103f2
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-slots/server.lua
@@ -0,0 +1,170 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+local UsedSlots = {}
+local Slots = {}
+
+local function table_matches(t1, t2)
+ local type1, type2 = type(t1), type(t2)
+ if type1 ~= type2 then return false end
+ if type1 ~= 'table' and type2 ~= 'table' then return t1 == t2 end
+
+ for k1,v1 in pairs(t1) do
+ local v2 = t2[k1]
+ if v2 == nil or not table_matches(v1,v2) then return false end
+ end
+
+ for k2,v2 in pairs(t2) do
+ local v1 = t1[k2]
+ if v1 == nil or not table_matches(v1,v2) then return false end
+ end
+ return true
+end
+
+local function LeaveSlot(source)
+ if not Slots[source] then return end
+ if DoesEntityExist(Slots[source].Reel1) then DeleteEntity(Slots[source].Reel1) end
+ if DoesEntityExist(Slots[source].Reel2) then DeleteEntity(Slots[source].Reel2) end
+ if DoesEntityExist(Slots[source].Reel3) then DeleteEntity(Slots[source].Reel3) end
+ UsedSlots[Slots[source].SlotNetID] = false
+ Slots[source] = {}
+end
+
+RegisterNetEvent('dc-casino:slots:server:enter', function(netID, ReelLocation1, ReelLocation2, ReelLocation3)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local PlayerCoords = GetEntityCoords(GetPlayerPed(src))
+ local SlotEntity = NetworkGetEntityFromNetworkId(netID)
+ local SlotModel = GetEntityModel(SlotEntity)
+ local SlotCoords = GetEntityCoords(SlotEntity)
+
+ if not SlotReferences[SlotModel] then return end
+ if #(PlayerCoords - SlotCoords) > 4 then return end
+ if #(SlotCoords - ReelLocation1) > 2 or #(SlotCoords - ReelLocation2) > 2 or #(SlotCoords - ReelLocation2) > 2 then return end
+ if UsedSlots[netID] then return end
+
+ UsedSlots[netID] = true
+ TriggerClientEvent('dc-casino:slots:client:enter', src)
+ SetTimeout(1000, function()
+ local ReelEntity1 = CreateObject(SlotReferences[SlotModel].reela, ReelLocation1, true, false, false)
+ local ReelEntity2 = CreateObject(SlotReferences[SlotModel].reela, ReelLocation2, true, false, false)
+ local ReelEntity3 = CreateObject(SlotReferences[SlotModel].reela, ReelLocation3, true, false, false)
+ while not DoesEntityExist(ReelEntity1) do Wait(0) end
+ while not DoesEntityExist(ReelEntity2) do Wait(0) end
+ while not DoesEntityExist(ReelEntity3) do Wait(0) end
+ Slots[src] = {
+ Slot = NetworkGetEntityFromNetworkId(netID),
+ SlotNetID = netID,
+ Reel1 = ReelEntity1,
+ Reel2 = ReelEntity2,
+ Reel3 = ReelEntity3,
+ ReelLoc1 = ReelLocation1,
+ ReelLoc2 = ReelLocation2,
+ ReelLoc3 = ReelLocation3,
+ }
+ FreezeEntityPosition(Slots[src].Reel1, true)
+ FreezeEntityPosition(Slots[src].Reel2, true)
+ FreezeEntityPosition(Slots[src].Reel3, true)
+ local SlotHeading = GetEntityHeading(SlotEntity)
+ SetEntityRotation(Slots[src].Reel1, 0.0, 0.0, SlotHeading, 2, 1)
+ SetEntityRotation(Slots[src].Reel2, 0.0, 0.0, SlotHeading, 2, 1)
+ SetEntityRotation(Slots[src].Reel3, 0.0, 0.0, SlotHeading, 2, 1)
+ -- TriggerEvent('qb-log:server:CreateLog', 'casino', 'Casino Slots', 'green', string.format("**%s** (CitizenID: %s | ID: %s) - Entered a slot | Slot NetID %s | Slot Locations %s | Reel Locations %s %s %s | Player Location %s | Slot Model %s",
+ -- GetPlayerName(src), Player.PlayerData.citizenid, src, netID, SlotCoords, ReelLocation1, ReelLocation2, ReelLocation3, PlayerCoords, SlotModel))
+ end)
+end)
+
+RegisterNetEvent('dc-casino:slots:server:spin', function(ChosenBetAmount)
+ local src = source
+ local SpinTime = math.random(4000, 6000)
+ local ReelRewards = {math.random(0, 15), math.random(0, 15), math.random(0, 15)}
+ local SlotHeading = GetEntityHeading(Slots[src].Slot)
+ local SlotModel = GetEntityModel(Slots[src].Slot)
+ local Player = QBCore.Functions.GetPlayer(src)
+
+ if not Slots[src] then return end
+ if not SlotReferences[SlotModel].betamounts[ChosenBetAmount] then return end
+ if UseCash and Player.Functions.RemoveMoney('cash', SlotReferences[SlotModel].betamounts[ChosenBetAmount], 'Casino Slot Spin')
+ or UseBank and Player.Functions.RemoveMoney('bank', SlotReferences[SlotModel].betamounts[ChosenBetAmount], 'Casino Slot Spin')
+ -- luacheck: ignore
+ or UseItem and Player.Functions.RemoveItem(ItemName, SlotReferences[SlotModel].betamounts[ChosenBetAmount]) then TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['casino_redchip'], "remove", ChosenBetAmount)
+
+ else TriggerClientEvent('QBCore:Notify', src, 'Nothing left to bet with', 'error') return end
+
+ for i = 1, #ReelRewards do
+ if SlotReferences[SlotModel].misschance > math.random(1, 100) then ReelRewards[i] = ReelRewards[i] + math.random(4, 6) / 10 end
+ end
+ local BlurryReel1 = CreateObject(SlotReferences[SlotModel].reelb, Slots[src].ReelLoc1, true, false, false)
+ local BlurryReel2 = CreateObject(SlotReferences[SlotModel].reelb, Slots[src].ReelLoc2, true, false, false)
+ local BlurryReel3 = CreateObject(SlotReferences[SlotModel].reelb, Slots[src].ReelLoc3, true, false, false)
+ while not DoesEntityExist(BlurryReel1) do Wait(0) end
+ while not DoesEntityExist(BlurryReel2) do Wait(0) end
+ while not DoesEntityExist(BlurryReel3) do Wait(0) end
+ FreezeEntityPosition(BlurryReel1, true)
+ FreezeEntityPosition(BlurryReel2, true)
+ FreezeEntityPosition(BlurryReel3, true)
+ SetEntityRotation(BlurryReel1, 0.0, 0.0, SlotHeading, 2, 1)
+ SetEntityRotation(BlurryReel2, 0.0, 0.0, SlotHeading, 2, 1)
+ SetEntityRotation(BlurryReel3, 0.0, 0.0, SlotHeading, 2, 1)
+ local RewardMultiplier = 0
+ for k, v in pairs(Rewards) do
+ if table_matches(k, ReelRewards) then
+ RewardMultiplier = v
+ break
+ end
+ end
+ if RewardMultiplier == 0 then
+ for i = 1, #ReelRewards do
+ if ReelRewards[i] == 4 or ReelRewards[i] == 11 or ReelRewards[i] == 15 then
+ RewardMultiplier = RewardMultiplier + 1
+ end
+ end
+ RewardMultiplier = SpecialReward[RewardMultiplier] or 0
+ end
+ TriggerClientEvent('dc-casino:slots:client:spinreels', src, SpinTime, ReelRewards, NetworkGetNetworkIdFromEntity(BlurryReel1), NetworkGetNetworkIdFromEntity(BlurryReel2), NetworkGetNetworkIdFromEntity(BlurryReel3), NetworkGetNetworkIdFromEntity(Slots[src].Reel1), NetworkGetNetworkIdFromEntity(Slots[src].Reel2), NetworkGetNetworkIdFromEntity(Slots[src].Reel3), RewardMultiplier)
+ SetTimeout(SpinTime, function()
+ local RewardAmount = SlotReferences[SlotModel].betamounts[ChosenBetAmount] * RewardMultiplier
+ -- TriggerEvent('qb-log:server:CreateLog', 'casino', 'Casino Slots', 'green', string.format("**%s** (CitizenID: %s | ID: %s) - Spinned a casino slot for %s and won %s",
+ -- GetPlayerName(src), Player.PlayerData.citizenid, src, SlotReferences[SlotModel].betamounts[ChosenBetAmount], RewardAmount))
+ if RewardMultiplier == 0 then return end
+ if UseCash and Player.Functions.AddMoney('cash', RewardAmount, 'Casino Slot Spin')
+ or UseBank and Player.Functions.AddMoney('bank', RewardAmount, 'Casino Slot Spin')
+ -- luacheck: ignore
+ or UseItem and Player.Functions.AddItem(ItemName, RewardAmount) then
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['casino_redchip'], "add", RewardAmount)
+ -- TriggerClientEvent('QBCore:Notify', src, 'You won '..tonumber(RewardAmount)..' chips!', 'success')
+ end
+ end)
+end)
+
+RegisterNetEvent('dc-casino:slots:server:leave', function()
+ LeaveSlot(source)
+end)
+
+AddEventHandler("playerDropped", function()
+ LeaveSlot(source)
+end)
+
+-- PerformHttpRequest('https://api.github.com/repos/Disabled-Coding/dc-casino/releases/latest', function(_, resultData, _)
+-- if not resultData then print('Failed to check for updates') return end
+-- local result = json.decode(resultData)
+-- if GetResourceMetadata(GetCurrentResourceName(), 'version') ~= result.tag_name then
+-- print('New version of '..GetCurrentResourceName()..' is available!')
+-- end
+-- end)
+
+local ItemList = {
+ ["casino_redchip"] = 1
+}
+QBCore.Functions.CreateCallback('doj:server:CasinoChipsAmount', function(source, cb)
+ local retval = 0
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.PlayerData.items ~= nil and next(Player.PlayerData.items) ~= nil then
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ retval = retval + (ItemList[Player.PlayerData.items[k].name] * Player.PlayerData.items[k].amount)
+ end
+ end
+ end
+ end
+ cb(retval)
+end)
diff --git a/resources/[qb]/[qb_casino]/casino-walls/client/ambient-peds.lua b/resources/[qb]/[qb_casino]/casino-walls/client/ambient-peds.lua
new file mode 100644
index 0000000..6596994
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/client/ambient-peds.lua
@@ -0,0 +1,944 @@
+CreateThread(function()
+ CasinoPeds()
+end)
+
+function setBlackjackDealerClothes(randomNumber,ped)
+ if randomNumber == 0 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 3, 0, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 1, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 1 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 2, 2, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 2 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 2, 1, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 3 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 2, 0, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 1, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 4 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 4, 2, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 5 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 4, 0, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 0, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 6 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 4, 1, 0)
+ SetPedComponentVariation(ped, 1, 1, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 1, 0, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 1, 0, 0)
+ elseif randomNumber == 7 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 1, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 1, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 0, 0, 0)
+ SetPedComponentVariation(ped, 7, 0, 0, 0)
+ SetPedComponentVariation(ped, 8, 0, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ elseif randomNumber == 8 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 1, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 1, 1, 0)
+ SetPedComponentVariation(ped, 3, 1, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 0, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ elseif randomNumber == 9 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 2, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 0, 0)
+ SetPedComponentVariation(ped, 3, 2, 3, 0)
+ SetPedComponentVariation(ped, 4, 0, 0, 0)
+ SetPedComponentVariation(ped, 6, 0, 0, 0)
+ SetPedComponentVariation(ped, 7, 0, 0, 0)
+ SetPedComponentVariation(ped, 8, 2, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ elseif randomNumber == 10 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 2, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 2, 1, 0)
+ SetPedComponentVariation(ped, 3, 3, 3, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 3, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ elseif randomNumber == 11 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 3, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 0, 0)
+ SetPedComponentVariation(ped, 3, 0, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 1, 0, 0)
+ SetPedComponentVariation(ped, 8, 0, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ SetPedPropIndex(ped, 1, 0, 0, false)
+ elseif randomNumber == 12 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 3, 1, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 3, 1, 0)
+ SetPedComponentVariation(ped, 3, 1, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 2, 0, 0)
+ SetPedComponentVariation(ped, 8, 1, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ elseif randomNumber == 13 then
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 0, 4, 0, 0)
+ SetPedComponentVariation(ped, 1, 0, 0, 0)
+ SetPedComponentVariation(ped, 2, 4, 0, 0)
+ SetPedComponentVariation(ped, 3, 2, 1, 0)
+ SetPedComponentVariation(ped, 4, 1, 0, 0)
+ SetPedComponentVariation(ped, 6, 1, 0, 0)
+ SetPedComponentVariation(ped, 7, 1, 0, 0)
+ SetPedComponentVariation(ped, 8, 2, 0, 0)
+ SetPedComponentVariation(ped, 10, 0, 0, 0)
+ SetPedComponentVariation(ped, 11, 0, 0, 0)
+ SetPedPropIndex(ped, 1, 0, 0, false)
+ end
+end
+
+
+
+function CasinoPeds()
+
+ setBlackjackDealerClothes(randomBlackShit,ped)
+
+ -- Employee
+ model = GetHashKey("U_F_M_CasinoCash_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model ,949.75, 33.422, 70.839, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 57.052 )
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+ -- Inside Track
+ model = GetHashKey("S_M_Y_Doorman_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 955.619, 70.179, 69.433, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 190.937)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+ -- Membership
+ model = GetHashKey("u_f_m_casinoshop_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model ,920.726, 45.883, 71.073, true)
+
+ SetPedDefaultComponentVariation(ped)
+ SetPedComponentVariation(ped, 2, 1, 0, 0)
+ SetPedComponentVariation(ped, 11, 2, 0, 0)
+
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 276.635)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+
+ -- ambient workers
+ --------------------------------------------------------------------------------------------------------------------------------------
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 947.994, 45.233, 70.638, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 220.199)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 998.848, 45.308, 68.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 43.086)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 973.283, 41.411, 70.233, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 184.428)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 996.982, 37.33, 69.233, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 45.32)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 989.222, 71.748, 69.233, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 161.745)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 974.901, 34.128, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 1.995)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 970.651, 65.43, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 192.896)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 920.48, 46.759, 71.073, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 277.117)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 933.011, 40.807, 80.089, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 54.913)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 929.086, 34.707, 80.089, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 328.4)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 949.615, 25.983, 70.834, true)
+ SetPedComponentVariation(ped, 8, 3, 3, 3)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 53.202)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_F_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 939.71, 47.066, 71.279, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 4164.51)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+ --------------------------------------------------------------------------------------------------------------------------------------
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 933.62, 41.631, 80.089, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 56.923)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 938.974, 27.776, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 13.513)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_WINDOW_SHOP_BROWSE", 0, true)
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 969.729, 57.35, 70.233, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 23.352)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 978.838, 69.432, 69.233, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 237.674)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 984.436, 36.494, 69.233, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 314.327)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 994.234, 65.098, 68.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 151.299)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("S_M_Y_Casino_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 929.79, 37.618, 71.274, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 35.262)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("s_m_y_valet_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 925.235, 50.921, 80.106, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 55.601)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_IMPATIENT", 0, true)
+
+ -- ==================================================================================================================--
+ -- ==================================================================================================================--locals-
+ -- ==================================================================================================================--
+ model = GetHashKey("a_m_m_paparazzi_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 949.985, 54.927, 70.433, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 172.611)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+
+ model = GetHashKey("a_f_y_tourist_02")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 943.266, 64.802, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 267.054)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_MOBILE", 0, true)
+
+ model = GetHashKey("a_f_y_vinewood_02")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 943.723, 65.612, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 173.907)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_HANG_OUT_STREET", 0, true)
+
+ model = GetHashKey("cs_tom")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 942.68, 38.882, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 154.872)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_WINDOW_SHOP_BROWSE", 0, true)
+
+ model = GetHashKey("cs_jimmyboston")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 942.057, 38.012, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 329.05)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_MOBILE_FILM_SHOCKING", 0, true)
+
+ model = GetHashKey("cs_carbuyer")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 929.239, 28.97, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 281.783)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_MOBILE_FILM_SHOCKING", 0, true)
+
+ model = GetHashKey("a_m_y_clubcust_03")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 928.8, 29.857, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 283.934)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_HANG_OUT_STREET", 0, true)
+
+ model = GetHashKey("cs_gurk")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 934.337, 37.499, 71.279, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 168.193)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_HANG_OUT_STREET", 0, true)
+
+ model = GetHashKey("cs_lazlow_2")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model ,935.38, 37.579, 71.279, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 180.215)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_m_y_clubcust_03")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model ,927.904, 41.925, 71.274, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 179.576)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+
+ model = GetHashKey("a_m_y_bevhills_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 953.208, 61.601, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 339.76)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_f_y_vinewood_04")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 953.94, 61.392, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 344.716)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+
+ model = GetHashKey("a_f_y_scdressy_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 955.158, 61.174, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 356.136)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_f_y_genhot_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 965.489, 72.251, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 196.752)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_m_m_malibu_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 964.468, 71.471, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 221.392)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_MOBILE", 0, true)
+
+ model = GetHashKey("a_f_y_vinewood_04")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 987.52, 57.652, 68.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 204.379)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("s_m_m_hairdress_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 986.732, 57.113, 68.866, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 222.62)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_MOBILE", 0, true)
+
+ model = GetHashKey("ig_taostranslator")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 982.362, 46.761, 69.238, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 0.99)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("u_f_m_miranda_02")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 969.109, 46.507, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 82.089)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_STAND_MOBILE", 0, true)
+
+ model = GetHashKey("cs_carbuyer")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 969.066, 47.366, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 83.4)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("cs_dale")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model ,968.666, 45.528, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 81.227)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+
+ model = GetHashKey("ig_taostranslator")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 961.332, 52.542, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped,203.484)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_m_y_hipster_02")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 988.817, 49.03, 68.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 352.551)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("u_f_m_miranda_02")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 989.748, 49.294, 68.832, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 6.127)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+
+ model = GetHashKey("a_f_y_scdressy_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 962.446, 52.816, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 207.774)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_m_m_prolhost_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 945.779, 22.762, 70.279, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 44.244)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_CHAIR", 0, true)
+
+ model = GetHashKey("a_f_y_scdressy_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 945.09, 21.745, 70.279, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 51.433)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_DECKCHAIR_DRINK", 0, true)
+
+ model = GetHashKey("a_f_y_bevhills_04")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 940.96, 18.807, 70.305, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 17.935)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_DECKCHAIR_DRINK", 0, true)
+
+ model = GetHashKey("a_m_m_stlat_02")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 941.913, 19.163, 70.288, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 18.65)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_CHAIR_FOOD", 0, true)
+
+ model = GetHashKey("a_f_y_scdressy_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 932.517, 18.882, 70.313, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 7.469)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_CHAIR_UPRIGHT", 0, true)
+
+ model = GetHashKey("a_f_y_bevhills_04")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 933.335, 19.048, 70.33, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 357.385)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_BENCH_DRINK_BEER", 0, true)
+
+ model = GetHashKey("a_m_m_malibu_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 934.378, 19.097, 70.339, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 357.293)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_DECKCHAIR_DRINK", 0, true)
+
+ model = GetHashKey("a_f_y_bevhills_04")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 937.486, 29.38, 70.537, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 202.034)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_BENCH_DRINK_BEER", 0, true)
+
+ model = GetHashKey("a_m_m_malibu_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 938.916, 29.585, 70.534, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 179.067)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_SEAT_BENCH_DRINK_BEER", 0, true)
+
+ model = GetHashKey("ig_taostranslator")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 935.392, 27.821, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 326.627)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_f_y_genhot_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 935.98, 28.242, 70.834, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped,233.585)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "PROP_HUMAN_STAND_IMPATIENT", 0, true)
+
+ model = GetHashKey("a_f_y_genhot_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 962.431, 51.656, 69.833, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 29.831)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+
+ model = GetHashKey("a_f_y_genhot_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 951.392, 36.326, 70.838, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 101.098)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_PARTYING", 0, true)
+
+ model = GetHashKey("a_f_y_genhot_01")
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+ ped = CreatePed(0, model , 950.274, 37.131, 70.838, true)
+ FreezeEntityPosition(ped, true)
+ SetEntityHeading(ped, 201.608)
+ SetEntityInvincible(ped, true)
+ SetBlockingOfNonTemporaryEvents(ped, true)
+ TaskStartScenarioInPlace(ped, "WORLD_HUMAN_SMOKING", 0, true)
+end
+
diff --git a/resources/[qb]/[qb_casino]/casino-walls/client/casino-addons.lua b/resources/[qb]/[qb_casino]/casino-walls/client/casino-addons.lua
new file mode 100644
index 0000000..d292432
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/client/casino-addons.lua
@@ -0,0 +1,166 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+RegisterNetEvent('qb-casino:client:openCasinoShop', function()
+ local ShopItems = {}
+ ShopItems.label = "The Diamond Casino & Resort Shop"
+ ShopItems.items = Config.CasinoShop
+ ShopItems.slots = #Config.CasinoShop
+ TriggerServerEvent("inventory:server:OpenInventory", "shop", "Vendingshop_", ShopItems)
+end)
+
+RegisterNetEvent('doj:casinoChipMenu', function()
+ TriggerEvent('drawtextui:HideUI')
+ exports['qb-menu']:openMenu({
+ {
+ header = "The Diamond Casino & Resort Chip Exchange",
+ isMenuHeader = true,
+ },
+ {
+ header = "Sell All Casino Chips",
+ txt = "Current Value: $"..Config.casinoChipPrice.." per chip",
+ params = {
+
+ event = "qb-casino:server:GoldSell",
+ isServer = true,
+ }
+ },
+ {
+ header = "< Return",
+ txt = "",
+ params = {
+ event = "doj:casinoMainMenu"
+ }
+ },
+ })
+end)
+
+CreateThread(function()
+ local CasinoShop = CircleZone:Create(vector3(948.591, 34.207, 71.839), 2.0, {
+ name="CasinoShop",
+ heading=160,
+ debugPoly=false,
+ useZ=true,
+ })
+ CasinoShop:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ text = 'The Diamond Casino & ResortCashier'
+ exports['qb-core']:DrawText(text)
+ exports['qb-target']:AddTargetModel(`U_F_M_CasinoCash_01`, {
+ options = {
+ {
+ event = "doj:casinoMainMenu",
+ icon = "fab fa-speakap",
+ label = "Speak with Casino Employee",
+ },
+ },
+ distance = 3.0
+ })
+ else
+ exports['qb-menu']:closeMenu()
+ exports["qb-core"]:HideText()
+ end
+ end)
+end)
+
+
+CreateThread(function()
+ local CasinoMembership = CircleZone:Create(vector3(920.726, 45.883, 71.073), 5.0, {
+ name="CasinoMembership",
+ heading=160,
+ debugPoly=false,
+ useZ=true,
+ })
+ CasinoMembership:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ text = 'The Diamond Casino & ResortFront Counter'
+ exports['qb-core']:DrawText(text)
+ exports['qb-target']:AddTargetModel(`u_f_m_casinoshop_01`, {
+ options = {
+ {
+ event = "doj:casinoMembershipMenu",
+ icon = "fab fa-speakap",
+ label = "Speak with Casino Employee",
+ },
+ },
+ distance = 3.0
+ })
+ else
+ exports['qb-menu']:closeMenu()
+ exports["qb-core"]:HideText()
+ end
+ end)
+end)
+
+
+
+RegisterNetEvent('doj:casinoMainMenu', function()
+ QBCore.Functions.TriggerCallback('doj:server:HasCasinoMembership', function(HasItem)
+ if HasItem then
+ -- exports["qb-core"]:HideText()
+ exports['qb-menu']:openMenu({
+ {
+ header = "The Diamond Casino & Resort",
+ isMenuHeader = true,
+ },
+ {
+ header = "Chip Exchange",
+ txt = "See current prices",
+ params = {
+ event = "doj:casinoChipMenu",
+ }
+ },
+ {
+ header = "Browse Shop",
+ txt = "See what we have to offer",
+ params = {
+ event = "qb-casino:client:openCasinoShop",
+ }
+ },
+ {
+ header = "Cancel",
+ txt = "",
+ params = {
+ event = ""
+ }
+ },
+ })
+ else
+ text = 'The Diamond Casino & ResortPlease visit the front desk!'
+ exports['qb-core']:DrawText(text)
+ end
+ end)
+end)
+
+
+RegisterNetEvent('doj:casinoMembershipMenu', function()
+ -- exports["qb-core"]:HideText()
+ exports['qb-menu']:openMenu({
+ {
+ header = "The Diamond Casino & Resort",
+ isMenuHeader = true,
+ },
+ {
+ header = "Purchase Casino Membership",
+ txt = "Price: $"..Config.casinoMemberPrice,
+ params = {
+ isServer = true,
+ event = "doj:server:purchaseMembership",
+ }
+ },
+ {
+ header = "Purchase V.I.P Membership",
+ txt = "Price: $"..Config.casinoVIPPrice,
+ params = {
+ isServer = true,
+ event = "doj:server:purchaseVIPMembership",
+ }
+ },
+ {
+ header = "Cancel",
+ txt = "",
+ params = {
+ event = ""
+ }
+ },
+ })
+end)
diff --git a/resources/[qb]/[qb_casino]/casino-walls/client/casino-interior.lua b/resources/[qb]/[qb_casino]/casino-walls/client/casino-interior.lua
new file mode 100644
index 0000000..9ec8724
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/client/casino-interior.lua
@@ -0,0 +1,215 @@
+
+local inCasino = false
+local videoWallRenderTarget = nil
+local showBigWin = false
+local spinningObject = nil
+local spinningCar = nil
+--
+-- Threads
+--
+
+function startCasinoThreads()
+ RequestStreamedTextureDict('Prop_Screen_Vinewood')
+ while not HasStreamedTextureDictLoaded('Prop_Screen_Vinewood') do
+ Wait(100)
+ end
+ RegisterNamedRendertarget('casinoscreen_01')
+ LinkNamedRendertarget(`vw_vwint01_video_overlay`)
+ videoWallRenderTarget = GetNamedRendertargetRenderId('casinoscreen_01')
+ CreateThread(function()
+ local lastUpdatedTvChannel = 0
+ while true do
+ Wait(0)
+ if not inCasino then
+ ReleaseNamedRendertarget('casinoscreen_01')
+ videoWallRenderTarget = nil
+ showBigWin = false
+ break
+ end
+ if videoWallRenderTarget then
+ local currentTime = GetGameTimer()
+ if showBigWin then
+ setVideoWallTvChannelWin()
+ lastUpdatedTvChannel = GetGameTimer() - 33666
+ showBigWin = false
+ else
+ if (currentTime - lastUpdatedTvChannel) >= 42666 then
+ setVideoWallTvChannel()
+ lastUpdatedTvChannel = currentTime
+ end
+ end
+ SetTextRenderId(videoWallRenderTarget)
+ SetScriptGfxDrawOrder(4)
+ SetScriptGfxDrawBehindPausemenu(true)
+ DrawInteractiveSprite('Prop_Screen_Vinewood', 'BG_Wall_Colour_4x4', 0.25, 0.5, 0.5, 1.0, 0.0, 255, 255, 255, 255)
+ DrawTvChannel(0.5, 0.5, 1.0, 1.0, 0.0, 255, 255, 255, 255)
+ SetTextRenderId(GetDefaultScriptRendertargetRenderId())
+ end
+ end
+ end)
+end
+
+function setVideoWallTvChannel()
+ SetTvChannelPlaylist(0, Config.AnimatedWallNormal, true)
+ SetTvAudioFrontend(true)
+ SetTvVolume(-100.0)
+ SetTvChannel(0)
+end
+
+function setVideoWallTvChannelWin()
+ SetTvChannelPlaylist(0, Config.AnimatedWallWin, true)
+ SetTvAudioFrontend(true)
+ SetTvVolume(-100.0)
+ SetTvChannel(-1)
+ SetTvChannel(0)
+end
+
+--
+-- Events
+--
+
+AddEventHandler("chCasinoWall:enteredCasino", function()
+ inCasino = true
+ if Config.SetAnimatedWalls then
+ startCasinoThreads()
+ end
+ if Config.SetShowCarOnDisplay then
+ spinMeRightRoundBaby()
+ end
+ if Config.PlayCasinoAmbientNoise then
+ playSomeBackgroundAudioBaby()
+ end
+end)
+
+AddEventHandler("chCasinoWall:exitedCasino", function()
+ inCasino = false
+end)
+
+RegisterNetEvent('chCasinoWall:bigWin')
+AddEventHandler('chCasinoWall:bigWin', function()
+ if not inCasino then
+ return
+ end
+ showBigWin = true
+end)
+
+
+function enterCasino()
+ InCasino = true
+ TriggerEvent("chCasinoWall:enteredCasino")
+ print("Entered Casino area")
+ if Config.SendWelcomeMail then
+ TriggerServerEvent('qb-phone:server:sendNewMail', {
+ sender = Config.WelcomeMailsender,
+ subject = Config.WelcomeMailsubject,
+ message = Config.WelcomeMailmessage,
+ button = {}
+ })
+ end
+end
+
+function exitCasino()
+ TriggerEvent("chCasinoWall:exitedCasino")
+ print("Exited Casino area")
+ InCasino = false
+ StopAudioScene("DLC_VW_Casino_General")
+ Wait(5000)
+ startCasinoThreads()
+end
+
+CreateThread(function()
+ local CasinoZone = CircleZone:Create(vector3(945.85, 41.58, -170.50), 250.0, {
+ name="CasinoZone",
+ heading=0.0,
+ debugPoly=false,
+ useZ=true,
+ })
+ CasinoZone:onPlayerInOut(function(inCasino)
+ if inCasino then
+ enterCasino()
+ else
+ exitCasino()
+ end
+ end)
+end)
+
+function spinMeRightRoundBaby()
+ CreateThread(function()
+ while inCasino do
+ if not spinningObject or spinningObject == 0 or not DoesEntityExist(spinningObject) then
+ spinningObject = GetClosestObjectOfType(935.432, 42.5611, 72.14, 10.0, -1561087446, 0, 0, 0)
+ drawCarForWins()
+ end
+ if spinningObject ~= nil and spinningObject ~= 0 then
+ local curHeading = GetEntityHeading(spinningObject)
+ local curHeadingCar = GetEntityHeading(spinningCar)
+ if curHeading >= 360 then
+ curHeading = 0.0
+ curHeadingCar = 0.0
+ elseif curHeading ~= curHeadingCar then
+ curHeadingCar = curHeading
+ end
+ SetEntityHeading(spinningObject, curHeading + 0.075)
+ SetEntityHeading(spinningCar, curHeadingCar + 0.075)
+ end
+ Wait(0)
+ end
+ spinningObject = nil
+ end)
+end
+
+function drawCarForWins()
+ if DoesEntityExist(spinningCar) then
+ DeleteEntity(spinningCar)
+ end
+ RequestModel(Config.VehicleOnDisplay)
+ while not HasModelLoaded(Config.VehicleOnDisplay) do
+ Wait(0)
+ end
+ SetModelAsNoLongerNeeded(Config.VehicleOnDisplay)
+ spinningCar = CreateVehicle(Config.VehicleOnDisplay, 935.432, 42.5611, 72.34, 0.0, 0, 0)
+ Wait(0)
+ SetVehicleDirtLevel(spinningCar, 0.0)
+ SetVehicleOnGroundProperly(spinningCar)
+ Wait(0)
+ FreezeEntityPosition(spinningCar, 1)
+end
+
+function playSomeBackgroundAudioBaby()
+ CreateThread(function()
+ local function audioBanks()
+ while not RequestScriptAudioBank("DLC_VINEWOOD/CASINO_GENERAL", false, -1) do
+ Wait(0)
+ end
+ while not RequestScriptAudioBank("DLC_VINEWOOD/CASINO_SLOT_MACHINES_01", false, -1) do
+ Wait(0)
+ end
+ while not RequestScriptAudioBank("DLC_VINEWOOD/CASINO_SLOT_MACHINES_02", false, -1) do
+ Wait(0)
+ end
+ while not RequestScriptAudioBank("DLC_VINEWOOD/CASINO_SLOT_MACHINES_03", false, -1) do
+ Wait(0)
+ end
+ end
+ audioBanks()
+ while inCasino do
+ if not IsStreamPlaying() and LoadStream("casino_walla", "DLC_VW_Casino_Interior_Sounds") then
+ PlayStreamFromPosition(945.85, 41.58, 75.82)
+ end
+ if IsStreamPlaying() and not IsAudioSceneActive("DLC_VW_Casino_General") then
+ StartAudioScene("DLC_VW_Casino_General")
+ end
+ Wait(1000)
+ end
+ if IsStreamPlaying() then
+ StopStream()
+ end
+ if IsAudioSceneActive("DLC_VW_Casino_General") then
+ StopAudioScene("DLC_VW_Casino_General")
+ end
+ end)
+end
+
+
+
+
diff --git a/resources/[qb]/[qb_casino]/casino-walls/client/casino-teleports.lua b/resources/[qb]/[qb_casino]/casino-walls/client/casino-teleports.lua
new file mode 100644
index 0000000..b56b3a9
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/client/casino-teleports.lua
@@ -0,0 +1,99 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+CreateThread(function()
+ local TeleportUpZone = CircleZone:Create(vector3(930.251, 34.324, 81.089), 1.5, {
+ name="TeleportUp",
+ heading=328.0,
+ debugPoly=false,
+ useZ=true,
+ })
+ TeleportUpZone:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ -- exports['qb-core']:DrawText('The Diamond Casino & ResortElevators')
+ QBCore.Functions.TriggerCallback('doj:server:HasCasinoMembership', function(HasItem)
+ if HasItem then
+ TriggerEvent("doj:casinoTeleportUp")
+ else
+ exports['qb-core']:DrawText('The Diamond Casino & ResortNOT A MEMBERPlease visit the front desk!')
+ end
+ end)
+ else
+ exports['qb-menu']:closeMenu()
+ exports["qb-core"]:HideText()
+ end
+ end)
+end)
+
+CreateThread(function()
+ local TeleportDownZone = CircleZone:Create(vector3(964.737, 58.743, 112.553), 1.5, {
+ name="TeleportDown",
+ heading=328.0,
+ debugPoly=false,
+ useZ=true,
+ })
+ TeleportDownZone:onPlayerInOut(function(isPointInside)
+ if isPointInside then
+ TriggerEvent("doj:casinoTeleportDown")
+ else
+ exports['qb-menu']:closeMenu()
+ end
+ end)
+end)
+
+RegisterNetEvent('doj:casinoTeleports', function(args)
+ local args = tonumber(args)
+ local ped = PlayerPedId()
+ if args == 1 then
+ SetEntityCoords(ped, 965.0619, 58.51287, 112.553, false, false, false, true)
+ else
+ SetEntityCoords(ped, 930.0716, 33.86854, 81.09772, false, false, false, true)
+ end
+end)
+
+RegisterNetEvent('doj:casinoTeleportUp', function()
+ exports['qb-menu']:showHeader({
+ {
+ header = "The Diamond Casino & Resort Elevators",
+ isMenuHeader = true,
+ },
+ {
+ header = "Elevator Up",
+ txt = "Roof access",
+ params = {
+ event = "doj:casinoTeleports",
+ args = 1,
+ }
+ },
+ {
+ header = "return",
+ txt = "",
+ params = {
+ event = "doj:casinoTeleportUp"
+ }
+ },
+ })
+end)
+
+RegisterNetEvent('doj:casinoTeleportDown', function()
+ exports['qb-menu']:showHeader({
+ {
+ header = "The Diamond Casino & Resort Elevators",
+ isMenuHeader = true,
+ },
+ {
+ header = "Elevator Down",
+ txt = "Main Lobby",
+ params = {
+ event = "doj:casinoTeleports",
+ args = 2,
+ }
+ },
+ {
+ header = "return",
+ txt = "",
+ params = {
+ event = "doj:casinoTeleportDown"
+ }
+ },
+ })
+end)
diff --git a/resources/[qb]/[qb_casino]/casino-walls/config.lua b/resources/[qb]/[qb_casino]/casino-walls/config.lua
new file mode 100644
index 0000000..066a493
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/config.lua
@@ -0,0 +1,32 @@
+Config = {}
+
+Config.PlayCasinoAmbientNoise = true
+Config.SetShowCarOnDisplay = true
+Config.VehicleOnDisplay = `crownbp`
+
+
+Config.SetAnimatedWalls = true
+Config.AnimatedWallNormal = 'CASINO_DIA_PL'
+Config.AnimatedWallWin = 'CASINO_WIN_PL'
+-- WALLS
+-- CASINO_DIA_PL - Falling Diamonds
+-- CASINO_HLW_PL - Falling Skulls
+-- CASINO_SNWFLK_PL - Falling Snowflakes
+-- CASINO_WIN_PL - Falling Confetti
+
+Config.SendWelcomeMail = false -- Sends a email to players phone on entering casino
+Config.WelcomeMailsender = "The Diamond Casino & Resort"
+Config.WelcomeMailsubject ="Welcome!"
+Config.WelcomeMailmessage = "Welcome to The Diamond Casino & Resort, We are Open 24/7 & only accept Electronic Transactions"
+
+Config.payment = "bank" -- or "cash" -- Payment player will recieve by selling casino chips
+
+Config.casinoChipPrice = 100
+Config.casinoMemberPrice = 500
+Config.casinoVIPPrice = 500
+
+Config.CasinoShop = {
+ [1] = { name = "casino_redchip", price = 100, amount = 1000, info = {}, type = "item", slot = 1 },
+ -- [2] = { name = "casino_member", price = 500, amount = 50, info = {}, type = "item", slot = 2 },
+ -- [3] = { name = "casino_vip", price = 750, amount = 50, info = {}, type = "item", slot = 3 }
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/casino-walls/fxmanifest.lua b/resources/[qb]/[qb_casino]/casino-walls/fxmanifest.lua
new file mode 100644
index 0000000..0f87c4a
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/fxmanifest.lua
@@ -0,0 +1,21 @@
+fx_version 'cerulean'
+games { 'gta5' }
+
+
+shared_scripts {
+ 'config.lua',
+}
+
+
+client_scripts{
+ '@PolyZone/client.lua',
+ '@PolyZone/BoxZone.lua',
+ '@PolyZone/EntityZone.lua',
+ '@PolyZone/CircleZone.lua',
+ '@PolyZone/ComboZone.lua',
+ 'client/*.lua'
+}
+
+server_scripts{
+ 'server/*.lua'
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_casino]/casino-walls/server/casino.lua b/resources/[qb]/[qb_casino]/casino-walls/server/casino.lua
new file mode 100644
index 0000000..dc522ef
--- /dev/null
+++ b/resources/[qb]/[qb_casino]/casino-walls/server/casino.lua
@@ -0,0 +1,145 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+local quantity = 0
+local ItemList = {
+ ["casino_redchip"] = 1,
+}
+
+RegisterServerEvent("qb-casino:server:GoldSell")
+AddEventHandler("qb-casino:server:GoldSell", function()
+ local src = source
+ local price = Config.casinoChipPrice
+ local Player = QBCore.Functions.GetPlayer(src)
+ local xItem = Player.Functions.GetItemByName("casino_redchip")
+ if xItem ~= nil then
+ local quantity = 0
+ for k, v in pairs(Player.PlayerData.items) do
+ if Player.PlayerData.items[k] ~= nil then
+ if ItemList[Player.PlayerData.items[k].name] ~= nil then
+ quantity = quantity + Player.PlayerData.items[k].amount
+ Player.Functions.RemoveItem(Player.PlayerData.items[k].name, Player.PlayerData.items[k].amount, k)
+ end
+ end
+ end
+ price = price * quantity
+ Player.Functions.AddMoney(Config.payment, price, "sold-casino-chips")
+ TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items['casino_redchip'], "remove", quantity)
+ TriggerClientEvent('QBCore:Notify', src, "You sold "..quantity.." Gold chips for $"..price)
+ TriggerEvent('qb-log:server:CreateLog', 'guedesteste', 'Dinheiro Venda | '..Player.PlayerData.name, 'default', quantity.." fichas de ouro por "..price.."€")
+ TriggerClientEvent("doj:casinoChipMenu", src)
+ quantity = 0
+ else
+ TriggerClientEvent('QBCore:Notify', src, "You dont have any gold casino chips...", "error")
+ TriggerClientEvent("doj:casinoChipMenu", src)
+ end
+end)
+
+
+RegisterNetEvent("doj:server:purchaseMembership", function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local MembershipCheck = Player.Functions.GetItemByName('casino_member')
+ if MembershipCheck ~= nil then
+ TriggerClientEvent('doj:casinoMembershipMenu', src)
+ TriggerClientEvent('QBCore:Notify', src, 'You already have a Membership', 'error')
+ else
+ if Player.Functions.AddItem('casino_member', 1, false, info) then
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['casino_member'], "add", 1)
+ TriggerClientEvent('doj:casinoMembershipMenu', src)
+
+ end
+ end
+end)
+
+RegisterNetEvent("doj:server:purchaseVIPMembership", function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local VIPMembershipCheck = Player.Functions.GetItemByName('casino_vip')
+ if VIPMembershipCheck ~= nil then
+ TriggerClientEvent('doj:casinoMembershipMenu', src)
+ TriggerClientEvent('QBCore:Notify', src, 'You already have a Membership', 'error')
+ else
+ if Player.Functions.AddItem('casino_vip', 1, false, info) then
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items['casino_vip'], "add", 1)
+ TriggerClientEvent('doj:casinoMembershipMenu', src)
+
+ end
+ end
+end)
+
+
+QBCore.Functions.CreateCallback('doj:server:HasCasinoMembership', function(source, cb)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local Item = Player.Functions.GetItemByName("casino_member")
+
+ if Item ~= nil then
+ cb(true)
+ else
+ cb(false)
+ end
+end)
+
+QBCore.Functions.CreateCallback('doj:server:HasVIPMembership', function(source, cb)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local Item = Player.Functions.GetItemByName("casino_vip")
+
+ if Item ~= nil then
+ cb(true)
+ else
+ cb(false)
+ end
+end)
+
+
+
+
+
+-- RegisterNetEvent("doj:server:validateMembership")
+-- AddEventHandler("doj:server:validateMembership", function(args)
+-- local src = source
+-- local Player = QBCore.Functions.GetPlayer(src)
+-- local args = tonumber(args)
+-- if args == 1 then
+-- if Player.Functions.GetItemByName("casino_member") then
+-- Player.Functions.RemoveItem("casino_member", 1)
+-- local info = {
+-- owner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname,
+-- }
+-- Player.Functions.AddItem("casino_member_validated", 1, false, info)
+-- TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["casino_member_validated"], "add", 1)
+-- TriggerClientEvent('QBCore:Notify', src, "Membership has been validated", "success")
+-- else
+-- TriggerClientEvent('QBCore:Notify', src, "You need to buy a Casino Membership first", "error")
+-- end
+-- else
+-- if Player.Functions.GetItemByName("casino_vip") then
+-- Player.Functions.RemoveItem("casino_vip", 1)
+-- local info = {
+-- owner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname,
+-- }
+-- Player.Functions.AddItem("casino_vip_validated", 1, false, info)
+-- TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["casino_vip_validated"], "add", 1)
+-- TriggerClientEvent('QBCore:Notify', src, "Membership has been validated", "success")
+-- else
+-- TriggerClientEvent('QBCore:Notify', src, "You need to buy a V.I.P Membership first", "error")
+-- end
+-- end
+-- end)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/[qb]/[qb_core]/qb-crypto/LICENSE b/resources/[qb]/[qb_core]/qb-crypto/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/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/[qb]/[qb_core]/qb-crypto/README.md b/resources/[qb]/[qb_core]/qb-crypto/README.md
new file mode 100644
index 0000000..aefb551
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/README.md
@@ -0,0 +1,23 @@
+# qb-crypto
+Crypto Currency For QB-Core
+
+# Dependency
+https://github.com/qbcore-framework/mhacking
+
+# License
+
+ QBCore Framework
+ Copyright (C) 2021 Joshua Eger
+
+ 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
diff --git a/resources/[qb]/[qb_core]/qb-crypto/client/main.lua b/resources/[qb]/[qb_core]/qb-crypto/client/main.lua
new file mode 100644
index 0000000..caa6002
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/client/main.lua
@@ -0,0 +1,130 @@
+-- Variables
+local QBCore = exports['qb-core']:GetCoreObject()
+local requiredItemsShowed = false
+local requiredItems = {[1] = {name = QBCore.Shared.Items["cryptostick"]["name"], image = QBCore.Shared.Items["cryptostick"]["image"]}}
+
+-- Functions
+
+local function DrawText3Ds(coords, text)
+ SetTextScale(0.35, 0.35)
+ SetTextFont(4)
+ SetTextProportional(1)
+ SetTextColour(255, 255, 255, 215)
+ SetTextEntry("STRING")
+ SetTextCentre(true)
+ AddTextComponentString(text)
+ SetDrawOrigin(coords.x, coords.y, coords.z, 0)
+ DrawText(0.0, 0.0)
+ local factor = (string.len(text)) / 370
+ DrawRect(0.0, 0.0+0.0125, 0.017+ factor, 0.03, 0, 0, 0, 75)
+ ClearDrawOrigin()
+end
+
+local function ExchangeSuccess()
+ TriggerServerEvent('qb-crypto:server:ExchangeSuccess', math.random(1, 10))
+end
+
+local function ExchangeFail()
+ local Odd = 5
+ local RemoveChance = math.random(1, Odd)
+ local LosingNumber = math.random(1, Odd)
+ if RemoveChance == LosingNumber then
+ TriggerServerEvent('qb-crypto:server:ExchangeFail')
+ TriggerServerEvent('qb-crypto:server:SyncReboot')
+ end
+end
+
+local function SystemCrashCooldown()
+ CreateThread(function()
+ while Crypto.Exchange.RebootInfo.state do
+ if (Crypto.Exchange.RebootInfo.percentage + 1) <= 100 then
+ Crypto.Exchange.RebootInfo.percentage = Crypto.Exchange.RebootInfo.percentage + 1
+ TriggerServerEvent('qb-crypto:server:Rebooting', true, Crypto.Exchange.RebootInfo.percentage)
+ else
+ Crypto.Exchange.RebootInfo.percentage = 0
+ Crypto.Exchange.RebootInfo.state = false
+ TriggerServerEvent('qb-crypto:server:Rebooting', false, 0)
+ end
+ Wait(1200)
+ end
+ end)
+end
+
+local function HackingSuccess(success)
+ if success then
+ TriggerEvent('mhacking:hide')
+ ExchangeSuccess()
+ else
+ TriggerEvent('mhacking:hide')
+ ExchangeFail()
+ end
+end
+
+CreateThread(function()
+ while true do
+ local sleep = 5000
+ if LocalPlayer.state.isLoggedIn then
+ local ped = PlayerPedId()
+ local pos = GetEntityCoords(ped)
+ local dist = #(pos - Crypto.Exchange.coords)
+ if dist < 15 then
+ sleep = 5
+ if dist < 1.5 then
+ if not Crypto.Exchange.RebootInfo.state then
+ DrawText3Ds(Crypto.Exchange.coords, Lang:t('text.enter_usb'))
+ if not requiredItemsShowed then
+ requiredItemsShowed = true
+ TriggerEvent('inventory:client:requiredItems', requiredItems, true)
+ end
+
+ if IsControlJustPressed(0, 38) then
+ QBCore.Functions.TriggerCallback('qb-crypto:server:HasSticky', function(HasItem)
+ if HasItem then
+ TriggerEvent("mhacking:show")
+ TriggerEvent("mhacking:start", math.random(4, 6), 45, HackingSuccess)
+ else
+ QBCore.Functions.Notify(Lang:t('error.you_dont_have_a_cryptostick'), 'error')
+ end
+ end)
+ end
+ else
+ DrawText3Ds(Crypto.Exchange.coords, Lang:t('text.system_is_rebooting', {rebootInfoPercentage = Crypto.Exchange.RebootInfo.percentage}) )
+ end
+ else
+ if requiredItemsShowed then
+ requiredItemsShowed = false
+ TriggerEvent('inventory:client:requiredItems', requiredItems, false)
+ end
+ end
+ end
+ end
+ Wait(sleep)
+ end
+end)
+
+-- Events
+
+RegisterNetEvent('qb-crypto:client:SyncReboot', function()
+ Crypto.Exchange.RebootInfo.state = true
+ SystemCrashCooldown()
+end)
+
+RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
+ TriggerServerEvent('qb-crypto:server:FetchWorth')
+ TriggerServerEvent('qb-crypto:server:GetRebootState')
+end)
+
+RegisterNetEvent('qb-crypto:client:UpdateCryptoWorth', function(crypto, amount, history)
+ Crypto.Worth[crypto] = amount
+ if history ~= nil then
+ Crypto.History[crypto] = history
+ end
+end)
+
+RegisterNetEvent('qb-crypto:client:GetRebootState', function(RebootInfo)
+ if RebootInfo.state then
+ Crypto.Exchange.RebootInfo.state = RebootInfo.state
+ Crypto.Exchange.RebootInfo.percentage = RebootInfo.percentage
+ SystemCrashCooldown()
+ end
+end)
diff --git a/resources/[qb]/[qb_core]/qb-crypto/config.lua b/resources/[qb]/[qb_core]/qb-crypto/config.lua
new file mode 100644
index 0000000..4ae4431
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/config.lua
@@ -0,0 +1,55 @@
+Crypto = {
+ Lower = 500,
+ Upper = 5000,
+ History = {
+ ["qbit"] = {}
+ },
+
+ Worth = {
+ ["qbit"] = 1000
+ },
+
+ Labels = {
+ ["qbit"] = "Qbit"
+ },
+
+ Exchange = {
+ coords = vector3(1276.21, -1709.88, 54.57),
+ RebootInfo = {
+ state = false,
+ percentage = 0
+ },
+ },
+
+ -- For auto updating the value of qbit
+ Coin = 'qbit',
+ RefreshTimer = 10, -- In minutes, so every 10 minutes.
+
+ -- Crashes or luck
+ ChanceOfCrashOrLuck = 2, -- This is in % (1-100)
+ Crash = {20,80}, -- Min / Max
+ Luck = {20,45}, -- Min / Max
+
+ -- If not not Chance of crash or luck, then this shit
+ ChanceOfDown = 30, -- If out of 100 hits less or equal to
+ ChanceOfUp = 60, -- If out of 100 is greater or equal to
+ CasualDown = {1,10}, -- Min / Max (If it goes down)
+ CasualUp = {1,10}, -- Min / Max (If it goes up)
+}
+
+
+
+
+Ticker = {
+ Enabled = false, -- Decide whether the real life price ticker should be enabled or not :)
+ coin = 'BTC', --- The coin, please make sure you find the actual name, for example: Bitcoin vs BTC, BTC would be correct
+ currency = 'DKK', -- For example USD, NOK, SEK, EUR, CAD and more here https://www.countries-ofthe-world.com/world-currencies.html
+ tick_time = 2, --- Minutes (Minimum is 2 minutes) 20,160 Requests a month, Its recommended to get the free API key so the crypto script doesnt switch on and off if ratelimit is encountered
+ Api_key = '2c7b4c7ce20a31818c81d9168be47503b756951e42dec288ae4679acc6f6c6d0', -- If you decide to get an api key for the API (https://min-api.cryptocompare.com/pricing) The free plan should be more than enough for 1 Fivem server
+ --- Error handle stuff, for more user friendly and readable errors, Don't touch.
+ Error_handle = {
+ ['fsym is a required param.'] = 'Config error: Invalid / Missing coin name',
+ ['tsyms is a required param.'] = 'Config error: Invalid / Missing currency',
+ ['cccagg_or_exchange'] = 'Config error: Invalid currency / coin combination', -- For some reason api throws this error if either coin or currency is invalid
+ },
+}
diff --git a/resources/[qb]/[qb_core]/qb-crypto/fxmanifest.lua b/resources/[qb]/[qb_core]/qb-crypto/fxmanifest.lua
new file mode 100644
index 0000000..2bd2801
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/fxmanifest.lua
@@ -0,0 +1,20 @@
+fx_version 'cerulean'
+game 'gta5'
+
+description 'QB-Crypto'
+version '1.2.0'
+
+shared_scripts {
+ '@qb-core/shared/locale.lua',
+ 'locales/da.lua',
+ 'config.lua'
+}
+server_scripts {
+ '@oxmysql/lib/MySQL.lua',
+ 'server/main.lua'
+}
+client_script 'client/main.lua'
+
+dependency 'mhacking'
+
+lua54 'yes'
diff --git a/resources/[qb]/[qb_core]/qb-crypto/locales/da.lua b/resources/[qb]/[qb_core]/qb-crypto/locales/da.lua
new file mode 100644
index 0000000..36765a9
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/locales/da.lua
@@ -0,0 +1,33 @@
+local Translations = {
+ error = {
+ you_dont_have_a_cryptostick = 'Du har ikke en cryptostic',
+ one_bus_active = 'Du kan kun have en BUS aktiv ad gangen',
+ drop_off_passengers = 'Aflever passagererne, før du stopper med at arbejde',
+ cryptostick_malfunctioned = 'Cryptostick fungerede ikke korrekt'
+ },
+ success = {
+ you_have_exchanged_your_cryptostick_for = 'Du byttede din cryptostick for: %{amount} QBit(s)'
+ },
+ credit = {
+ there_are_amount_credited = 'Der er %{amount} Qbit(s) krediteret!',
+ you_have_qbit_purchased = 'Du har købt %{dataCoins} Qbit(s)!'
+ },
+ depreciation = {
+ you_have_sold = 'Du har solgt %{dataCoins} Qbit(s)!'
+ },
+ text = {
+ enter_usb = '[E] - Indsæt USB',
+ system_is_rebooting = 'System genstarter - %{rebootInfoPercentage} %',
+ you_have_not_given_a_new_value = 'Du har ikke angivet en ny værdi.. Nuværrende værdi: %{crypto}',
+ this_crypto_does_not_exist = 'Denne Crypto findes ikke. Tilgængelig: Qbit',
+ you_have_not_provided_crypto_available_qbit = 'Du har ikke angivet Crypto. Tilgængelig: Qbit',
+ the_qbit_has_a_value_of = 'QBIT har en værdi af: %{crypto}',
+ you_have_with_a_value_of = 'Du har %{playerPlayerDataMoneyCrypto} QBit, til en værdi af %{mypocket},-'
+ }
+}
+
+Lang = Locale:new({
+ phrases = Translations,
+ warnOnMissing = true,
+ fallbackLang = Lang,
+})
diff --git a/resources/[qb]/[qb_core]/qb-crypto/qb-crypto.sql b/resources/[qb]/[qb_core]/qb-crypto/qb-crypto.sql
new file mode 100644
index 0000000..acff1df
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/qb-crypto.sql
@@ -0,0 +1,8 @@
+CREATE TABLE IF NOT EXISTS `crypto` (
+ `crypto` varchar(50) NOT NULL DEFAULT 'qbit',
+ `worth` int(11) NOT NULL DEFAULT 0,
+ `history` text DEFAULT NULL,
+ PRIMARY KEY (`crypto`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+INSERT INTO `crypto` VALUES ('qbit', 1000, '[{"NewWorth":1000,"PreviousWorth":1000}]');
diff --git a/resources/[qb]/[qb_core]/qb-crypto/server/main.lua b/resources/[qb]/[qb_core]/qb-crypto/server/main.lua
new file mode 100644
index 0000000..a741777
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-crypto/server/main.lua
@@ -0,0 +1,371 @@
+-- Variables
+local coin = Crypto.Coin
+local QBCore = exports['qb-core']:GetCoreObject()
+local bannedCharacters = {'%','$',';'}
+
+-- Function
+local function RefreshCrypto()
+ local result = MySQL.query.await('SELECT * FROM crypto WHERE crypto = ?', { coin })
+ if result ~= nil and result[1] ~= nil then
+ Crypto.Worth[coin] = result[1].worth
+ if result[1].history ~= nil then
+ Crypto.History[coin] = json.decode(result[1].history)
+ TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, coin, result[1].worth, json.decode(result[1].history))
+ else
+ TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, coin, result[1].worth, nil)
+ end
+ end
+end
+
+local function ErrorHandle(error)
+ for k, v in pairs(Ticker.Error_handle) do
+ if string.match(error, k) then
+ return v
+ end
+ end
+ return false
+end
+
+local function GetTickerPrice() -- Touch = no help
+ local ticker_promise = promise.new()
+ PerformHttpRequest("https://min-api.cryptocompare.com/data/price?fsym=" .. Ticker.coin .. "&tsyms=" .. Ticker.currency .. '&api_key=' .. Ticker.Api_key, function(Error, Result, _)
+ local result_obj = json.decode(Result)
+ if not result_obj['Response'] then
+ local this_resolve = {error = Error, response_data = result_obj[string.upper(Ticker.currency)]}
+ ticker_promise:resolve(this_resolve) --- Could resolve Error aswell for more accurate Error messages? Solved in else
+ else
+ local this_resolve = {error = result_obj['Message']}
+ ticker_promise:resolve(this_resolve)
+ end
+ end, 'GET')
+ Citizen.Await(ticker_promise)
+ if type(ticker_promise.value.error) ~= 'number' then
+ local get_user_friendly_error = ErrorHandle(ticker_promise.value.error)
+ if get_user_friendly_error then
+ return get_user_friendly_error
+ else
+ return '\27[31m Unexpected error \27[0m' --- Raised an error which we did not expect, script should be capable of sticking with last recorded price and shutting down the sync logic
+ end
+ else
+ return ticker_promise.value.response_data
+ end
+end
+
+local function HandlePriceChance()
+ local currentValue = Crypto.Worth[coin]
+ local prevValue = Crypto.Worth[coin]
+ local trend = math.random(0,100)
+ local event = math.random(0,100)
+ local chance = event - Crypto.ChanceOfCrashOrLuck
+
+ if event > chance then
+ if trend <= Crypto.ChanceOfDown then
+ currentValue = currentValue - math.random(Crypto.CasualDown[1], Crypto.CasualDown[2])
+ elseif trend >= Crypto.ChanceOfUp then
+ currentValue = currentValue + math.random(Crypto.CasualUp[1], Crypto.CasualUp[2])
+ end
+ else
+ if math.random(0, 1) == 1 then
+ currentValue = currentValue + math.random(Crypto.Luck[1], Crypto.Luck[2])
+ else
+ currentValue = currentValue - math.random(Crypto.Crash[1], Crypto.Crash[2])
+ end
+ end
+
+ if currentValue <= Crypto.Lower then
+ currentValue = Crypto.Lower
+ elseif currentValue >= Crypto.Upper then
+ currentValue = Crypto.Upper
+ end
+
+ if Crypto.History[coin][4] then
+ -- Shift array index 1 to 3
+ for k=3,1,-1 do
+ Crypto.History[coin][k] = Crypto.History[coin][k+1]
+ end
+ -- Assign array index 4 to the latest result
+ Crypto.History[coin][4] = {PreviousWorth = prevValue, NewWorth = currentValue}
+ else
+ Crypto.History[coin][#Crypto.History[coin] + 1] = {PreviousWorth = prevValue, NewWorth = currentValue}
+ end
+
+ Crypto.Worth[coin] = currentValue
+
+ local history = json.encode(Crypto.History[coin])
+ local props = {
+ ['worth'] = currentValue,
+ ['history'] = history,
+ ['crypto'] = coin
+ }
+ MySQL.update(
+ 'UPDATE crypto set worth = :worth, history = :history where crypto = :crypto',
+ props,
+ function(affectedRows)
+ if affectedRows < 1 then
+ print("Crypto not found, inserting new record for " .. coin)
+ MySQL.insert('INSERT INTO crypto (crypto, worth, history) VALUES (:crypto, :worth, :history)', props)
+ end
+ RefreshCrypto()
+ end
+ )
+end
+
+-- Commands
+
+QBCore.Commands.Add("setcryptoworth", "Sæt crypto værdi", {{name="crypto", help="navn på crypto"}, {name="Værdi", help="Den nye værdi"}}, false, function(source, args)
+ local src = source
+ local crypto = tostring(args[1])
+
+ if crypto ~= nil then
+ if Crypto.Worth[crypto] ~= nil then
+ local NewWorth = math.ceil(tonumber(args[2]))
+
+ if NewWorth ~= nil then
+ local PercentageChange = math.ceil(((NewWorth - Crypto.Worth[crypto]) / Crypto.Worth[crypto]) * 100)
+ local ChangeLabel = "+"
+
+ if PercentageChange < 0 then
+ ChangeLabel = "-"
+ PercentageChange = (PercentageChange * -1)
+ end
+
+ if Crypto.Worth[crypto] == 0 then
+ PercentageChange = 0
+ ChangeLabel = ""
+ end
+
+ Crypto.History[crypto][#Crypto.History[crypto]+1] = {
+ PreviousWorth = Crypto.Worth[crypto],
+ NewWorth = NewWorth
+ }
+
+ TriggerClientEvent('QBCore:Notify', src, "Du ændrede værdien af "..Crypto.Labels[crypto].." fra "..Crypto.Worth[crypto]..",- til "..NewWorth..",- ("..ChangeLabel.." "..PercentageChange.."%)")
+ Crypto.Worth[crypto] = NewWorth
+ TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, crypto, NewWorth)
+ --Update crypto.worth
+ MySQL.update('UPDATE crypto set worth = :worth where crypto = :crypto', {
+ ['worth'] = NewWorth,
+ ['crypto'] = crypto
+ })
+ else
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('text.you_have_not_given_a_new_value', {crypto = Crypto.Worth[crypto]}))
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('text.this_crypto_does_not_exist'))
+ end
+ else
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('text.you_have_not_provided_crypto_available_qbit'))
+ end
+end, "admin")
+
+QBCore.Commands.Add("checkcryptoworth", "", {}, false, function(source)
+ local src = source
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('text.the_qbit_has_a_value_of', {crypto = Crypto.Worth["qbit"]}))
+end)
+
+QBCore.Commands.Add("crypto", "", {}, false, function(source)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local MyPocket = math.ceil(Player.PlayerData.money.crypto * Crypto.Worth["qbit"])
+
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('text.you_have_with_a_value_of',{playerPlayerDataMoneyCrypto = Player.PlayerData.money.crypto,mypocket = MyPocket}))
+end)
+
+-- Events
+
+RegisterServerEvent('qb-crypto:server:FetchWorth', function()
+ for name,_ in pairs(Crypto.Worth) do
+ local result = MySQL.query.await('SELECT * FROM crypto WHERE crypto = ?', { name })
+ if result[1] ~= nil then
+ Crypto.Worth[name] = result[1].worth
+ if result[1].history ~= nil then
+ Crypto.History[name] = json.decode(result[1].history)
+ TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, name, result[1].worth, json.decode(result[1].history))
+ else
+ TriggerClientEvent('qb-crypto:client:UpdateCryptoWorth', -1, name, result[1].worth, nil)
+ end
+ end
+ end
+end)
+
+RegisterServerEvent('qb-crypto:server:ExchangeFail', function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local ItemData = Player.Functions.GetItemByName("cryptostick")
+
+ if ItemData ~= nil then
+ Player.Functions.RemoveItem("cryptostick", 1)
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["cryptostick"], "remove")
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('error.cryptostick_malfunctioned'), 'error')
+ end
+end)
+
+RegisterServerEvent('qb-crypto:server:Rebooting', function(state, percentage)
+ Crypto.Exchange.RebootInfo.state = state
+ Crypto.Exchange.RebootInfo.percentage = percentage
+end)
+
+RegisterServerEvent('qb-crypto:server:GetRebootState', function()
+ local src = source
+ TriggerClientEvent('qb-crypto:client:GetRebootState', src, Crypto.Exchange.RebootInfo)
+end)
+
+RegisterServerEvent('qb-crypto:server:SyncReboot', function()
+ TriggerClientEvent('qb-crypto:client:SyncReboot', -1)
+end)
+
+RegisterServerEvent('qb-crypto:server:ExchangeSuccess', function(LuckChance)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+ local ItemData = Player.Functions.GetItemByName("cryptostick")
+
+ if ItemData ~= nil then
+ local LuckyNumber = math.random(1, 10)
+ local DeelNumber = 1000000
+ local Amount = (math.random(611111, 1599999) / DeelNumber)
+ if LuckChance == LuckyNumber then
+ Amount = (math.random(1599999, 2599999) / DeelNumber)
+ end
+
+ Player.Functions.RemoveItem("cryptostick", 1)
+ Player.Functions.AddMoney('crypto', Amount)
+ TriggerClientEvent('QBCore:Notify', src, Lang:t('success.you_have_exchanged_your_cryptostick_for',{amount = Amount}), "success", 3500)
+ TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items["cryptostick"], "remove")
+ TriggerClientEvent('qb-phone:client:AddTransaction', src, Player, {}, Lang:t('credit.there_are_amount_credited',{amount = Amount}), "Modtog")
+ end
+end)
+
+-- Callbacks
+
+QBCore.Functions.CreateCallback('qb-crypto:server:HasSticky', function(source, cb)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local Item = Player.Functions.GetItemByName("cryptostick")
+
+ if Item ~= nil then
+ cb(true)
+ else
+ cb(false)
+ end
+end)
+
+QBCore.Functions.CreateCallback('qb-crypto:server:GetCryptoData', function(source, cb, name)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local CryptoData = {
+ History = Crypto.History[name],
+ Worth = Crypto.Worth[name],
+ Portfolio = Player.PlayerData.money.crypto,
+ WalletId = Player.PlayerData.metadata["walletid"],
+ }
+
+ cb(CryptoData)
+end)
+
+QBCore.Functions.CreateCallback('qb-crypto:server:BuyCrypto', function(source, cb, data)
+ local Player = QBCore.Functions.GetPlayer(source)
+ local total_price = math.floor(tonumber(data.Coins) * tonumber(Crypto.Worth["qbit"]))
+ if Player.PlayerData.money.bank >= total_price then
+ local CryptoData = {
+ History = Crypto.History["qbit"],
+ Worth = Crypto.Worth["qbit"],
+ Portfolio = Player.PlayerData.money.crypto + tonumber(data.Coins),
+ WalletId = Player.PlayerData.metadata["walletid"],
+ }
+ Player.Functions.RemoveMoney('bank', total_price)
+ TriggerClientEvent('qb-phone:client:AddTransaction', source, Player, data, Lang:t('credit.you_have_qbit_purchased',{dataCoins = tonumber(data.Coins)}), "Modtog")
+ Player.Functions.AddMoney('crypto', tonumber(data.Coins))
+ cb(CryptoData)
+ else
+ cb(false)
+ end
+end)
+
+QBCore.Functions.CreateCallback('qb-crypto:server:SellCrypto', function(source, cb, data)
+ local Player = QBCore.Functions.GetPlayer(source)
+
+ if Player.PlayerData.money.crypto >= tonumber(data.Coins) then
+ local CryptoData = {
+ History = Crypto.History["qbit"],
+ Worth = Crypto.Worth["qbit"],
+ Portfolio = Player.PlayerData.money.crypto - tonumber(data.Coins),
+ WalletId = Player.PlayerData.metadata["walletid"],
+ }
+ Player.Functions.RemoveMoney('crypto', tonumber(data.Coins))
+ local amount = math.floor(tonumber(data.Coins) * tonumber(Crypto.Worth["qbit"]))
+ TriggerClientEvent('qb-phone:client:AddTransaction', source, Player, data, Lang:t('depreciation.you_have_sold',{dataCoins = tonumber(data.Coins)}), "Solgte")
+ Player.Functions.AddMoney('bank', amount)
+ cb(CryptoData)
+ else
+ cb(false)
+ end
+end)
+
+QBCore.Functions.CreateCallback('qb-crypto:server:TransferCrypto', function(source, cb, data)
+ local newCoin = tostring(data.Coins)
+ local newWalletId = tostring(data.WalletId)
+ for _, v in pairs(bannedCharacters) do
+ newCoin = string.gsub(newCoin, '%' .. v, '')
+ newWalletId = string.gsub(newWalletId, '%' .. v, '')
+ end
+ data.WalletId = newWalletId
+ data.Coins = tonumber(newCoin)
+ local Player = QBCore.Functions.GetPlayer(source)
+ if Player.PlayerData.money.crypto >= tonumber(data.Coins) then
+ local query = '%"walletid":"' .. data.WalletId .. '"%'
+ local result = MySQL.query.await('SELECT * FROM `players` WHERE `metadata` LIKE ?', { query })
+ if result[1] ~= nil then
+ local CryptoData = {
+ History = Crypto.History["qbit"],
+ Worth = Crypto.Worth["qbit"],
+ Portfolio = Player.PlayerData.money.crypto - tonumber(data.Coins),
+ WalletId = Player.PlayerData.metadata["walletid"],
+ }
+ Player.Functions.RemoveMoney('crypto', tonumber(data.Coins))
+ TriggerClientEvent('qb-phone:client:AddTransaction', source, Player, data, "Du overførte "..tonumber(data.Coins).." Qbit('s)!", "Solgte")
+ local Target = QBCore.Functions.GetPlayerByCitizenId(result[1].citizenid)
+
+ if Target ~= nil then
+ Target.Functions.AddMoney('crypto', tonumber(data.Coins))
+ TriggerClientEvent('qb-phone:client:AddTransaction', Target.PlayerData.source, Player, data, "Du modtog "..tonumber(data.Coins).." Qbit('s)!", "Modtog")
+ else
+ local MoneyData = json.decode(result[1].money)
+ MoneyData.crypto = MoneyData.crypto + tonumber(data.Coins)
+ MySQL.update('UPDATE players SET money = ? WHERE citizenid = ?', { json.encode(MoneyData), result[1].citizenid })
+ end
+ cb(CryptoData)
+ else
+ cb("notvalid")
+ end
+ else
+ cb("notenough")
+ end
+end)
+
+-- Threads
+
+CreateThread(function()
+ while true do
+ Wait(Crypto.RefreshTimer*60000)
+ HandlePriceChance()
+ end
+end)
+
+-- You touch = you break
+if Ticker.Enabled then
+ Citizen.CreateThread(function()
+ local Interval = Ticker.tick_time * 60000
+ if Ticker.tick_time < 2 then
+ Interval = 120000
+ end
+ while(true) do
+ local get_coin_price = GetTickerPrice()
+ if type(get_coin_price) == 'number' then
+ Crypto.Worth["qbit"] = get_coin_price
+ else
+ print('\27[31m' .. get_coin_price .. '\27[0m')
+ Ticker.Enabled = false
+ break
+ end
+ Citizen.Wait(Interval)
+ end
+ end)
+end
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/LICENSE b/resources/[qb]/[qb_core]/qb-doorlock/LICENSE
new file mode 100644
index 0000000..f288702
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/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/[qb]/[qb_core]/qb-doorlock/README.md b/resources/[qb]/[qb_core]/qb-doorlock/README.md
new file mode 100644
index 0000000..7f25dc0
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/README.md
@@ -0,0 +1,113 @@
+# qb-doorlock
+Doorlock System For QBCore
+
+This doorlock system is based on [nui_doorlock by thelindat](https://github.com/thelindat/nui_doorlock) and contains compatibility with it's format.
+
+## Dependencies
+
+* [qb-core](https://github.com/qbcore-framework/qb-core)
+* [qb-input](https://github.com/qbcore-framework/qb-input) - For Making New Doors
+* [qb-lockpick](https://github.com/qbcore-framework/qb-lockpick) - For Lockpicking Doors
+
+## Features
+
+* Quick in-game door creation with /newdoor
+* Multiple door types to support all possible doors
+* Support for item checking, multiple or single items
+* Support for citizenid, gang and job checking
+* Support for qb-lockpick
+* NUI Text as interaction text
+* Great performance
+* Uses the native door system
+* Support for object names and hashes
+* Play any sound you want when unlocking/locking a door
+* Highly customisable
+* Auto lock, to automatically lock a door after it has been opened
+* Admin access option
+* Change color based on locked state
+
+## Single Door Configuration
+
+ ['somesingledoor'] = { -- The index of the table, this is used as the doorID
+ objName = 'hei_v_ilev_bk_gate2_pris', -- Door object name can be a string or a number. Alias: objHash = 'hei_v_ilev_bk_gate2_pris',
+ objCoords = vec3(261.83, 221.39, 106.41), -- Object coords
+ textCoords = vec3(261.83, 221.39, 106.41), -- Coords for the interaction text
+ authorizedJobs = { ['police'] = 0 }, -- Job access (checks for a minimum grade of 0)
+ authorizedGangs = { ['vagos'] = 0 }, -- Gang access (checks for a minimum grade of 0)
+ authorizedCitizenIDs = { ['BUI05180'] = true }, -- Citizen ID access
+ items = { ['keycard'] = 1, ['banana'] = 3 }, -- Item access, can be a string or table | the value of the item is the amount of items needed when using a table, if it is a string it will always check if this person has one or more of the item
+ needsAllItems = false, -- true or false | Whether to check if the person has all items to unlock the door or just one of the items
+ allAuthorized = false, -- true or false | Will give access to everyone if it is true
+ objYaw = -110.0, -- Heading of the door. Alias: objHeading = -110.0,
+ locked = true, -- true or false | Is the door locked by default
+ pickable = false, -- true or false | Can the door be lockpicked. Alias: lockpick = false,
+ distance = 1.5, -- At what range the interaction text will show. Alis: maxDistance = 1.5,
+ doorType = 'door', -- The type of door, can be door, double, sliding, doublesliding or garage
+ fixText = true, -- true or false | fix the text to the center of the door
+ doorLabel = 'Cloakroom', -- Label of the door that shows up when nearby
+ audioRemote = true, -- true or false | Play sound from the player instead of the door
+ audioLock = {['file'] = 'metal-locker.ogg', ['volume'] = 0.6}, -- Play sound on door lock
+ audioUnlock = {['file'] = 'metallic-creak.ogg', ['volume'] = 0.7}, -- Play sound on door unlock
+ autoLock = 1000, -- Auto lock after this many miliseconds
+ doorRate = 1.0, -- The rate of the animation to lock/unlock the door
+ cantUnlock = true -- true or false | Set to true to not allow the player to unlock the door, only lock it. This means a script will have to trigger the unlock
+ hideLabel = true, -- Set to true to hide the popup label, for hiding doors
+ remoteTrigger = true, -- true or false | If you want to be able to remote trigger a door with H, put this here
+ },
+
+## Double Door Configuration
+
+ ['somedoubledoor'] = { -- The index of the table, this is used as the doorID, can be a number or a string
+ doors = { -- Table of doors which holds both doors' data
+ {
+ objName = 'v_ilev_rc_door2', -- Door object name can be a string or a number. Alias: objHash = 'v_ilev_rc_door2',
+ objYaw = 135.0, -- Heading of the door. Alias: objHeading = 135.0,
+ objCoords = vec3(-447.7283, 6006.702, 31.86523), -- Object coords
+ },
+
+ {
+ objName = 'v_ilev_rc_door2', -- Door object name can be a string or a number. Alias: objHash = 'v_ilev_rc_door2',
+ objYaw = -45.0, -- Heading of the door. Alias: objHeading = -45.0,
+ objCoords = vec3(-449.5656, 6008.538, 31.86523), -- Object coords
+ },
+ },
+ textCoords = vec3(-448.67, 6007.52, 31.86523), -- Coords for the interaction text
+ authorizedJobs = { ['police'] = 0 }, -- Job access (checks for a minimum grade of 0)
+ authorizedGangs = { ['vagos'] = 0 }, -- Gang access (checks for a minimum grade of 0)
+ authorizedCitizenIDs = { ['BUI05180'] = true }, -- Citizen ID access
+ items = { ['keycard'] = 1, ['banana'] = 3 }, -- Item access, can be a string or table | the value of the item is the amount of items needed when using a table, if it is a string it will always check if this person has one or more of the item
+ needsAllItems = false, -- true or false | Whether to check if the person has all items to unlock the door or just one of the items
+ allAuthorized = false, -- true or false | Will give access to everyone if it is true
+ locked = true, -- true or false | Is the door locked by default
+ pickable = false, -- true or false | Can the door be lockpicked. Alias: lockpick = false,
+ distance = 2.5, -- At what range the interaction text will show. Alis: maxDistance = 2.5,
+ doorType = 'double', -- The type of door, can be door, double, sliding, doublesliding or garage
+ fixText = true, -- true or false | fix the text to the center of the door
+ doorLabel = 'Cloakroom', -- Label of the door that shows up when nearby
+ audioRemote = true, -- true or false | Play sound from the player instead of the door
+ audioLock = {['file'] = 'metal-locker.ogg', ['volume'] = 0.6}, -- Play sound on door lock
+ audioUnlock = {['file'] = 'metallic-creak.ogg', ['volume'] = 0.7}, -- Play sound on door unlock
+ autoLock = 1000, -- Auto lock after this many miliseconds
+ doorRate = 1.0, -- The rate of the animation to lock/unlock the door
+ cantUnlock = true -- true or false | Set to true to not allow the player to unlock the door, only lock it. This means a script will have to trigger the unlock
+ hideLabel = true, -- Set to true to hide the popup label, for hiding doors
+ remoteTrigger = true, -- true or false | If you want to be able to remote trigger a door with H, put this here
+ },
+
+# License
+
+ QBCore Framework
+ Copyright (C) 2021 Joshua Eger
+
+ 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
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/client/main.lua b/resources/[qb]/[qb_core]/qb-doorlock/client/main.lua
new file mode 100644
index 0000000..c9a07a2
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/client/main.lua
@@ -0,0 +1,886 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+local PlayerData = QBCore.Functions.GetPlayerData()
+local isLoggedIn = LocalPlayer.state['isLoggedIn']
+local Config = Config
+local canContinue = true
+local playerPed = PlayerPedId()
+local playerCoords = GetEntityCoords(playerPed)
+local lastCoords = playerCoords
+local nearbyDoors, closestDoor = {}, {}
+local paused = false
+local usingAdvanced = false
+local doorData = {}
+
+-- Functions
+function Draw3DText(coords, str)
+ local onScreen, worldX, worldY = World3dToScreen2d(coords.x, coords.y, coords.z)
+ local camCoords = GetGameplayCamCoord()
+ local scale = 200 / (GetGameplayCamFov() * #(camCoords - coords))
+ if onScreen then
+ SetTextScale(1.0, 0.5 * scale)
+ SetTextFont(4)
+ SetTextColour(255, 255, 255, 255)
+ SetTextEdge(2, 0, 0, 0, 150)
+ SetTextProportional(1)
+ SetTextOutline()
+ SetTextCentre(1)
+ SetTextEntry("STRING")
+ AddTextComponentString(str)
+ DrawText(worldX, worldY)
+ end
+end
+
+local function raycastWeapon()
+ local offset = GetOffsetFromEntityInWorldCoords(GetCurrentPedWeaponEntityIndex(playerPed), 0, 0, -0.01)
+ local direction = GetGameplayCamRot()
+ direction = vec2(direction.x * math.pi / 180.0, direction.z * math.pi / 180.0)
+ local num = math.abs(math.cos(direction.x))
+ direction = vec3((-math.sin(direction.y) * num), (math.cos(direction.y) * num), math.sin(direction.x))
+ local destination = vec3(offset.x + direction.x * 30, offset.y + direction.y * 30, offset.z + direction.z * 30)
+ local hit, entityHit, result
+ local rayHandle = StartShapeTestLosProbe(offset, destination, -1, playerPed, 0)
+ repeat
+ result, hit, _, _, entityHit = GetShapeTestResult(rayHandle)
+ Wait(0)
+ until result ~= 1
+ if GetEntityType(entityHit) == 3 then return hit, entityHit else return false, 0 end
+end
+
+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
+
+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, endCoords, _, _ = GetShapeTestResult(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, -1, PlayerPedId(), 0))
+ return hit == 1, endCoords
+end
+
+
+local function setTextCoords(data)
+ local minDimension, maxDimension = GetModelDimensions(data.objName or data.objHash)
+ local dimensions = maxDimension - minDimension
+ local dx, dy = tonumber(dimensions.x), tonumber(dimensions.y)
+ if dy <= -1 or dy >= 1 then dx = dy end
+ if data.fixText then
+ return GetOffsetFromEntityInWorldCoords(data.object, dx / 2, 0, 0)
+ else
+ return GetOffsetFromEntityInWorldCoords(data.object, -dx / 2, 0, 0)
+ end
+end
+
+local function getTextCoords(door)
+ if door.setText then return door.textCoords end
+ return setTextCoords(door)
+end
+
+local function round(value, numDecimalPlaces)
+ if not numDecimalPlaces then return math.floor(value + 0.5) end
+ local power = 10 ^ numDecimalPlaces
+ return math.floor((value * power) + 0.5) / (power)
+end
+
+local function loadAnimDict(dict)
+ RequestAnimDict(dict)
+ while not HasAnimDictLoaded(dict) do
+ Wait(0)
+ end
+end
+
+local function displayNUIText(text)
+ local color = Config.ChangeColor and (closestDoor.data.locked and Config.LockedColor or Config.UnlockedColor) or Config.DefaultColor
+ SendNUIMessage({
+ type = "setDoorText",
+ enable = true,
+ text = text,
+ color = color
+ })
+ Wait(1)
+end
+
+local function HandleDoorDebug()
+ if not Config.DoorDebug then return end
+
+ CreateThread(function()
+ while Config.DoorDebug do
+ if closestDoor.data then
+ Draw3DText(closestDoor.data.textCoords, closestDoor.data.doorLabel or 'Dør her')
+ end
+ Wait(0)
+ end
+ end)
+end
+
+local function hideNUI()
+ SendNUIMessage({
+ type = "setDoorText",
+ enable = false
+ })
+ Wait(1)
+end
+
+local function playSound(door, src, enableSounds)
+ if not Config.EnableSounds or not enableSounds then return end
+ local origin
+ if src and src ~= playerPed then src = NetworkGetEntityFromNetworkId(src) end
+ if not src then origin = door.textCoords elseif src == playerPed then origin = playerCoords else origin = NetworkGetPlayerCoords(src) end
+ local distance = #(playerCoords - origin)
+ if distance < 10 then
+ if not door.audioLock then
+ if door.audioRemote then
+ door.audioLock = {['file'] = 'button-remote.ogg', ['volume'] = 0.08}
+ door.audioUnlock = {['file'] = 'button-remote.ogg', ['volume'] = 0.08}
+ else
+ door.audioLock = {['file'] = 'door-bolt-4.ogg', ['volume'] = 0.1}
+ door.audioUnlock = {['file'] = 'door-bolt-4.ogg', ['volume'] = 0.1}
+ end
+ end
+ local sfx_level = GetProfileSetting(300)
+ local sound = door.locked and door.audioLock or door.audioUnlock
+ SendNUIMessage({
+ type = 'audio',
+ audio = sound,
+ distance = distance,
+ sfx = sfx_level
+ })
+ end
+end
+
+local function doorAnim()
+ if not Config.EnableAnimation then return end
+ CreateThread(function()
+ loadAnimDict("anim@heists@keycard@")
+ TaskPlayAnim(playerPed, "anim@heists@keycard@", "exit", 8.0, 1.0, -1, 48, 0, 0, 0, 0)
+ Wait(550)
+ ClearPedTasks(playerPed)
+ end)
+end
+
+local function updateDoors(specificDoor)
+ if #(playerCoords - lastCoords) > 30 then Wait(1000) end
+ playerCoords = GetEntityCoords(playerPed)
+ for doorID, data in pairs(Config.DoorList) do
+ if not specificDoor or doorID == specificDoor then
+ if data.doors then
+ if not data.doorType then data.doorType = 'double' end
+ for k, v in pairs(data.doors) do
+ if #(playerCoords - v.objCoords) < 30 then
+
+ if data.doorType == "doublesliding" then
+ v.object = GetClosestObjectOfType(v.objCoords.x, v.objCoords.y, v.objCoords.z, 5.0, v.objName or v.objHash, false, false, false)
+ else
+ v.object = GetClosestObjectOfType(v.objCoords.x, v.objCoords.y, v.objCoords.z, 1.0, v.objName or v.objHash, false, false, false)
+ end
+ if v.object and v.object ~= 0 then
+ v.doorHash = 'door_'..doorID..'_'..k
+ if not IsDoorRegisteredWithSystem(v.doorHash) then
+ local objCoords = GetEntityCoords(v.object)
+ local objHeading = GetEntityHeading(v.object)
+ local hasHeading = v.objYaw or v.objHeading or false
+ if v.objCoords ~= objCoords then v.objCoords = objCoords end -- Backwards compatibility fix
+ if not hasHeading then
+ v.objYaw = objHeading
+ else
+ if hasHeading ~= objHeading then -- Backwards compatibility fix
+ v.objYaw = v.objYaw and objHeading or nil
+ v.objHeading = v.objHeading and objHeading or nil
+ end
+ end
+ AddDoorToSystem(v.doorHash, v.objName or v.objHash, v.objCoords.x, v.objCoords.y, v.objCoords.z, false, false, false)
+ nearbyDoors[doorID] = true
+ if data.locked then
+ DoorSystemSetDoorState(v.doorHash, 4, false, false)
+ DoorSystemSetDoorState(v.doorHash, 1, false, false)
+ else
+ DoorSystemSetDoorState(v.doorHash, 0, false, false)
+ end
+ end
+ end
+ elseif v.object then
+ RemoveDoorFromSystem(v.doorHash)
+ nearbyDoors[doorID] = nil
+ end
+ end
+ elseif not data.doors then
+ if not data.doorType then data.doorType = 'door' end
+ if #(playerCoords - data.objCoords) < 30 then
+ if data.doorType == "sliding" or data.doorType == "garage" then
+ data.object = GetClosestObjectOfType(data.objCoords.x, data.objCoords.y, data.objCoords.z, 5.0, data.objName or data.objHash, false, false, false)
+ else
+ data.object = GetClosestObjectOfType(data.objCoords.x, data.objCoords.y, data.objCoords.z, 1.0, data.objName or data.objHash, false, false, false)
+ end
+ if data.object and data.object ~= 0 then
+ data.doorHash = 'door_'..doorID
+ if not IsDoorRegisteredWithSystem(data.doorHash) then
+ local objCoords = GetEntityCoords(data.object)
+ local objHeading = GetEntityHeading(data.object)
+ local hasHeading = data.objYaw or data.objHeading or false
+ if data.objCoords ~= objCoords then data.objCoords = objCoords end -- Backwards compatibility fix
+ if not hasHeading then
+ data.objYaw = objHeading
+ else
+ if hasHeading ~= objHeading then -- Backwards compatibility fix
+ data.objYaw = data.objYaw and objHeading or nil
+ data.objHeading = data.objHeading and objHeading or nil
+ end
+ end
+ data.objCoords = GetEntityCoords(data.object)
+ AddDoorToSystem(data.doorHash, data.objName or data.objHash, data.objCoords.x, data.objCoords.y, data.objCoords.z, false, false, false)
+ nearbyDoors[doorID] = true
+ if data.locked then
+ DoorSystemSetDoorState(data.doorHash, 4, false, false)
+ DoorSystemSetDoorState(data.doorHash, 1, false, false)
+ else
+ DoorSystemSetDoorState(data.doorHash, 0, false, false)
+ end
+ end
+ end
+ elseif data.object then
+ RemoveDoorFromSystem(data.doorHash)
+ nearbyDoors[doorID] = nil
+ end
+ end
+ -- set text coords
+ if not data.setText and data.doors then
+ for k, v in pairs(data.doors) do
+ if k == 1 and DoesEntityExist(v.object) then
+ data.textCoords = v.objCoords
+ elseif k == 2 and DoesEntityExist(v.object) and data.textCoords then
+ local textDistance = data.textCoords - v.objCoords
+ data.textCoords = data.textCoords - (textDistance / 2)
+ data.setText = true
+ end
+ if k == 2 and data.textCoords and (data.doorType == "sliding" or data.doorType == "garage") then
+ if GetEntityHeightAboveGround(v.object) < 1 then
+ data.textCoords = vec3(data.textCoords.x, data.textCoords.y, data.textCoords.z + 1.2)
+ end
+ end
+ end
+ elseif not data.setText and not data.doors and DoesEntityExist(data.object) then
+ if data.doorType == "garage" then
+ data.textCoords = data.objCoords
+ data.setText = true
+ else
+ data.textCoords = setTextCoords(data)
+ data.setText = true
+ end
+ if data.doorType == "sliding" or data.doorType == "garage" then
+ if GetEntityHeightAboveGround(data.object) < 1 then
+ data.textCoords = vec3(data.textCoords.x, data.textCoords.y, data.textCoords.z + 1.6)
+ end
+ end
+ end
+ end
+ end
+ lastCoords = playerCoords
+end
+
+local function lockpickFinish(success)
+ if success then
+ QBCore.Functions.Notify(Lang:t("success.lockpick_success"), 'success', 2500)
+ if closestDoor.data.coords then
+ TaskTurnPedToFaceCoord(playerPed, closestDoor.data.doors[1].objCoords.x, closestDoor.data.doors[1].objCoords.y, closestDoor.data.doors[1].objCoords.z, 0)
+ else
+ TaskTurnPedToFaceCoord(playerPed, closestDoor.data.objCoords.x, closestDoor.data.objCoords.y, closestDoor.data.objCoords.z, 0)
+ end
+ Wait(300)
+ local count = 0
+ while GetIsTaskActive(playerPed, 225) do
+ Wait(10)
+ if count == 150 then break end
+ count += 1
+ end
+ Wait(1800)
+ TriggerServerEvent('qb-doorlock:server:updateState', closestDoor.id, false, false, true, false) -- Broadcast new state of the door to everyone
+ else
+ QBCore.Functions.Notify(Lang:t("error.lockpick_fail"), 'error', 2500)
+ if math.random(1,100) <= 17 then
+ if usingAdvanced then
+ TriggerServerEvent("qb-doorlock:server:removeLockpick", "advancedlockpick")
+ TriggerEvent('inventory:client:ItemBox', QBCore.Shared.Items["advancedlockpick"], "remove")
+ else
+ TriggerServerEvent("qb-doorlock:server:removeLockpick", "lockpick")
+ TriggerEvent('inventory:client:ItemBox', QBCore.Shared.Items["lockpick"], "remove")
+ end
+ end
+ end
+end
+
+local function isAuthorized(door)
+ if door.allAuthorized then return true end
+
+ if door.authorizedJobs then
+ if door.authorizedJobs[PlayerData.job.name] and PlayerData.job.grade.level >= door.authorizedJobs[PlayerData.job.name] then
+ return true
+ elseif type(door.authorizedJobs[1]) == 'string' then
+ for _, job in pairs(door.authorizedJobs) do -- Support for old format
+ if job == PlayerData.job.name then return true end
+ end
+ end
+ end
+
+ if door.authorizedGangs then
+ if door.authorizedGangs[PlayerData.gang.name] and PlayerData.gang.grade.level >= door.authorizedGangs[PlayerData.gang.name] then
+ return true
+ elseif type(door.authorizedGangs[1]) == 'string' then
+ for _, gang in pairs(door.authorizedGangs) do -- Support for old format
+ if gang == PlayerData.gang.name then return true end
+ end
+ end
+ end
+
+ if door.authorizedCitizenIDs then
+ if door.authorizedCitizenIDs[PlayerData.citizenid] then
+ return true
+ elseif type(door.authorizedCitizenIDs[1]) == 'string' then
+ for _, id in pairs(door.authorizedCitizenIDs) do -- Support for old format
+ if id == PlayerData.citizenid then return true end
+ end
+ end
+ end
+
+ if door.items then
+ local p = promise.new()
+ QBCore.Functions.TriggerCallback('qb-doorlock:server:checkItems', function(result)
+ p:resolve(result)
+ end, door.items, door.needsAllItems)
+ return Citizen.Await(p)
+ end
+
+ return false
+end
+
+function SetupDoors()
+ local p = promise.new()
+ QBCore.Functions.TriggerCallback('qb-doorlock:server:setupDoors', function(result)
+ p:resolve(result)
+ end)
+ Config.DoorList = Citizen.Await(p)
+end
+
+-- Events
+
+RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
+ QBCore.Functions.TriggerCallback('qb-doorlock:server:setupDoors', function(result)
+ Config.DoorList = result
+ PlayerData = QBCore.Functions.GetPlayerData()
+ isLoggedIn = true
+ end)
+end)
+
+RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
+ isLoggedIn = false
+ PlayerData = {}
+end)
+
+RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
+ PlayerData = val
+end)
+
+RegisterNetEvent('qb-doorlock:client:setState', function(serverId, doorID, state, src, enableAnimation, enableSounds)
+ if not Config.DoorList[doorID] then return end
+ if enableAnimation == nil then enableAnimation = true end
+ if enableSounds == nil then enableSounds = true end
+ if serverId == PlayerData.source and enableAnimation then doorAnim() end
+ Config.DoorList[doorID].locked = state
+ updateDoors(doorID)
+ local current = Config.DoorList[doorID]
+ while true do
+ if current.doors then
+ if not current.doorType then current.doorType = 'double' end
+ for k, v in pairs(current.doors) do
+ if not IsDoorRegisteredWithSystem(v.doorHash) then return end
+ v.currentHeading = GetEntityHeading(v.object)
+ v.doorState = DoorSystemGetDoorState(v.doorHash)
+ if current.doorType == "doublesliding" then
+ DoorSystemSetAutomaticRate(v.doorHash, v.doorRate or 1.0, false, false)
+ if current.locked then
+ DoorSystemSetDoorState(v.doorHash, 1, false, false)
+ DoorSystemSetAutomaticDistance(v.doorHash, 0.0, false, false)
+ if k == 2 then
+ playSound(current, src, enableSounds)
+ return
+ end
+ else
+ DoorSystemSetDoorState(v.doorHash, 0, false, false)
+ DoorSystemSetAutomaticDistance(v.doorHash, 30.0, false, false)
+ if k == 2 then
+ playSound(current, src, enableSounds)
+ return
+ end
+ end
+ elseif current.locked and v.doorState == 4 then
+ DoorSystemSetDoorState(v.doorHash, 1, false, false)
+ if current.doors[1].doorState == current.doors[2].doorState then
+ playSound(current, src, enableSounds)
+ return
+ end
+ elseif not current.locked then
+ DoorSystemSetDoorState(v.doorHash, 0, false, false)
+ if current.doors[1].doorState == current.doors[2].doorState then
+ playSound(current, src, enableSounds)
+ return
+ end
+ else
+ if round(v.currentHeading, 0) == round(v.objYaw or v.objHeading, 0) then
+ DoorSystemSetDoorState(v.doorHash, 4, false, false)
+ end
+ end
+ end
+ else
+ if not IsDoorRegisteredWithSystem(current.doorHash) then return end
+ if not current.doorType then current.doorType = 'door' end
+ current.currentHeading = GetEntityHeading(current.object)
+ current.doorState = DoorSystemGetDoorState(current.doorHash)
+ if current.doorType == "sliding" or current.doorType == "garage" then
+ DoorSystemSetAutomaticRate(current.doorHash, current.doorRate or 1.0, false, false)
+ if current.locked then
+ DoorSystemSetDoorState(current.doorHash, 1, false, false)
+ DoorSystemSetAutomaticDistance(current.doorHash, 0.0, false, false)
+ playSound(current, src, enableSounds)
+ return
+ else
+ DoorSystemSetDoorState(current.doorHash, 0, false, false)
+ DoorSystemSetAutomaticDistance(current.doorHash, 30.0, false, false)
+ playSound(current, src, enableSounds)
+ return
+ end
+ elseif current.locked and current.doorState == 4 then
+ DoorSystemSetDoorState(current.doorHash, 1, false, false)
+ playSound(current, src, enableSounds)
+ return
+ elseif not current.locked then
+ DoorSystemSetDoorState(current.doorHash, 0, false, false)
+ playSound(current, src, enableSounds)
+ return
+ else
+ if round(current.currentHeading, 0) == round(current.objYaw or current.objHeading, 0) then
+ DoorSystemSetDoorState(current.doorHash, 4, false, false)
+ end
+ end
+ end
+ Wait(0)
+ end
+end)
+
+RegisterNetEvent('lockpicks:UseLockpick', function(isAdvanced)
+ if not closestDoor.data or not next(closestDoor.data) or PlayerData.metadata['isdead'] or PlayerData.metadata['ishandcuffed'] or (not closestDoor.data.pickable and not closestDoor.data.lockpick) or not closestDoor.data.locked then return end
+ usingAdvanced = isAdvanced
+ TriggerEvent('qb-lockpick:client:openLockpick', lockpickFinish)
+end)
+
+RegisterNetEvent('qb-doorlock:client:addNewDoor', function()
+ canContinue = false
+ hideNUI()
+ if not Config.SaveDoorDialog then doorData = {} end
+ local dialog = exports['qb-input']:ShowInput({
+ header = Lang:t("general.newdoor_menu_title"),
+ submitText = Lang:t("general.submit_text"),
+ inputs = {
+ {
+ text = Lang:t("general.configfile_title"),
+ name = "configfile",
+ type = "text",
+ isRequired = true,
+ default = Config.SaveDoorDialog and doorData.configfile,
+ },
+ {
+ text = Lang:t("general.dooridentifier_title"),
+ name = "dooridentifier",
+ type = "text",
+ isRequired = true,
+ default = Config.SaveDoorDialog and doorData.dooridentifier,
+ },
+ {
+ text = Lang:t("general.doorlabel_title"),
+ name = "doorlabel",
+ type = "text",
+ isRequired = false,
+ default = Config.SaveDoorDialog and doorData.doorlabel,
+ },
+ {
+ text = Lang:t("general.doortype_title"),
+ name = "doortype",
+ type = "select",
+ options = {
+ { value = "door", text = Lang:t("general.doortype_door") },
+ { value = "double", text = Lang:t("general.doortype_double") },
+ { value = "sliding", text = Lang:t("general.doortype_sliding") },
+ { value = "doublesliding", text = Lang:t("general.doortype_doublesliding") },
+ { value = "garage", text = Lang:t("general.doortype_garage") }
+ },
+ default = Config.SaveDoorDialog and doorData.doortype,
+ },
+ {
+ text = Lang:t("general.job_authorisation_menu"),
+ name = "job",
+ type = "text",
+ isRequired = false,
+ default = Config.SaveDoorDialog and doorData.job,
+ },
+ {
+ text = Lang:t("general.gang_authorisation_menu"),
+ name = "gang",
+ type = "text",
+ isRequired = false,
+ default = Config.SaveDoorDialog and doorData.gang,
+ },
+ {
+ text = Lang:t("general.citizenid_authorisation_menu"),
+ name = "cid",
+ type = "text",
+ isRequired = false,
+ default = Config.SaveDoorDialog and doorData.cid,
+ },
+ {
+ text = Lang:t("general.item_authorisation_menu"),
+ name = "item",
+ type = "text",
+ isRequired = false,
+ default = Config.SaveDoorDialog and doorData.item,
+ },
+ {
+ text = Lang:t("general.distance_menu"),
+ name = "distance",
+ type = "number",
+ isRequired = true,
+ default = Config.SaveDoorDialog and doorData.distance,
+ },
+ {
+ text = "",
+ name = "checklock",
+ type = "checkbox",
+ options = {
+ { value = "locked", text = Lang:t("general.locked_menu"), checked = (Config.SaveDoorDialog and doorData.locked) },
+ { value = "pickable", text = Lang:t("general.pickable_menu"), checked = (Config.SaveDoorDialog and doorData.pickable == 'true') },
+ { value = "cantunlock", text = Lang:t("general.cantunlock_menu"), checked = (Config.SaveDoorDialog and doorData.cantunlock == 'true') },
+ { value = "hidelabel", text = Lang:t("general.hidelabel_menu"), checked = (Config.SaveDoorDialog and doorData.hidelabel == 'true') },
+ }
+ }
+ }
+ })
+ if not dialog or not next(dialog) then canContinue = true return end
+ doorData = dialog
+
+ local identifier = doorData.configfile..'-'..doorData.dooridentifier
+ if Config.DoorList[identifier] then
+ QBCore.Functions.Notify((Lang:t("error.door_identifier_exists")):format(identifier), 'error')
+ canContinue = true
+ return
+ end
+
+ if doorData.configfile == '' then doorData.configfile = false end
+ if doorData.job == '' then doorData.job = false end
+ if doorData.gang == '' then doorData.gang = false end
+ if doorData.cid == '' then doorData.cid = false end
+ if doorData.item == '' then doorData.item = false end
+ if doorData.doorlabel == '' then doorData.doorlabel = nil end
+ if doorData.pickable ~= 'true' then doorData.pickable = nil end
+ if doorData.cantunlock ~= 'true' then doorData.cantunlock = nil end
+ if doorData.hidelabel ~= 'true' then doorData.hidelabel = nil end
+
+ doorData.locked = doorData.locked == 'true'
+ doorData.distance = tonumber(doorData.distance)
+ if doorData.doortype == 'door' or doorData.doortype == 'sliding' or doorData.doortype == 'garage' then
+ SendNUIMessage({
+ type = "setText",
+ aim = "block"
+ })
+ local heading, result, entityHit
+ local entity, coords, model= 0, 0, 0
+ while true do
+ if IsPlayerFreeAiming(PlayerId()) then
+ result, entityHit = raycastWeapon()
+ if result and entityHit ~= entity then
+ SetEntityDrawOutline(entity, false)
+ SetEntityDrawOutline(entityHit, true)
+ entity = entityHit
+ coords = GetEntityCoords(entity)
+ model = GetEntityModel(entity)
+ heading = GetEntityHeading(entity)
+ SendNUIMessage({
+ type = "setText",
+ aim = "none",
+ details = "block",
+ coords = coords,
+ heading = heading,
+ hash = model
+ })
+ end
+ if entity and IsControlPressed(0, 24) then break end
+ end
+ Wait(0)
+ end
+ SetEntityDrawOutline(entity, false)
+ SendNUIMessage({
+ type = "setText",
+ aim = "none",
+ details = "none",
+ coords = "",
+ heading = "",
+ hash = ""
+ })
+ if not model or model == 0 then QBCore.Functions.Notify(Lang:t("error.door_not_found"), 'error') canContinue = true return end
+ result = DoorSystemFindExistingDoor(coords.x, coords.y, coords.z, model)
+ if result then QBCore.Functions.Notify(Lang:t("error.door_registered"), 'error') canContinue = true return end
+ doorData.doorHash = 'door_'..doorData.dooridentifier
+ AddDoorToSystem(doorData.doorHash, model, coords, false, false, false)
+ DoorSystemSetDoorState(doorData.doorHash, 4, false, false)
+ coords = GetEntityCoords(entity)
+ heading = GetEntityHeading(entity)
+ RemoveDoorFromSystem(doorData.doorHash)
+ doorData.entity = entity
+ doorData.coords = coords
+ doorData.model = model
+ doorData.heading = heading
+ TriggerServerEvent('qb-doorlock:server:saveNewDoor', doorData, false)
+ canContinue = true
+ else
+ local result, entityHit
+ local entity, coords, heading, model = {0, 0}, {0, 0}, {0, 0}, {0, 0}
+ for i = 1, 2 do
+ SendNUIMessage({
+ type = "setText",
+ aim = "block",
+ details = "none",
+ coords = "",
+ heading = "",
+ hash = ""
+ })
+ while true do
+ if IsPlayerFreeAiming(PlayerId()) then
+ result, entityHit = raycastWeapon()
+ if result and entityHit ~= entity[i] then
+ SetEntityDrawOutline(entity[i], false)
+ SetEntityDrawOutline(entityHit, true)
+ entity[i] = entityHit
+ coords[i] = GetEntityCoords(entity[i])
+ model[i] = GetEntityModel(entity[i])
+ heading[i] = GetEntityHeading(entity[i])
+ SendNUIMessage({
+ type = "setText",
+ aim = "none",
+ details = "block",
+ coords = coords[i],
+ heading = heading[i],
+ hash = model[i]
+ })
+ end
+ if entity[i] and IsControlPressed(0, 24) then break end
+ end
+ Wait(0)
+ end
+ Wait(200)
+ end
+ SetEntityDrawOutline(entity[1], false)
+ SetEntityDrawOutline(entity[2], false)
+ SendNUIMessage({
+ type = "setText",
+ aim = "none",
+ details = "none",
+ coords = "",
+ heading = "",
+ hash = ""
+ })
+ if not model[1] or model[1] == 0 or not model[2] or model[2] == 0 then QBCore.Functions.Notify(Lang:t("error.door_not_found"), 'error') return end
+ if entity[1] == entity[2] then QBCore.Functions.Notify(Lang:t("error.same_entity"), 'error') canContinue = true return end
+ doorData.doorHash = {}
+ for i = 1, 2 do
+ result = DoorSystemFindExistingDoor(coords[i].x, coords[i].y, coords[i].z, model[i])
+ if result then QBCore.Functions.Notify(Lang:t("error.door_registered"), 'error') canContinue = true return end
+ doorData.doorHash[i] = 'door_'..doorData.dooridentifier..'_'..i
+ AddDoorToSystem(doorData.doorHash[i], model[i], coords[i], false, false, false)
+ DoorSystemSetDoorState(doorData.doorHash[i], 4, false, false)
+ coords[i] = GetEntityCoords(entity[i])
+ heading[i] = GetEntityHeading(entity[i])
+ RemoveDoorFromSystem(doorData.doorHash[i])
+ end
+ doorData.entity = entity
+ doorData.coords = coords
+ doorData.model = model
+ doorData.heading = heading
+ TriggerServerEvent('qb-doorlock:server:saveNewDoor', doorData, true)
+ canContinue = true
+ end
+end)
+
+RegisterNetEvent('qb-doorlock:client:newDoorAdded', function(data, id, creatorSrc)
+ Config.DoorList[id] = data
+ TriggerEvent('qb-doorlock:client:setState', creatorSrc, id, data.locked, false, true, true)
+end)
+
+RegisterNetEvent('qb-doorlock:client:ToggleDoorDebug', function()
+ Config.DoorDebug = not Config.DoorDebug
+ HandleDoorDebug()
+end)
+
+-- Commands
+
+RegisterCommand('toggledoorlock', function()
+ if not closestDoor.data or not next(closestDoor.data) then return end
+
+ local distanceCheck = closestDoor.distance > (closestDoor.data.distance or closestDoor.data.maxDistance)
+ local unlockableCheck = (closestDoor.data.cantUnlock and closestDoor.data.locked)
+ local busyCheck = PlayerData.metadata['isdead'] or PlayerData.metadata['inlaststand'] or PlayerData.metadata['ishandcuffed']
+ if distanceCheck or unlockableCheck or busyCheck then return end
+
+ playerPed = PlayerPedId()
+ local veh = GetVehiclePedIsIn(playerPed)
+ if veh then
+ CreateThread(function()
+ local siren = IsVehicleSirenOn(veh)
+ for _ = 0, 100 do
+ DisableControlAction(0, 86, true)
+ SetHornEnabled(veh, false)
+ if not siren then SetVehicleSiren(veh, false) end
+ Wait(0)
+ end
+ SetHornEnabled(veh, true)
+ end)
+ end
+ local locked = not closestDoor.data.locked
+ local src = false
+ if closestDoor.data.audioRemote then src = NetworkGetNetworkIdFromEntity(playerPed) end
+
+ TriggerServerEvent('qb-doorlock:server:updateState', closestDoor.id, locked, src, false, false, true, true) -- Broadcast new state of the door to everyone
+end, false)
+TriggerEvent("chat:removeSuggestion", "/toggledoorlock")
+RegisterKeyMapping('toggledoorlock', Lang:t("general.keymapping_description"), 'keyboard', 'E')
+
+
+RegisterCommand('remotetriggerdoor', function()
+ local hit, raycastCoords = RayCastGamePlayCamera(Config.RemoteTriggerDistance)
+ if not hit then return end
+
+ local nearestDoor = nil
+ for k in pairs(nearbyDoors) do
+ local door = Config.DoorList[k]
+ local canTrigger = door.remoteTrigger
+ local distance = #(raycastCoords - getTextCoords(door))
+
+ if canTrigger and (not nearestDoor or distance < nearestDoor.distance) and distance < math.max(door.distance,Config.RemoteTriggerMinDistance) then
+ nearestDoor = {
+ data = door,
+ id = k,
+ distance = distance
+ }
+ end
+ end
+
+ if not nearestDoor then return end
+
+ local unlockableCheck = (nearestDoor.data.cantUnlock and nearestDoor.data.locked)
+ local busyCheck = PlayerData.metadata['isdead'] or PlayerData.metadata['inlaststand'] or PlayerData.metadata['ishandcuffed']
+ if unlockableCheck or busyCheck then return end
+
+ playerPed = PlayerPedId()
+ local veh = GetVehiclePedIsIn(playerPed)
+ if veh then
+ CreateThread(function()
+ for _ = 0, 100 do
+ DisableControlAction(0, 74, true)
+ Wait(0)
+ end
+ end)
+ end
+
+ TriggerServerEvent('qb-doorlock:server:updateState', nearestDoor.id, not nearestDoor.data.locked, NetworkGetNetworkIdFromEntity(playerPed), false, false, true, true) -- Broadcast new state of the door to everyone
+end, false)
+TriggerEvent("chat:removeSuggestion", "/remotetriggerdoor")
+RegisterKeyMapping('remotetriggerdoor', Lang:t("general.keymapping_remotetriggerdoor"), 'keyboard', 'H')
+
+-- Threads
+
+CreateThread(function()
+ if Config.PersistentDoorStates and isLoggedIn then Wait(1000) SetupDoors() end -- Required for pulling in door states properly from live ensures
+
+ updateDoors()
+ HandleDoorDebug()
+ while true do
+ local sleep = 100
+ if isLoggedIn and canContinue then
+ playerPed = PlayerPedId()
+ playerCoords = GetEntityCoords(playerPed)
+ if not closestDoor.id then
+ local distance = #(playerCoords - lastCoords)
+ if distance > 15 then
+ updateDoors()
+ sleep = 1000
+ else
+ for k in pairs(nearbyDoors) do
+ local door = Config.DoorList[k]
+ if door.setText and door.textCoords then
+ distance = #(playerCoords - door.textCoords)
+ if distance < (closestDoor.distance or 15) then
+ if distance < (door.distance or door.maxDistance) then
+ closestDoor = {distance = distance, id = k, data = door}
+ sleep = 0
+ end
+ end
+ end
+ end
+ end
+ end
+ if closestDoor.id then
+ while isLoggedIn do
+ if not paused and IsPauseMenuActive() then
+ hideNUI()
+ paused = true
+ elseif paused then
+ if not IsPauseMenuActive() then paused = false end
+ else
+ playerCoords = GetEntityCoords(playerPed)
+ closestDoor.distance = #(closestDoor.data.textCoords - playerCoords)
+ if closestDoor.distance < (closestDoor.data.distance or closestDoor.data.maxDistance) then
+ local authorized = isAuthorized(closestDoor.data)
+ local displayText = ""
+
+ if not closestDoor.data.hideLabel and Config.UseDoorLabelText and closestDoor.data.doorLabel then
+ displayText = closestDoor.data.doorLabel
+ else
+ if not closestDoor.data.locked and not authorized then
+ displayText = Lang:t("general.unlocked")
+ elseif not closestDoor.data.locked and authorized then
+ displayText = Lang:t("general.unlocked_button")
+ elseif closestDoor.data.locked and not authorized then
+ displayText = Lang:t("general.locked")
+ elseif closestDoor.data.locked and authorized then
+ displayText = Lang:t("general.locked_button")
+ end
+ end
+
+ if displayText ~= "" and (closestDoor.data.hideLabel == nil or not closestDoor.data.hideLabel) then displayNUIText(displayText) end
+ else
+ hideNUI()
+ break
+ end
+ end
+ Wait(100)
+ end
+ closestDoor = {}
+ sleep = 0
+ end
+ end
+ Wait(sleep)
+ end
+end)
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/config.lua b/resources/[qb]/[qb_core]/qb-doorlock/config.lua
new file mode 100644
index 0000000..a5500b2
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/config.lua
@@ -0,0 +1,251 @@
+Config = {}
+
+Config.CommandPermission = 'admin' -- permission level for creating new doors
+Config.AdminAccess = true -- Enable admins to unlock any door
+Config.AdminPermission = 'admin' -- The permission needed to get AdminAccess if it is enabled
+Config.Warnings = true -- if true it will show warnings in the console when certain requirements aren't met
+Config.FallbackDistance = 3.0 -- Distance to fall back on when it is not set
+Config.EnableSounds = true -- Enable sounds when unlocking/locking doors (doors triggered by scripts can have the sound manually disabled)
+Config.EnableAnimation = true -- Enable the animation when unlocking/locking doors (doors triggered by scripts can have the animation manually disabled)
+Config.SaveDoorDialog = true -- Saves the door dialogue popup between door saves
+Config.PersistentDoorStates = true -- Persists the door state between server restarts
+Config.PersistentSaveInternal = 60000 -- How often door states are saved to the file system, in miliseconds.
+
+Config.ChangeColor = true -- Change the color of the box of the popup text based on if it is locked or not
+Config.DefaultColor = 'rgb(19, 28, 74)' -- The default color of the box of the popup text if Config.ChangeColor is false
+Config.LockedColor = 'rgb(219 58 58)' -- The color of the box of the popup text if Config.ChangeColor is true and the door is locked
+Config.UnlockedColor = 'rgb(27 195 63)' -- The color of the box of the popup text if Config.ChangeColor is true and the door is unlocked
+Config.UseDoorLabelText = false -- Will use the LABEL field as the nui text instead of locked/unlocked
+Config.DoorDebug = false -- Enable DRAWTEXT in the world at the coords where the door 'center' is
+Config.RemoteTriggerDistance = 15.0 -- This is how far from your camera the raycast will go to try to hit something solid
+Config.RemoteTriggerMinDistance = 5.0 -- This is the minimum distance required for the raycast hit to count near a door. It will take the larger two between this and 'distance' option
+
+Config.Consumables = { ['ticket'] = 1, ['paperclip'] = 1 } -- The items will get removed once used on a door that has the item on it
+
+--[[ -- Configuration Options
+Config.DoorList['configname-identifier'] = {
+ fixText = false, -- Adjusts guess of center of door
+ textCoords = vector3(x, y, z) -- Set the text coordinates to a specific location
+ setText = true -- Use with above setting
+ distance = 2.0, -- Max interact distance
+ lockpick = true, -- Alows for lockpicking
+ allAuthorized = true, -- Anyone can use door
+ authorizedJobs = { ['police']=0, ['bcso']=0, ['sasp]=0 } -- Authorize door access based on job grade
+ authorizedGangs = { ['vagos']=0, ['ballas']=0 } -- Authorize door access based on gang grade
+ authorizedCitizenIDs = { 'ABC123', 'DEF456' } -- Authorize door access based on citizenid
+ items = {'item_1','item_2'} -- Authorize based on items. Must have all items in this list.
+ doorLabel = 'Cloakroom', -- Label of room that shows up when nearby
+ locked = true, -- Default lock state
+ audioRemote = true, -- Play sound from the player instead of the door
+ audioLock = {['file'] = 'metal-locker.ogg', ['volume'] = 0.6}, -- Play sound on door lock
+ audioUnlock = {['file'] = 'metallic-creak.ogg', ['volume'] = 0.7}, -- Play sound on door unlock
+ autoLock = 1000, -- Auto lock after this many miliseconds
+ doorRate = 1.0, -- Time till auto closes? Needs more testing
+ cantUnlock = true -- Set to true to not allow the player to unlock the door, only lock it. This means a script will have to trigger the unlock.
+ pickable = true, -- Can use a lockpick to unlock, only need if true
+ hideLabel = true, -- Set to true to hide the popup label, for hiding doors ;)
+ remoteTrigger = true, -- If you want to be able to remote trigger a door with H, put this here
+}
+]]
+
+Config.DoorStates = {}
+Config.DoorList = {
+ {
+ objName = 'hei_v_ilev_bk_gate2_pris',
+ objCoords = vec3(261.83, 221.39, 106.41),
+ textCoords = vec3(261.83, 221.39, 106.41),
+ authorizedJobs = { 'police' },
+ objYaw = -110.0,
+ locked = true,
+ pickable = false,
+ distance = 1.5,
+ },
+ --door2 for pacific opened with thermite right near the vault door
+ {
+ objName = 'hei_v_ilev_bk_safegate_pris',
+ objCoords = vec3(252.98, 220.65, 101.8),
+ textCoords = vec3(252.98, 220.65, 101.8),
+ authorizedJobs = { 'police' },
+ objYaw = 160.0,
+ locked = true,
+ pickable = false,
+ distance = 1.5
+ },
+ -- door3 for pacific opened with thermite after passing the door near vault
+ {
+ objName = 'hei_v_ilev_bk_safegate_pris',
+ objCoords = vec3(261.68, 215.62, 101.81),
+ textCoords = vec3(261.68, 215.62, 101.81),
+ authorizedJobs = { 'police' },
+ objYaw = -110.0,
+ locked = true,
+ pickable = false,
+ distance = 1.5
+ },
+ -- First Pacific Door opened with lockpick
+ {
+ objName = 'hei_v_ilev_bk_gate_pris',
+ objCoords = vec3(257.41, 220.25, 106.4),
+ textCoords = vec3(257.41, 220.25, 106.4),
+ authorizedJobs = { 'police' },
+ objYaw = -20.0,
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Second Pacific Door opened with lockpick
+ {
+ objName = 'v_ilev_bk_door',
+ objCoords = vec3(265.19, 217.84, 110.28),
+ textCoords = vec3(265.19, 217.84, 110.28),
+ authorizedJobs = { 'police' },
+ objYaw = -20.0,
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Fleeca Door opened with lockpick
+ {
+ objName = 'v_ilev_gb_vaubar',
+ objCoords = vec3(314.61, -285.82, 54.49),
+ textCoords = vec3(313.3, -285.45, 54.49),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Fleeca Door opened with lockpick
+ {
+ objName = 'v_ilev_gb_vaubar',
+ objCoords = vec3(148.96, -1047.12, 29.7),
+ textCoords = vec3(148.96, -1047.12, 29.7),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Fleeca Door opened with lockpick
+ {
+ objName = 'v_ilev_gb_vaubar',
+ objCoords = vec3(-351.7, -56.28, 49.38),
+ textCoords = vec3(-351.7, -56.28, 49.38),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Fleeca Door opened with lockpick
+ {
+ objName = 'v_ilev_gb_vaubar',
+ objCoords = vec3(-1208.12, -335.586, 37.759),
+ textCoords = vec3(-1208.12, -335.586, 37.759),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Fleeca Door opened with lockpick
+ {
+ objName = 'v_ilev_gb_vaubar',
+ objCoords = vec3(-2956.18, 483.96, 16.02),
+ textCoords = vec3(-2956.18, 483.96, 16.02),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = true,
+ distance = 1.5
+ },
+ -- Prison Door 1
+ {
+ objName = 'prop_gate_prison_01',
+ objCoords = vec3(1844.9, 2604.8, 44.6),
+ textCoords = vec3(1844.9, 2608.5, 48.0),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = false,
+ distance = 13
+ },
+ -- Prison Door 2
+ {
+ objName = 'prop_gate_prison_01',
+ objCoords = vec3(1818.5, 2604.8, 44.6),
+ textCoords = vec3(1818.5, 2608.4, 48.0),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = false,
+ distance = 13
+ },
+ -- Prison Door 3
+ {
+ objName = 'prop_gate_prison_01',
+ objCoords = vec3(1799.237, 2616.303, 44.6),
+ textCoords = vec3(1795.941, 2616.969, 48.0),
+ authorizedJobs = { 'police' },
+ locked = true,
+ pickable = false,
+ distance = 10
+ },
+ ------------------------------------------Always add new doors below this line for your bank robberies to work!!!---------------------------------
+ ------------------------------------------End Fixed Doors!!!---------------------------------
+ -- Luxury Cars
+ -- Entrance Doors
+ {
+ textCoords = vec3(-803.0223, -223.8222, 37.87975),
+ authorizedJobs = { 'cardealer', 'police' },
+ locked = true,
+ pickable = false,
+ distance = 3.5,
+ doors = {
+ {
+ objName = 'prop_doorluxyry2',
+ objYaw = 120.0,
+ objCoords = vec3(-803.0223, -222.5841, 37.87975)
+ },
+
+ {
+ objName = 'prop_doorluxyry2',
+ objYaw = -60.0,
+ objCoords = vec3(-801.9622, -224.5203, 37.87975)
+ }
+ }
+ },
+ -- Side Entrance Doors
+ {
+ textCoords = vec3(-777.1855, -244.0013, 37.333889),
+ authorizedJobs = { 'cardealer', 'police' },
+ locked = true,
+ pickable = false,
+ distance = 3.5,
+ doors = {
+ {
+ objName = 'prop_doorluxyry',
+ objYaw = -160.0,
+ objCoords = vec3(-778.1855, -244.3013, 37.33388)
+ },
+
+ {
+ objName = 'prop_doorluxyry',
+ objYaw = 23.0,
+ objCoords = vec3(-776.1591, -243.5013, 37.33388)
+ }
+ }
+ },
+ -- Garage Doors
+ {
+ textCoords = vec3(-768.1264, -238.9737, 37.43247),
+ authorizedJobs = { 'cardealer', 'police' },
+ locked = true,
+ pickable = false,
+ distance = 13.0,
+ doors = {
+ {
+ objName = 'prop_autodoor',
+ objCoords = vec3(-770.6311, -240.0069, 37.43247)
+ },
+
+ {
+ objName = 'prop_autodoor',
+ objCoords = vec3(-765.6217, -237.9405, 37.43247)
+ }
+ }
+ },
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/1robbery.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/1robbery.lua
new file mode 100644
index 0000000..c37e54c
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/1robbery.lua
@@ -0,0 +1,56 @@
+
+
+-- GuardTower5 created by THX1139
+Config.DoorList['1robbery-GuardTower5'] = {
+ doorRate = 1.0,
+ objYaw = 270.0,
+ locked = true,
+ objName = -1033001619,
+ distance = 2,
+ doorLabel = 'PrisonTower5',
+ fixText = false,
+ doorType = 'door',
+ objCoords = vec3(1537.810913, 2585.995117, 45.689148),
+ authorizedJobs = { ['police'] = 0 },
+}
+-- infirmaryoffice created by THX1139
+-- infirmarylab created by THX1139
+Config.DoorList['1robbery-infirmarylab'] = {
+ distance = 1,
+ objYaw = 90.000007629395,
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0, ['bcso'] = 0, ['corrections'] = 0 },
+ doorLabel = 'infirmary2',
+ fixText = false,
+ locked = true,
+ doorRate = 1.0,
+ objName = -1392981450,
+ objCoords = vec3(1767.323242, 2580.832031, 45.747826),
+}
+-- cameraroom1 created by THX1139
+Config.DoorList['1robbery-cameraroom1'] = {
+ distance = 1,
+ objYaw = 29.999996185303,
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0, ['bcso'] = 0, ['corrections'] = 0 },
+ doorLabel = 'camera1',
+ fixText = false,
+ locked = true,
+ doorRate = 1.0,
+ objName = 241550507,
+ objCoords = vec3(1772.938599, 2495.313232, 49.840057),
+}
+
+-- cameraroom2 created by THX1139
+Config.DoorList['1robbery-cameraroom2'] = {
+ distance = 1,
+ objYaw = 29.999996185303,
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0, ['bcso'] = 0, ['corrections'] = 0 },
+ doorLabel = 'camera2',
+ fixText = false,
+ locked = true,
+ doorRate = 1.0,
+ objName = 241550507,
+ objCoords = vec3(1775.414185, 2491.025391, 49.840057),
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/bean.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/bean.lua
new file mode 100644
index 0000000..9c6048c
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/bean.lua
@@ -0,0 +1,29 @@
+
+
+-- b1 created by isakh
+Config.DoorList['bean-b1'] = {
+ objYaw = 340.00003051758,
+ objCoords = vec3(128.213394, -1029.455322, 29.261801),
+ locked = false,
+ objName = 494354570,
+ distance = 2,
+ fixText = false,
+ doorType = 'door',
+ doorRate = 1.0,
+ doorLabel = 'b1',
+ authorizedJobs = { ['beanmachine'] = 0 },
+}
+
+-- b2 created by isakh
+Config.DoorList['bean-b2'] = {
+ authorizedJobs = { ['beanmachine'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = -747011272, objYaw = 69.999992370605, objCoords = vec3(115.375694, -1037.655029, 29.348320)},
+ {objName = -1182160879, objYaw = 250.00004577637, objCoords = vec3(114.562912, -1039.888184, 29.348320)}
+ },
+ doorRate = 1.0,
+ doorLabel = 'b2',
+ doorType = 'double',
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/burgershot.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/burgershot.lua
new file mode 100644
index 0000000..229a8d4
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/burgershot.lua
@@ -0,0 +1,15 @@
+
+
+-- burgershot created by s0b1esk1_86
+Config.DoorList['burgershot-burgershot'] = {
+ distance = 2,
+ objCoords = vec3(-1680.785034, -1095.974976, 13.305560),
+ objName = -1300743830,
+ doorRate = 1.0,
+ doorType = 'door',
+ fixText = false,
+ doorLabel = 'Burgershot',
+ locked = false,
+ authorizedJobs = { ['burgershot'] = 0 },
+ objYaw = 313.00003051758,
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/luxury.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/luxury.lua
new file mode 100644
index 0000000..fb1b972
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/luxury.lua
@@ -0,0 +1,43 @@
+
+
+-- LuxuryGarage created by Hawk
+Config.DoorList['LuxuryGarage-LuxuryGarage'] = {
+ doorLabel = 'LuxuryGarage',
+ doorType = 'garage',
+ distance = 5,
+ authorizedJobs = { ['cardealer'] = 0 },
+ fixText = false,
+ locked = true,
+ objYaw = 207.0,
+ objName = 1430328167,
+ objCoords = vec3(-1237.843628, -338.194764, 37.607274),
+ doorRate = 1.0,
+}
+
+-- LuxuryFrontDoor1 created by Hawk
+Config.DoorList['LuxuryFrontDoor1-LuxuryFrontDoor1'] = {
+ locked = false,
+ doorType = 'double',
+ doors = {
+ {objName = 73386408, objYaw = 207.0, objCoords = vec3(-1259.591308, -348.532258, 37.111160)},
+ {objName = -1152174184, objYaw = 207.0, objCoords = vec3(-1261.875610, -349.696198, 37.111160)}
+ },
+ distance = 3,
+ authorizedJobs = { ['cardealer'] = 0 },
+ doorLabel = 'LuxuryFrontDoor1',
+ doorRate = 1.0,
+}
+
+-- LuxuryFrontDoor2 created by Hawk
+Config.DoorList['LuxuryFrontDoor2-LuxuryFrontDoor2'] = {
+ locked = true,
+ doorType = 'double',
+ doors = {
+ {objName = -1152174184, objYaw = 298.0, objCoords = vec3(-1268.578002, -370.370178, 37.099244)},
+ {objName = 73386408, objYaw = 298.0, objCoords = vec3(-1269.793090, -368.111480, 37.111160)}
+ },
+ distance = 3,
+ authorizedJobs = { ['cardealer'] = 0 },
+ doorLabel = 'LuxuryFrontDoor2',
+ doorRate = 1.0,
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/mrpd.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/mrpd.lua
new file mode 100644
index 0000000..e56fed8
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/mrpd.lua
@@ -0,0 +1,628 @@
+-- MRPD
+
+--Custody A?
+
+-- -103609059 created by Hawk
+Config.DoorList['MRPD_CustodyA6--103609059'] = {
+ doorRate = 1.0,
+ objYaw = 89.999961853028,
+ distance = 2,
+ objCoords = vec3(480.817292, -1014.956788, 30.612476),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '3960322',
+ objName = -1036090959,
+ autoLock = 5000
+}
+
+-- -103609059 created by Hawk
+Config.DoorList['MRPD_CustodyA5--103609059'] = {
+ doorRate = 1.0,
+ objYaw = 89.999961853028,
+ distance = 2,
+ objCoords = vec3(480.817292, -1010.842468, 30.612476),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '3960578',
+ objName = -1036090959,
+ autoLock = 5000
+}
+
+-- -103609059 created by Hawk
+Config.DoorList['MRPD_CustodyA4--103609059'] = {
+ doorRate = 1.0,
+ objYaw = 89.999961853028,
+ distance = 2,
+ objCoords = vec3(480.817352, -1006.746032, 30.612476),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '4028674',
+ objName = -1036090959,
+ autoLock = 5000
+}
+
+-- -103609059 created by Hawk
+Config.DoorList['MRPD_CustodyA3--103609059'] = {
+ doorRate = 1.0,
+ objYaw = 89.999961853028,
+ distance = 2,
+ objCoords = vec3(484.083068, -1014.943298, 30.612476),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '4028418',
+ objName = -1036090959,
+ autoLock = 5000
+}
+
+-- -103609059 created by Hawk
+Config.DoorList['MRPD_CustodyA2--103609059'] = {
+ doorRate = 1.0,
+ objYaw = 89.999961853028,
+ distance = 2,
+ objCoords = vec3(484.083068, -1010.842530, 30.612476),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '4027906',
+ objName = -1036090959,
+ autoLock = 5000
+}
+
+-- -103609059 created by Hawk
+Config.DoorList['MRPD_CustodyA1--103609059'] = {
+ doorRate = 1.0,
+ objYaw = 89.999961853028,
+ distance = 2,
+ objCoords = vec3(484.083130, -1006.736146, 30.612476),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '4028162',
+ objName = -1036090959,
+ autoLock = 5000
+}
+
+-- Custody B?
+
+-- -1036090959 created by Hawk
+Config.DoorList['Custody_B6--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(460.823852, -983.660828, 30.612476),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3849986',
+ objYaw = 1.0017911336036e-05,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['Custody_B5--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(464.938140, -983.660828, 30.612476),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3938562',
+ objYaw = 1.0017911336036e-05,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['Custody_B4--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(469.034606, -983.660888, 30.612476),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3991042',
+ objYaw = 1.0017911336036e-05,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['Custody_B3--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(460.837310, -986.926636, 30.612476),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3850242',
+ objYaw = 1.0017911336036e-05,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['Custody_B2--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(464.938080, -986.926636, 30.612476),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3938306',
+ objYaw = 1.0017911336036e-05,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['Custody_B1--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(469.044464, -986.926696, 30.612476),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3938050',
+ objYaw = 1.0017911336036e-05,
+ autoLock = 5000
+}
+
+--Pressroom
+
+-- 952639784 created by Hawk
+Config.DoorList['PressroomD1-952639784'] = {
+ doorType = 'double',
+ authorizedJobs = { ['police'] = 0 },
+ locked = false,
+ distance = 3,
+ doors = {
+ {objName = 952639784, objYaw = 180.00001525878, objCoords = vec3(437.124390, -989.491760, 30.873428)},
+ {objName = -1481015543, objYaw = 179.99998474122, objCoords = vec3(434.526550, -989.491760, 30.873428)}
+ },
+ doorLabel = '3680514',
+ doorRate = 1.0,
+}
+
+-- -824920418 created by Hawk
+Config.DoorList['PressroomD2-824920418'] = {
+ doorRate = 1.0,
+ objYaw = 90.0,
+ distance = 3,
+ objCoords = vec3(437.510040, -997.986634, 30.873428),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = false,
+ fixText = false,
+ doorLabel = '4668738',
+ objName = -824920418,
+}
+
+-- Entry-doors
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRPD_M_Entry--1481015543'] = {
+ doorType = 'double',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ distance = 2,
+ doors = {
+ {objName = -1481015543, objYaw = 89.999977111816, objCoords = vec3(449.522370, -980.361022, 30.874448)},
+ {objName = 952639784, objYaw = 89.999977111816, objCoords = vec3(449.522370, -982.958436, 30.874448)}
+ },
+ doorLabel = '3832578',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- 1847320387 created by Hawk
+Config.DoorList['MRPDParkingEntry-1847320387'] = {
+ doorType = 'double',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ distance = 3,
+ doors = {
+ {objName = 1847320387, objYaw = 360.0, objCoords = vec3(442.750886, -998.583802, 31.118602)},
+ {objName = -688443112, objYaw = 0.0, objCoords = vec3(440.114258, -998.584350, 31.118142)}
+ },
+ doorLabel = '36599522',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRPD_E_Entry--1481015543'] = {
+ doorType = 'double',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ distance = 2,
+ doors = {
+ {objName = -1481015543, objYaw = 270.00003051758, objCoords = vec3(445.918518, -995.031250, 30.874198)},
+ {objName = 952639784, objYaw = 270.00003051758, objCoords = vec3(445.918518, -992.436646, 30.874198)}
+ },
+ doorLabel = '3674114',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['MRDP_Back_Entry--1036090959'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = -1036090959, objYaw = 180.00001525878, objCoords = vec3(479.690888, -979.453002, 28.143826)},
+ {objName = -1036090959, objYaw = 0.0, objCoords = vec3(477.091370, -979.453002, 28.143826)}
+ },
+ doorType = 'double',
+ doorLabel = '4082434',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- Evidence Door
+
+-- 749848321 created by Hawk
+Config.DoorList['MRPD_EvidenceDoor-749848321'] = {
+ doorRate = 1.0,
+ objYaw = 89.999977111816,
+ distance = 2,
+ objCoords = vec3(468.018616, -998.500244, 30.611514),
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ fixText = false,
+ doorLabel = '3880706',
+ objName = 749848321,
+ autoLock = 10000
+}
+
+-- Storage
+
+-- -1036090959 created by Hawk
+Config.DoorList['MRDP_Storage--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(467.507172, -994.437988, 35.212628),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3885570',
+ objYaw = 134.99995422364,
+ autoLock = 10000
+}
+
+-- Forensics
+
+-- 161378502 created by Hawk
+Config.DoorList['MRDP_Forensics-161378502'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = 161378502, objYaw = 0.0, objCoords = vec3(480.575318, -1004.605590, 24.471722)},
+ {objName = -1572101598, objYaw = 1.0017911336036e-05, objCoords = vec3(477.975372, -1004.605590, 24.471722)}
+ },
+ doorType = 'doublesliding',
+ doorLabel = '4031490',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- Interrogation
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRDP_2IntA--1481015543'] = {
+ distance = 2,
+ objName = -1481015543,
+ objCoords = vec3(477.647492, -996.258484, 35.212360),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntA',
+ objYaw = 269.99996948242,
+ autoLock = 5000
+}
+
+-- -82420418 created by Hawk
+Config.DoorList['MRDP_2IntA1--82420418'] = {
+ distance = 2,
+ objName = -824920418,
+ objCoords = vec3(477.647492, -988.151062, 35.212360),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntA1',
+ objYaw = 269.99996948242,
+ autoLock = 5000
+}
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRDP_2IntB--1481015543'] = {
+ distance = 2,
+ objName = -1481015543,
+ objCoords = vec3(477.643096, -987.182006, 35.211696),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntB',
+ objYaw = 269.99996948242,
+ autoLock = 5000
+}
+
+-- -82420418 created by Hawk
+Config.DoorList['MRDP_2IntB1--82420418'] = {
+ distance = 2,
+ objName = -824920418,
+ objCoords = vec3(477.643830, -979.079346, 35.209060),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntB1',
+ objYaw = 269.99996948242,
+ autoLock = 5000
+}
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRDP_2IntC--1481015543'] = {
+ distance = 2,
+ objName = -1481015543,
+ objCoords = vec3(482.664460, -996.257568, 35.214234),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntC',
+ objYaw = 270.00003051758,
+ autoLock = 5000
+}
+
+-- -82420418 created by Hawk
+Config.DoorList['MRDP_2IntC1--82420418'] = {
+ distance = 2,
+ objName = -824920418,
+ objCoords = vec3(482.664460, -988.146362, 35.214234),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntC1',
+ objYaw = 270.00003051758,
+ autoLock = 5000
+}
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRDP_2IntD--1481015543'] = {
+ distance = 2,
+ objName = -1481015543,
+ objCoords = vec3(482.660064, -987.188050, 35.213570),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntD',
+ objYaw = 270.00003051758,
+ autoLock = 5000
+}
+
+-- -82420418 created by Hawk
+Config.DoorList['MRDP_2IntD1--82420418'] = {
+ distance = 2,
+ objName = -824920418,
+ objCoords = vec3(482.660798, -979.072022, 35.210934),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'IntD1',
+ objYaw = 270.00003051758,
+ autoLock = 5000
+}
+
+-- ARMOURY
+
+-- -1036090959 created by Hawk
+Config.DoorList['MRDP_Armoury--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(458.398224, -992.107056, 35.212628),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = '3791362',
+ objYaw = 315.0,
+ autoLock = 5000
+}
+
+-- 2nd Floor Doubles
+
+-- 952639784 created by Hawk
+Config.DoorList['MRDP_2Floor_Doubles-952639784'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = 952639784, objYaw = 89.999977111816, objCoords = vec3(455.546630, -988.383118, 35.212100)},
+ {objName = -1481015543, objYaw = 89.999977111816, objCoords = vec3(455.546630, -985.783264, 35.212100)}
+ },
+ doorType = 'double',
+ doorLabel = '3832322',
+ doorRate = 1.0,
+ autoLock = 15000
+}
+
+-- -1481015543 created by Hawk
+Config.DoorList['MRDP_2DoubleEntry--1481015543'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = -1481015543, objYaw = 270.00003051758, objCoords = vec3(470.490570, -1000.717712, 35.206952)},
+ {objName = 952639784, objYaw = 270.0, objCoords = vec3(470.489686, -998.117920, 35.206952)}
+ },
+ doorType = 'double',
+ doorLabel = '3886850',
+ doorRate = 1.0,
+ autoLock = 15000
+}
+
+-- Garage Entries
+
+-- 1255964982 created by Hawk
+Config.DoorList['MRDP_Garage_Doubles-1255964982'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = 1255964982, objYaw = 270.00003051758, objCoords = vec3(463.187622, -991.515686, 25.617482)},
+ {objName = 1255964982, objYaw = 90.000022888184, objCoords = vec3(463.187622, -988.916992, 25.617482)}
+ },
+ doorType = 'double',
+ doorLabel = '3880962',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- 1255964982 created by Hawk
+Config.DoorList['MRDP_Garage_Doubles2-1255964982'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = 1255964982, objYaw = 180.00001525878, objCoords = vec3(471.858216, -993.203370, 25.616542)},
+ {objName = 1255964982, objYaw = 1.0017911336036e-05, objCoords = vec3(474.457062, -993.203370, 25.616542)}
+ },
+ doorType = 'double',
+ doorLabel = '39121944',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- 1255964982 created by Hawk
+Config.DoorList['MRDP_Garage_Doubles2_Interior-1255964982'] = {
+ authorizedJobs = { ['police'] = 0 },
+ distance = 2,
+ locked = true,
+ doors = {
+ {objName = 1255964982, objYaw = 89.999977111816, objCoords = vec3(476.721894, -986.831298, 25.615550)},
+ {objName = 1255964982, objYaw = 270.00003051758, objCoords = vec3(476.721894, -989.433410, 25.615550)}
+ },
+ doorType = 'double',
+ doorLabel = '4025090',
+ doorRate = 1.0,
+ autoLock = 5000
+}
+
+-- HelipadDoors
+
+-- -1036090959 created by Hawk
+Config.DoorList['MRDP_Roof_Door--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(464.230468, -984.680420, 43.843894),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'HeliPadDoor',
+ objYaw = 90.000022888184,
+ autoLock = 5000
+}
+
+-- -1036090959 created by Hawk
+Config.DoorList['MRDP_Roof_Door_Interior--1036090959'] = {
+ distance = 2,
+ objName = -1036090959,
+ objCoords = vec3(463.323792, -982.196900, 38.760418),
+ doorType = 'door',
+ fixText = false,
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorRate = 1.0,
+ doorLabel = 'HeliPadDoorInterior',
+ objYaw = 270.00003051758,
+ autoLock = 5000
+}
+
+-- Garage doors
+
+-- -1195127879 created by Hawk
+Config.DoorList['MRPD_GarageDoor--1195127879'] = {
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorType = 'garage',
+ objName = -1195127879,
+ doorLabel = 'MRPD_FirstGarageDoor',
+ doorRate = 1.0,
+ fixText = false,
+ objCoords = vec3(433.815124, -999.920472, 26.115582),
+ distance = 5,
+ objYaw = 0.0,
+ autoLock = 10000,
+ remoteTrigger = true
+}
+
+-- -1195127879 created by Hawk
+Config.DoorList['MRPD_GarageDoor2--1195127879'] = {
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorType = 'garage',
+ objName = -1195127879,
+ doorLabel = 'MRPD_SecondGarageDoor',
+ doorRate = 1.0,
+ fixText = false,
+ objCoords = vec3(449.897766, -999.903198, 26.114242),
+ distance = 5,
+ objYaw = 0.0,
+ autoLock = 10000,
+ remoteTrigger = true
+}
+
+-- -1195127879 created by Hawk
+Config.DoorList['MRPD_GarageDoor3--1195127879'] = {
+ authorizedJobs = { ['police'] = 0 },
+ locked = true,
+ doorType = 'garage',
+ objName = -1195127879,
+ doorLabel = 'MRPD_ThirdGarageDoor',
+ doorRate = 1.0,
+ fixText = false,
+ objCoords = vec3(488.767578, -1021.413146, 28.898114),
+ distance = 5,
+ objYaw = 90.000022888184,
+ autoLock = 10000,
+ remoteTrigger = true
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/paletobank.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/paletobank.lua
new file mode 100644
index 0000000..3e2ac9d
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/paletobank.lua
@@ -0,0 +1,71 @@
+
+
+-- PaletoInteriorVault3 created by Hawk
+Config.DoorList['PaletoInteriorVault3-PaletoInteriorVault3'] = {
+ objYaw = 180,
+ doorRate = 2.0,
+ locked = true,
+ fixText = false,
+ objName = 1622278560,
+ objCoords = vec3(-104.813636, 6473.646484, 31.954800),
+ distance = 1,
+ authorizedJobs = { ['police'] = 0 },
+ doorType = 'door',
+ doorLabel = 'PaletoInteriorVault3',
+}
+
+-- PaletoInteriorVault created by Hawk
+Config.DoorList['PaletoInteriorVault-PaletoInteriorVault'] = {
+ authorizedJobs = { ['police'] = 0 },
+ doorRate = 1.0,
+ objCoords = vec3(-105.6242, 6474.6509, 31.6267),
+ locked = true,
+ fixText = false,
+ doorLabel = 'PaletoInteriorVault',
+ objName = 1309269072,
+ objYaw = 315.00006103516,
+ doorType = 'door',
+ distance = 3,
+}
+
+-- PaletoCashRegister created by Hawk
+Config.DoorList['PaletoCashRegister- PaletoCashRegister'] = {
+ objYaw = 45.000061035156,
+ objCoords = vec3(-108.914688, 6469.104980, 31.910284),
+ doorType = 'door',
+ fixText = false,
+ doorRate = 1.0,
+ locked = true,
+ distance = 0,
+ objName = -1184592117,
+ authorizedJobs = { ['police'] = 0 },
+ doorLabel = 'PaletoCashRegister',
+}
+
+-- UWUGarage created by Hawk
+Config.DoorList['UWUGarage-UWUGarage'] = {
+ doorLabel = 'UWUGarage',
+ doorType = 'garage',
+ distance = 2,
+ authorizedJobs = { ['uwu'] = 0 },
+ fixText = false,
+ locked = true,
+ objYaw = 270.00003051758,
+ objName = 522844070,
+ objCoords = vec3(-600.910584, -1059.217652, 21.721432),
+ doorRate = 1.0,
+}
+
+-- UWUFrontDoor created by Hawk
+Config.DoorList['UWUFrontDoor-UWUFrontDoor'] = {
+ locked = true,
+ doorType = 'double',
+ doors = {
+ {objName = 526179188, objYaw = 0.0, objCoords = vec3(-581.667786, -1069.627198, 22.489748)},
+ {objName = -69331849, objYaw = 0.0, objCoords = vec3(-580.361084, -1069.627198, 22.489748)}
+ },
+ distance = 5,
+ authorizedJobs = { ['uwu'] = 0 },
+ doorLabel = 'UWUFrontDoor',
+ doorRate = 1.0,
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/pillbox.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/pillbox.lua
new file mode 100644
index 0000000..876c765
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/pillbox.lua
@@ -0,0 +1,193 @@
+
+
+-- Pillbox Upper MRI created by Hawk
+Config.DoorList['PillboxMRIUpper-Pillbox Upper MRI'] = {
+ objYaw = 340.0,
+ doorLabel = 'MRI Dør',
+ doorRate = 1.0,
+ fixText = false,
+ distance = 2,
+ locked = false,
+ objCoords = vec3(309.252930, -570.573608, 43.395038),
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ objName = 1281019151,
+ doorType = 'door',
+}
+
+-- ElevatorPillbox1 created by Hawk
+Config.DoorList['ElevatorPillbox1-ElevatorPillbox1'] = {
+ doorRate = 1.0,
+ distance = 0,
+ locked = true,
+ doorLabel = 'ElevatorPillbox1',
+ doors = {
+ {objName = -1240156945, objYaw = 250.24739074708, objCoords = vec3(334.584960, -591.236450, 42.264454)},
+ {objName = -1240156945, objYaw = 69.999992370606, objCoords = vec3(334.071808, -592.646180, 42.264454)}
+ },
+ doorType = 'doublesliding',
+}
+
+-- ElevatorPillbox2 created by Hawk
+Config.DoorList['ElevatorPillbox2-ElevatorPillbox2'] = {
+ doorRate = 1.0,
+ distance = 0,
+ locked = true,
+ doorLabel = 'ElevatorPillbox2',
+ doors = {
+ {objName = -1240156945, objYaw = 249.99337768554, objCoords = vec3(335.764954, -587.991516, 42.269192)},
+ {objName = -1240156945, objYaw = 69.999992370606, objCoords = vec3(335.251832, -589.401246, 42.269192)}
+ },
+ doorType = 'doublesliding',
+}
+
+-- PillboxElevator3 created by Hawk
+Config.DoorList['PillboxElevator3-PillboxElevator3'] = {
+ doors = {
+ {objName = -1240156945, objYaw = 70.166603088378, objCoords = vec3(324.674682, -584.547302, 27.848122)},
+ {objName = -1240156945, objYaw = 250.00146484375, objCoords = vec3(325.187774, -583.137574, 27.848122)}
+ },
+ doorLabel = 'PillboxElevator3',
+ doorType = 'doublesliding',
+ locked = true,
+ doorRate = 1.0,
+ distance = 0,
+}
+
+-- Elevator4 created by Hawk
+Config.DoorList['Elevator4-Elevator4'] = {
+ distance = 0,
+ locked = true,
+ doorLabel = 'Elevator4',
+ doorRate = 1.0,
+ doors = {
+ {objName = -1240156945, objYaw = 69.99998474121, objCoords = vec3(323.490510, -587.791198, 27.847042)},
+ {objName = -1240156945, objYaw = 250.0, objCoords = vec3(324.003418, -586.381958, 27.847042)}
+ },
+ doorType = 'doublesliding',
+}
+
+-- PillboxMRIOBS created by Hawk
+Config.DoorList['PillboxMRIOBS-PillboxMRIOBS'] = {
+ objYaw = 250.00003051758,
+ doorLabel = 'PillboxMRIOBS',
+ doorRate = 1.0,
+ fixText = false,
+ distance = 1,
+ locked = true,
+ objCoords = vec3(311.624390, -570.570618, 43.395828),
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ objName = 1281019151,
+ doorType = 'door',
+}
+
+-- PillboxUpperEntry created by Hawk
+Config.DoorList['PillboxUpperEntry-PillboxUpperEntry'] = {
+ doorRate = 1.0,
+ distance = 5,
+ locked = false,
+ doorLabel = 'Hovedør',
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ doors = {
+ {objName = -923364535, objYaw = 250.0, objCoords = vec3(299.994964, -583.781250, 43.366504)},
+ {objName = -69142243, objYaw = 250.0, objCoords = vec3(299.220368, -585.875366, 43.371972)}
+ },
+ doorType = 'doublesliding',
+}
+
+-- Pillbox Observation Upper created by Hawk
+Config.DoorList['PillboxObservationUpper-Pillbox Observation Upper'] = {
+ objYaw = 340.0,
+ doorLabel = 'Observation Upper',
+ doorRate = 1.0,
+ fixText = false,
+ distance = 2,
+ locked = true,
+ objCoords = vec3(314.226990, -572.384034, 43.395038),
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ objName = 459631401,
+ doorType = 'door',
+}
+
+-- PillboxWardCDør created by Hawk
+Config.DoorList['PillboxWardCDør-PillboxWardCDør'] = {
+ doorRate = 1.0,
+ distance = 2,
+ locked = true,
+ doorLabel = 'PillboxWardCDør',
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ doors = {
+ {objName = 630194374, objYaw = 250.00003051758, objCoords = vec3(337.002136, -584.447326, 43.394818)},
+ {objName = 630194374, objYaw = 69.999992370606, objCoords = vec3(337.817626, -582.206848, 43.394818)}
+ },
+ doorType = 'double',
+}
+
+-- PillboxOBSXRAY created by Hawk
+Config.DoorList['PillboxOBSXRAY-PillboxOBSXRAY'] = {
+ objYaw = 250.00003051758,
+ doorLabel = 'PillboxOBSXRAY',
+ doorRate = 1.0,
+ fixText = false,
+ distance = 1,
+ locked = true,
+ objCoords = vec3(316.242492, -572.251464, 43.395828),
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ objName = 1281019151,
+ doorType = 'door',
+}
+
+-- PillboxWardAMellemdør created by Hawk
+Config.DoorList['PillboxWardAMellemdør-PillboxWardAMellemdør'] = {
+ doorRate = 1.0,
+ distance = 2,
+ locked = true,
+ doorLabel = 'PillboxWardAMellemdør',
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ doors = {
+ {objName = 1527147442, objYaw = 70.000030517578, objCoords = vec3(333.393464, -580.596558, 43.394822)},
+ {objName = 1527147442, objYaw = 250.00003051758, objCoords = vec3(332.579650, -582.837646, 43.394822)}
+ },
+ doorType = 'double',
+}
+
+-- PillboxXRAYUpper created by Hawk
+Config.DoorList['PillboxXRAYUpper-PillboxXRAYUpper'] = {
+ objYaw = 340.0,
+ doorLabel = 'PillboxXRAYUpper',
+ doorRate = 1.0,
+ fixText = false,
+ distance = 2,
+ locked = true,
+ objCoords = vec3(319.202302, -574.194886, 43.395038),
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ objName = 1281019151,
+ doorType = 'door',
+}
+
+-- PillboxUpperPauserum created by Hawk
+Config.DoorList['PillboxUpperPauserum-PillboxUpperPauserum'] = {
+ objYaw = 159.99998474122,
+ doorLabel = 'PillboxUpperPauserum',
+ doorRate = 1.0,
+ fixText = false,
+ distance = 2,
+ locked = true,
+ objCoords = vec3(310.535644, -591.911438, 43.395894),
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ objName = 102514839,
+ doorType = 'door',
+}
+
+-- PillboxWardBOuterEntry created by Hawk
+Config.DoorList['PillboxWardBOuterEntry-PillboxWardBOuterEntry'] = {
+ doorRate = 1.0,
+ distance = 3,
+ locked = false,
+ doorLabel = 'WardBYdreDøre',
+ authorizedJobs = { ['ambulance, police'] = 0 },
+ doors = {
+ {objName = 1527147442, objYaw = 160.0, objCoords = vec3(309.472930, -575.663392, 43.396018)},
+ {objName = 1527147442, objYaw = 340.0, objCoords = vec3(311.713044, -576.478698, 43.396018)}
+ },
+ doorType = 'double',
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/prison.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/prison.lua
new file mode 100644
index 0000000..e69de29
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/tequila.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/tequila.lua
new file mode 100644
index 0000000..717f910
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/tequila.lua
@@ -0,0 +1,85 @@
+
+
+-- tequila01 criado por GG. ! m.
+Config.DoorList['tequila-tequila01'] = {
+ objCoords = vec3(-563.887329, 276.516632, 83.286263),
+ doorRate = 1.0,
+ objYaw = 355.00003051758,
+ authorizedJobs = { ['tequilala'] = 0 },
+ doorLabel = 'tequila01',
+ fixText = false,
+ locked = true,
+ doorType = 'door',
+ distance = 2,
+ objName = -2037125726,
+}
+
+-- tequila02 criado por GG. ! m.
+Config.DoorList['tequila-tequila02'] = {
+ authorizedJobs = { ['tequilala'] = 0 },
+ doorLabel = 'tequila02',
+ doorRate = 1.0,
+ doors = {
+ {objName = 1888438146, objYaw = 355.00003051758, objCoords = vec3(-561.399963, 278.584595, 83.125275)},
+ {objName = 272205552, objYaw = 355.00003051758, objCoords = vec3(-559.460327, 278.414886, 83.124260)}
+ },
+ locked = true,
+ distance = 2,
+ doorType = 'double',
+}
+
+-- tequila03 criado por GG. ! m.
+Config.DoorList['tequila-tequila03'] = {
+ objCoords = vec3(-567.583252, 280.997650, 83.126434),
+ doorRate = 1.0,
+ objYaw = 355.00003051758,
+ authorizedJobs = { ['tequilala'] = 0 },
+ doorLabel = 'tequila03',
+ fixText = false,
+ locked = true,
+ doorType = 'door',
+ distance = 2,
+ objName = 1927676967,
+}
+
+-- tequila04 criado por GG. ! m.
+Config.DoorList['tequila-tequila04'] = {
+ objCoords = vec3(-567.935120, 291.926422, 85.524986),
+ doorRate = 1.0,
+ objYaw = 175.00003051758,
+ authorizedJobs = { ['tequilala'] = 0 },
+ doorLabel = 'tequila04',
+ fixText = false,
+ locked = true,
+ doorType = 'door',
+ distance = 2,
+ objName = 1927676967,
+}
+
+-- tequila05 criado por GG. ! m.
+Config.DoorList['tequila-tequila05'] = {
+ authorizedJobs = { ['tequilala'] = 0 },
+ doorLabel = 'tequila05',
+ doorRate = 1.0,
+ doors = {
+ {objName = 1888438146, objYaw = 265.00006103516, objCoords = vec3(-563.527100, 290.733093, 85.404839)},
+ {objName = 272205552, objYaw = 265.00006103516, objCoords = vec3(-563.696777, 288.794495, 85.404839)}
+ },
+ locked = true,
+ distance = 2,
+ doorType = 'double',
+}
+
+-- tequila06 criado por GG. ! m.
+Config.DoorList['tequila-tequila06'] = {
+ objCoords = vec3(-560.350647, 291.715027, 82.326088),
+ doorRate = 1.0,
+ objYaw = 265.00006103516,
+ authorizedJobs = { ['tequilala'] = 0 },
+ doorLabel = 'tequila06',
+ fixText = false,
+ locked = true,
+ doorType = 'door',
+ distance = 2,
+ objName = 1927676967,
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/uwu.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/uwu.lua
new file mode 100644
index 0000000..39955af
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/uwu.lua
@@ -0,0 +1,43 @@
+
+
+-- UWUGarage created by Hawk
+Config.DoorList['UWUGarage-UWUGarage'] = {
+ doorLabel = 'UWUGarage',
+ doorType = 'garage',
+ distance = 2,
+ authorizedJobs = { ['uwu'] = 0 },
+ fixText = false,
+ locked = true,
+ objYaw = 270.00003051758,
+ objName = 522844070,
+ objCoords = vec3(-600.910584, -1059.217652, 21.721432),
+ doorRate = 1.0,
+}
+
+-- UWUFrontDoor created by Hawk
+Config.DoorList['UWUFrontDoor-UWUFrontDoor'] = {
+ locked = true,
+ doorType = 'double',
+ doors = {
+ {objName = 526179188, objYaw = 0.0, objCoords = vec3(-581.667786, -1069.627198, 22.489748)},
+ {objName = -69331849, objYaw = 0.0, objCoords = vec3(-580.361084, -1069.627198, 22.489748)}
+ },
+ distance = 5,
+ authorizedJobs = { ['uwu'] = 0 },
+ doorLabel = 'UWUFrontDoor',
+ doorRate = 1.0,
+}
+
+-- UWUBackdoor created by Hawk
+Config.DoorList['UWUBackdoor-UWUBackdoor'] = {
+ doorLabel = 'UWUBackdoor',
+ doorType = 'door',
+ distance = 1,
+ authorizedJobs = { ['uwu'] = 0 },
+ fixText = false,
+ locked = true,
+ objYaw = 269.99996948242,
+ objName = 1099436502,
+ objCoords = vec3(-600.888610, -1055.131470, 22.713028),
+ doorRate = 1.0,
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/vange.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/vange.lua
new file mode 100644
index 0000000..67ac9d0
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/vange.lua
@@ -0,0 +1,15 @@
+
+
+-- vange created by Shrek
+Config.DoorList['vange-vange'] = {
+ doors = {
+ {objName = 1425919976, objYaw = 306.00003051758, objCoords = vec3(-631.955383, -236.333267, 38.206532)},
+ {objName = 9467943, objYaw = 306.00003051758, objCoords = vec3(-630.426514, -238.437546, 38.206532)}
+ },
+ doorLabel = 'vange',
+ doorRate = 1.0,
+ locked = true,
+ doorType = 'double',
+ distance = 2,
+ authorizedJobs = { ['police'] = 0 },
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/configs/vange2.lua b/resources/[qb]/[qb_core]/qb-doorlock/configs/vange2.lua
new file mode 100644
index 0000000..0930705
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/configs/vange2.lua
@@ -0,0 +1,15 @@
+
+
+-- vange2 created by Shrek
+Config.DoorList['vange2-vange2'] = {
+ objYaw = 36.000022888184,
+ objName = 1335309163,
+ distance = 2,
+ locked = true,
+ fixText = false,
+ doorType = 'door',
+ authorizedJobs = { ['police'] = 0 },
+ doorRate = 1.0,
+ objCoords = vec3(-629.133850, -230.151703, 38.206585),
+ doorLabel = 'vange2',
+}
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/fxmanifest.lua b/resources/[qb]/[qb_core]/qb-doorlock/fxmanifest.lua
new file mode 100644
index 0000000..65b29cc
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/fxmanifest.lua
@@ -0,0 +1,26 @@
+fx_version 'cerulean'
+game 'gta5'
+
+description 'Doorlock system for the QBCore Framework'
+version '2.0.0'
+
+ui_page 'html/index.html'
+
+shared_scripts {
+ 'config.lua',
+ 'configs/*.lua',
+ '@qb-core/shared/locale.lua',
+ 'locales/da.lua' -- Change this to your preferred language
+}
+
+server_script 'server/main.lua'
+client_script 'client/main.lua'
+
+files {
+ 'html/*.html',
+ 'html/*.js',
+ 'html/*.css',
+ 'html/sounds/*.ogg',
+}
+
+lua54 'yes'
\ No newline at end of file
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/html/app.js b/resources/[qb]/[qb_core]/qb-doorlock/html/app.js
new file mode 100644
index 0000000..0f68abd
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/html/app.js
@@ -0,0 +1,80 @@
+const app = Vue.createApp({
+ data() {
+ return {
+ coords: "",
+ heading: "",
+ hash: "",
+ doorlockStyleObject: {
+ "display": "none",
+ "background-color": "rgb(19, 28, 74)"
+ },
+ doorlockClassObject: {
+ "slide_in": false,
+ "slide_out": false
+ },
+ doorText: ""
+ }
+ },
+ mounted() {
+ this.listener = window.addEventListener("message", (event) => {
+ switch (event.data.type) {
+ case "setText":
+ this.setText(event.data);
+ break;
+ case "setDoorText":
+ this.setDoorText(event.data)
+ break;
+ case "audio":
+ this.playAudio(event.data)
+ break;
+ default:
+ break;
+ }
+ })
+ },
+ beforeUnmount() {
+ window.removeEventListener(this.listener);
+ },
+ methods: {
+ setText(data) {
+ if (data.aim) {
+ const element = document.getElementById("aim");
+ element.style.display = data.aim;
+ }
+
+ if (data.details) {
+ this.coords = data.coords;
+ this.heading = data.heading;
+ this.hash = data.hash;
+ const element = document.getElementById("textDetails");
+ element.style.display = data.details;
+ }
+ },
+ setDoorText(data) {
+ if (data.enable) {
+ if (this.doorlockStyleObject["display"] == "none") {
+ this.doorlockClassObject["slide_in"] = true;
+ this.doorlockStyleObject["display"] = "flex";
+ }
+ this.doorlockStyleObject["background-color"] = data.color;
+ this.doorText = data.text;
+ } else {
+ this.doorlockClassObject["slide_in"] = false;
+ this.doorlockClassObject["slide_out"] = true;
+ setTimeout(() => {
+ this.doorlockStyleObject["display"] = "none";
+ this.doorlockClassObject["slide_out"] = false;
+ this.doorText = "";
+ }, 1000);
+ }
+ },
+ playAudio(data) {
+ var volume = (data.audio['volume'] / 10) * data.sfx
+ if (data.distance !== 0) volume /= data.distance;
+ if (volume > 1.0) volume = 1.0;
+ const sound = new Audio('sounds/' + data.audio['file']);
+ sound.volume = volume;
+ sound.play();
+ }
+ }
+}).mount('#mainContainer');
diff --git a/resources/[qb]/[qb_core]/qb-doorlock/html/index.html b/resources/[qb]/[qb_core]/qb-doorlock/html/index.html
new file mode 100644
index 0000000..58e0203
--- /dev/null
+++ b/resources/[qb]/[qb_core]/qb-doorlock/html/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
{{ doorText }}
+
+
Sigt på døren. Tryk på venstre museknap for at bekræfte