diff --git a/resources/[defaultmaps]/dtpl_carrental/fxmanifest.lua b/resources/[defaultmaps]/dtpl_carrental/fxmanifest.lua
new file mode 100644
index 000000000..3f6cd83fa
--- /dev/null
+++ b/resources/[defaultmaps]/dtpl_carrental/fxmanifest.lua
@@ -0,0 +1,5 @@
+fx_version 'cerulean'
+games { 'gta5' }
+author 'DTPL 3D <3d@dtpl.cz>'
+description 'Touchdown Car Rental'
+version '1.0.1'
\ No newline at end of file
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/_dtplcarrent.ymf b/resources/[defaultmaps]/dtpl_carrental/stream/_dtplcarrent.ymf
new file mode 100644
index 000000000..09455cc04
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/_dtplcarrent.ymf differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark.ydr
new file mode 100644
index 000000000..988372a9c
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark.ydr differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark2.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark2.ydr
new file mode 100644
index 000000000..c59c70d28
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/ap1_03_td_cpark2.ydr differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.cwproj b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.cwproj
new file mode 100644
index 000000000..56a850537
--- /dev/null
+++ b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.cwproj
@@ -0,0 +1,21 @@
+
+ New CodeWalker Project
+
+
+ - dtpl_carrent.ymap
+ - hei_ap1_03_strm_2.ymap
+
+
+ - dtpl_carrent.ytyp
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ymap b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ymap
new file mode 100644
index 000000000..227126a09
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ymap differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ytyp b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ytyp
new file mode 100644
index 000000000..b4a05fb3e
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent.ytyp differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_col.ybn b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_col.ybn
new file mode 100644
index 000000000..948502977
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_col.ybn differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_doors.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_doors.ydr
new file mode 100644
index 000000000..27b3f519e
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_doors.ydr differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_shell.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_shell.ydr
new file mode 100644
index 000000000..d4b8571ce
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_shell.ydr differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_txd.ytd b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_txd.ytd
new file mode 100644
index 000000000..009ab9940
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/dtpl_carrent_txd.ytd differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_9.ybn b/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_9.ybn
new file mode 100644
index 000000000..4207679a8
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_9.ybn differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_strm_2.ymap b/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_strm_2.ymap
new file mode 100644
index 000000000..5582fdd2f
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/hei_ap1_03_strm_2.ymap differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/hi@hei_ap1_03_0.ybn b/resources/[defaultmaps]/dtpl_carrental/stream/hi@hei_ap1_03_0.ybn
new file mode 100644
index 000000000..b3e47d5a1
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/hi@hei_ap1_03_0.ybn differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03+hi.ytd b/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03+hi.ytd
new file mode 100644
index 000000000..12fdf6366
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03+hi.ytd differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03.ytd b/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03.ytd
new file mode 100644
index 000000000..6bb9bad95
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/rebrand-ext/ap1_03.ytd differ
diff --git a/resources/[defaultmaps]/dtpl_carrental/stream/rental_light.ydr b/resources/[defaultmaps]/dtpl_carrental/stream/rental_light.ydr
new file mode 100644
index 000000000..74042c980
Binary files /dev/null and b/resources/[defaultmaps]/dtpl_carrental/stream/rental_light.ydr differ
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/.fxap b/resources/[freizeit]/[rcore_tv]/rcore_television/.fxap
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/.fxap
rename to resources/[freizeit]/[rcore_tv]/rcore_television/.fxap
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/Debug.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/Debug.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/Debug.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/Debug.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/VIP.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/VIP.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/VIP.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/VIP.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/cache_event.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/cache_event.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/cache_event.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/cache_event.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/camera.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/camera.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/camera.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/camera.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/client_editable.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/client_editable.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/client_editable.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/client_editable.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/create_television.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/create_television.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/create_television.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/create_television.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/dui_events.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/dui_events.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/dui_events.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/dui_events.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/editor.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/editor.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/editor.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/editor.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/events.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/events.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/events.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/events.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/init.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/init.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/init.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/init.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/link.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/link.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/link.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/link.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/permission.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/permission.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/permission.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/permission.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/render_scaleform.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/render_scaleform.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/render_scaleform.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/render_scaleform.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/television_utils/menu.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/television_utils/menu.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/television_utils/menu.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/television_utils/menu.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/television_utils/program.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/television_utils/program.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/television_utils/program.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/television_utils/program.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/television_utils/volume.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/television_utils/volume.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/television_utils/volume.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/television_utils/volume.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/utils.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/utils.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/utils.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/utils.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/client/utils_editable.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/client/utils_editable.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/client/utils_editable.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/client/utils_editable.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/config.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/config.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/config.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/config.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/const.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/const.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/const.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/const.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/custom/client/events.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/custom/client/events.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/custom/client/events.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/custom/client/events.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/es_extended only.sql b/resources/[freizeit]/[rcore_tv]/rcore_television/es_extended only.sql
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/es_extended only.sql
rename to resources/[freizeit]/[rcore_tv]/rcore_television/es_extended only.sql
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/fxmanifest.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/fxmanifest.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/fxmanifest.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/fxmanifest.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/bootstrap.min.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/bootstrap.min.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/bootstrap.min.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/bootstrap.min.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/css/bootstrap.min.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/css/bootstrap.min.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/css/bootstrap.min.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/css/bootstrap.min.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/css/img/bg.jpg b/resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/css/img/bg.jpg
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/css/img/bg.jpg
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/css/img/bg.jpg
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/css/tv-menu.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/css/tv-menu.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/css/tv-menu.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/css/tv-menu.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/js/script.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/js/script.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/js/script.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/js/script.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/js/vue.min.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/js/vue.min.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/custom/menu/js/vue.min.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/custom/menu/js/vue.min.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/js/functions.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/js/functions.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/js/functions.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/js/functions.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/js/howler.min.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/js/howler.min.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/js/howler.min.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/js/howler.min.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/js/jquery.min.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/js/jquery.min.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/js/jquery.min.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/js/jquery.min.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/js/prefixfree.min.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/js/prefixfree.min.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/js/prefixfree.min.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/js/prefixfree.min.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/js/visualizer.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/js/visualizer.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/js/visualizer.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/js/visualizer.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/js/vue.min.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/js/vue.min.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/js/vue.min.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/js/vue.min.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/loaded.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/loaded.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/loaded.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/loaded.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/menu/css/img/bg.jpg b/resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/css/img/bg.jpg
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/menu/css/img/bg.jpg
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/css/img/bg.jpg
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/menu/css/tv-menu.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/css/tv-menu.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/menu/css/tv-menu.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/css/tv-menu.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/menu/menu.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/menu.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/menu/menu.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/menu.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/menu/script.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/script.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/menu/script.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/menu/script.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/off.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/off.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/off.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/off.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/bilibili/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/bilibili/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/bilibili/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/bilibili/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/douyin/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/douyin/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/douyin/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/douyin/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/music/css.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/music/css.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/music/css.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/music/css.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/music/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/music/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/music/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/music/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/other/css.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/other/css.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/other/css.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/other/css.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/other/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/other/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/other/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/other/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/readme.md b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/readme.md
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/readme.md
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/readme.md
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/twitch/css.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/twitch/css.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/twitch/css.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/twitch/css.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/twitch/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/twitch/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/twitch/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/twitch/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/video/css.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/video/css.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/video/css.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/video/css.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/video/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/video/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/video/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/video/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/youtube/css.css b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/youtube/css.css
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/youtube/css.css
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/youtube/css.css
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/youtube/index.html b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/youtube/index.html
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/youtube/index.html
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/youtube/index.html
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/html/support/youtube/yt-player.js b/resources/[freizeit]/[rcore_tv]/rcore_television/html/support/youtube/yt-player.js
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/html/support/youtube/yt-player.js
rename to resources/[freizeit]/[rcore_tv]/rcore_television/html/support/youtube/yt-player.js
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/locales/en.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/locales/en.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/locales/en.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/locales/en.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/server/server.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/server/server.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/server/server.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/server/server.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/utils/client.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/utils/client.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/utils/client.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/utils/client.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/utils/server.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/utils/server.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/utils/server.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/utils/server.lua
diff --git a/resources/[standalone]/[rcore_tv]/rcore_television/utils/shared.lua b/resources/[freizeit]/[rcore_tv]/rcore_television/utils/shared.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/rcore_television/utils/shared.lua
rename to resources/[freizeit]/[rcore_tv]/rcore_television/utils/shared.lua
diff --git a/resources/[standalone]/[rcore_tv]/readme.md b/resources/[freizeit]/[rcore_tv]/readme.md
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/readme.md
rename to resources/[freizeit]/[rcore_tv]/readme.md
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/.fxap b/resources/[freizeit]/[rcore_tv]/tv_scaleform/.fxap
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/.fxap
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/.fxap
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/fxmanifest.lua b/resources/[freizeit]/[rcore_tv]/tv_scaleform/fxmanifest.lua
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/fxmanifest.lua
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/fxmanifest.lua
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_1.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_1.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_1.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_1.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_2.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_2.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_2.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_2.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_3.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_3.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_3.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_3.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_4.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_4.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_4.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_4.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_5.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_5.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_5.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_5.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_6.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_6.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_6.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_6.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_7.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_7.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_7.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_7.gfx
diff --git a/resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_8.gfx b/resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_8.gfx
similarity index 100%
rename from resources/[standalone]/[rcore_tv]/tv_scaleform/stream/television_scaleform_8.gfx
rename to resources/[freizeit]/[rcore_tv]/tv_scaleform/stream/television_scaleform_8.gfx
diff --git a/resources/[standalone]/vms_firework/README.md b/resources/[freizeit]/vms_firework/README.md
similarity index 100%
rename from resources/[standalone]/vms_firework/README.md
rename to resources/[freizeit]/vms_firework/README.md
diff --git a/resources/[standalone]/vms_firework/client.lua b/resources/[freizeit]/vms_firework/client.lua
similarity index 100%
rename from resources/[standalone]/vms_firework/client.lua
rename to resources/[freizeit]/vms_firework/client.lua
diff --git a/resources/[standalone]/vms_firework/config.lua b/resources/[freizeit]/vms_firework/config.lua
similarity index 100%
rename from resources/[standalone]/vms_firework/config.lua
rename to resources/[freizeit]/vms_firework/config.lua
diff --git a/resources/[standalone]/vms_firework/fxmanifest.lua b/resources/[freizeit]/vms_firework/fxmanifest.lua
similarity index 100%
rename from resources/[standalone]/vms_firework/fxmanifest.lua
rename to resources/[freizeit]/vms_firework/fxmanifest.lua
diff --git a/resources/[standalone]/vms_firework/server.lua b/resources/[freizeit]/vms_firework/server.lua
similarity index 100%
rename from resources/[standalone]/vms_firework/server.lua
rename to resources/[freizeit]/vms_firework/server.lua
diff --git a/resources/[inventory]/cs_shops/config/config.lua b/resources/[inventory]/cs_shops/config/config.lua
index 2e8f8c274..8d480f2e4 100644
--- a/resources/[inventory]/cs_shops/config/config.lua
+++ b/resources/[inventory]/cs_shops/config/config.lua
@@ -1485,13 +1485,7 @@ CodeStudio.Products = {
itemName = "AR-15",
itemStock = 50,
itemPrice = 0,
- itemInfo = "Versatile rifle with attachments",
- itemMetaData = { -- Also Supports Adding Attachement's [Example: For QBCore Server]
- attachments = {
- { component = 'flashlight_attachment', label = 'Flashlight' },
- { component = 'holoscope_attachment', label = '3x Scope' },
- }
- }
+ itemInfo = "",
},
['weapon_nightstick'] = {
itemName = "Schlagstok",
diff --git a/resources/[inventory]/cs_shops/config/functions/sv_function.lua b/resources/[inventory]/cs_shops/config/functions/sv_function.lua
index a75a7ea4c..4863bdd60 100644
--- a/resources/[inventory]/cs_shops/config/functions/sv_function.lua
+++ b/resources/[inventory]/cs_shops/config/functions/sv_function.lua
@@ -93,16 +93,45 @@ function RemovePlayerMoney(player, amount, bank)
end
function AddItem(source, item, amount, metadata)
- if not metadata then metadata = {} end
+ -- Initialize metadata if not provided
+ metadata = metadata or {}
+
if GetResourceState('ox_inventory') == 'started' then
exports['ox_inventory']:AddItem(source, item, amount, metadata)
+
elseif GetResourceState('qs-inventory') == 'started' then
exports['qs-inventory']:AddItem(source, item, amount, false, metadata)
+
elseif GetResourceState('tgiann-inventory') == 'started' then
- exports["tgiann-inventory"]:AddItem(source, item, amount, slot, metadata, isClotheSlot)
+ -- For tgiann-inventory, we need to handle weapons differently
+ local upperItem = string.upper(tostring(item))
+
+ if string.match(upperItem, "WEAPON_") then
+ -- Create a completely new metadata table for weapons to avoid any reference issues
+ local weaponMetadata = {
+ -- Always use a string for serie, generated fresh each time
+ serie = tostring(math.random(100000, 999999)),
+ -- Copy any existing metadata values that should be preserved
+ ammo = metadata.ammo or 0,
+ quality = metadata.quality or 100
+ }
+
+ -- Debug output to verify the metadata structure
+ print("Adding weapon: " .. item)
+ print("Metadata: serie=" .. weaponMetadata.serie .. ", type=" .. type(weaponMetadata.serie))
+
+ -- Use the clean weapon metadata instead of the original
+ exports["tgiann-inventory"]:AddItem(source, item, amount, nil, weaponMetadata, nil)
+ else
+ -- For non-weapon items, use the original metadata
+ exports["tgiann-inventory"]:AddItem(source, item, amount, nil, metadata, nil)
+ end
+
elseif GetResourceState('origen_inventory') == 'started' then
exports['origen_inventory']:addItem(source, item, amount, metadata, false)
+
else
+ -- Default handling for QB/ESX
local Player = GetPlayer(source)
if CodeStudio.ServerType == 'QB' then
Player.Functions.AddItem(item, amount, nil, metadata)
@@ -112,6 +141,9 @@ function AddItem(source, item, amount, metadata)
end
end
+
+
+
function BuyItems(data)
local item = data.item
local amount = tonumber(data.amount) or 1
diff --git a/resources/[inventory]/nordi_schredder/client.lua b/resources/[inventory]/nordi_schredder/client.lua
new file mode 100644
index 000000000..c4af2bd2d
--- /dev/null
+++ b/resources/[inventory]/nordi_schredder/client.lua
@@ -0,0 +1,261 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+-- Müllschredder Locations mit Props
+local shredderLocations = {
+ {
+ coords = vector3(287.5, -1334.5, 29.3),
+ heading = 0.0,
+ prop = 'prop_dumpster_4' -- Ändere hier das Prop
+ },
+ {
+ coords = vector3(148.54, 269.21, 109.97),
+ heading = 90.0,
+ prop = 'prop_bin_08a' -- Anderes Prop Beispiel
+ }
+}
+
+local createdProps = {}
+
+-- Erstelle Müllschredder Props und Targets
+Citizen.CreateThread(function()
+ for i, location in ipairs(shredderLocations) do
+ -- Prop Model laden
+ local model = GetHashKey(location.prop)
+ RequestModel(model)
+ while not HasModelLoaded(model) do
+ Wait(1)
+ end
+
+ -- Prop erstellen
+ local shredder = CreateObject(model, location.coords.x, location.coords.y, location.coords.z, false, false, false)
+ SetEntityHeading(shredder, location.heading)
+ FreezeEntityPosition(shredder, true)
+ SetEntityInvincible(shredder, true)
+
+ table.insert(createdProps, shredder)
+
+ -- QB-Target hinzufügen
+ exports['qb-target']:AddTargetEntity(shredder, {
+ options = {
+ {
+ type = "client",
+ event = "shredder:openInventory",
+ icon = "fas fa-dumpster",
+ label = "Müllschredder öffnen",
+ canInteract = function()
+ return true
+ end,
+ },
+ {
+ type = "client",
+ event = "shredder:openMenu",
+ icon = "fas fa-fire",
+ label = "Items vernichten",
+ canInteract = function()
+ return true
+ end,
+ }
+ },
+ distance = 2.0
+ })
+ end
+end)
+
+-- Schredder Inventar öffnen
+RegisterNetEvent('shredder:openInventory', function()
+ local playerPed = PlayerPedId()
+ local coords = GetEntityCoords(playerPed)
+
+ -- Prüfen ob Spieler nah genug an einem Schredder ist
+ local nearShredder = false
+ for i, location in ipairs(shredderLocations) do
+ local distance = #(coords - location.coords)
+ if distance <= 3.0 then
+ nearShredder = true
+ break
+ end
+ end
+
+ if not nearShredder then
+ lib.notify({
+ title = 'Müllschredder',
+ description = 'Du bist zu weit vom Schredder entfernt!',
+ type = 'error'
+ })
+ return
+ end
+
+ -- Schredder Inventar öffnen
+ TriggerServerEvent('shredder:server:openInventory')
+end)
+
+-- Vernichtungsmenü öffnen
+RegisterNetEvent('shredder:openMenu', function()
+ local playerPed = PlayerPedId()
+ local coords = GetEntityCoords(playerPed)
+
+ -- Prüfen ob Spieler nah genug an einem Schredder ist
+ local nearShredder = false
+ for i, location in ipairs(shredderLocations) do
+ local distance = #(coords - location.coords)
+ if distance <= 3.0 then
+ nearShredder = true
+ break
+ end
+ end
+
+ if not nearShredder then
+ lib.notify({
+ title = 'Müllschredder',
+ description = 'Du bist zu weit vom Schredder entfernt!',
+ type = 'error'
+ })
+ return
+ end
+
+ TriggerServerEvent('shredder:server:getItems')
+end)
+
+-- Menü mit Items anzeigen
+RegisterNetEvent('shredder:client:showMenu', function(items)
+ if not items or #items == 0 then
+ lib.notify({
+ title = 'Müllschredder',
+ description = 'Der Schredder ist leer!',
+ type = 'error'
+ })
+ return
+ end
+
+ local menuOptions = {}
+
+ -- Alle Items vernichten Option
+ table.insert(menuOptions, {
+ title = '🔥 ALLE ITEMS VERNICHTEN',
+ description = 'Vernichtet alle Items im Schredder permanent!',
+ icon = 'fire',
+ onSelect = function()
+ confirmDestroyAll()
+ end
+ })
+
+ table.insert(menuOptions, {
+ title = '─────────────────',
+ description = 'Einzelne Items:',
+ disabled = true
+ })
+
+ -- Einzelne Items zum Menü hinzufügen
+ for slot, item in pairs(items) do
+ if item and item.amount and item.amount > 0 then
+ table.insert(menuOptions, {
+ title = (item.label or item.name),
+ description = 'Anzahl: ' .. item.amount .. ' | Slot: ' .. slot,
+ icon = 'trash',
+ onSelect = function()
+ confirmDestroySingle(item.name, item.amount, slot)
+ end
+ })
+ end
+ end
+
+ lib.registerContext({
+ id = 'shredder_menu',
+ title = '🗑️ Müllschredder Verwaltung',
+ options = menuOptions
+ })
+
+ lib.showContext('shredder_menu')
+end)
+
+-- Einzelnes Item vernichten bestätigen
+function confirmDestroySingle(itemName, amount, slot)
+ lib.registerContext({
+ id = 'shred_single_confirm',
+ title = '⚠️ Item vernichten?',
+ options = {
+ {
+ title = '🔥 Ja, vernichten',
+ description = itemName .. ' (' .. amount .. 'x) wird permanent gelöscht!',
+ icon = 'check',
+ onSelect = function()
+ TriggerServerEvent('shredder:server:destroySingle', itemName, amount, slot)
+ end
+ },
+ {
+ title = '❌ Abbrechen',
+ description = 'Zurück zum Hauptmenü',
+ icon = 'times',
+ onSelect = function()
+ TriggerServerEvent('shredder:server:getItems')
+ end
+ }
+ }
+ })
+
+ lib.showContext('shred_single_confirm')
+end
+
+-- Alle Items vernichten bestätigen
+function confirmDestroyAll()
+ lib.registerContext({
+ id = 'shred_all_confirm',
+ title = '⚠️ WARNUNG ⚠️',
+ options = {
+ {
+ title = '🔥 JA, ALLES VERNICHTEN',
+ description = 'ALLE Items im Schredder werden permanent gelöscht!',
+ icon = 'fire',
+ onSelect = function()
+ TriggerServerEvent('shredder:server:destroyAll')
+ end
+ },
+ {
+ title = '❌ Abbrechen',
+ description = 'Zurück zum Hauptmenü',
+ icon = 'times',
+ onSelect = function()
+ TriggerServerEvent('shredder:server:getItems')
+ end
+ }
+ }
+ })
+
+ lib.showContext('shred_all_confirm')
+end
+
+-- Erfolgs-Notification mit Effekt
+RegisterNetEvent('shredder:client:itemDestroyed', function(message)
+ lib.notify({
+ title = 'Müllschredder',
+ description = message,
+ type = 'success',
+ duration = 4000
+ })
+
+ -- Partikel-Effekt
+ local playerPed = PlayerPedId()
+ local coords = GetEntityCoords(playerPed)
+
+ RequestNamedPtfxAsset("core")
+ while not HasNamedPtfxAssetLoaded("core") do
+ Wait(1)
+ end
+
+ UseParticleFxAssetNextCall("core")
+ StartParticleFxNonLoopedAtCoord("ent_sht_steam", coords.x, coords.y, coords.z + 1.0, 0.0, 0.0, 0.0, 2.0, false, false, false)
+
+ -- Sound Effect
+ PlaySoundFrontend(-1, "CHECKPOINT_PERFECT", "HUD_MINI_GAME_SOUNDSET", 1)
+end)
+
+-- Cleanup beim Resource Stop
+AddEventHandler('onResourceStop', function(resourceName)
+ if GetCurrentResourceName() == resourceName then
+ for _, prop in pairs(createdProps) do
+ if DoesEntityExist(prop) then
+ DeleteEntity(prop)
+ end
+ end
+ end
+end)
diff --git a/resources/[inventory]/nordi_schredder/fxmanifest.lua b/resources/[inventory]/nordi_schredder/fxmanifest.lua
new file mode 100644
index 000000000..24ce28025
--- /dev/null
+++ b/resources/[inventory]/nordi_schredder/fxmanifest.lua
@@ -0,0 +1,25 @@
+fx_version 'cerulean'
+game 'gta5'
+
+author 'YourName'
+description 'Müllschredder mit separatem Inventar für tgiann-inventory'
+version '1.0.0'
+
+shared_scripts {
+ '@ox_lib/init.lua'
+}
+
+client_scripts {
+ 'client.lua'
+}
+
+server_scripts {
+ 'server.lua'
+}
+
+dependencies {
+ 'qb-core',
+ 'qb-target',
+ 'ox_lib',
+ 'tgiann-inventory'
+}
diff --git a/resources/[inventory]/nordi_schredder/server.lua b/resources/[inventory]/nordi_schredder/server.lua
new file mode 100644
index 000000000..051fc2c0d
--- /dev/null
+++ b/resources/[inventory]/nordi_schredder/server.lua
@@ -0,0 +1,108 @@
+local QBCore = exports['qb-core']:GetCoreObject()
+
+-- Schredder Inventar öffnen
+RegisterNetEvent('shredder:server:openInventory', function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+
+ if not Player then return end
+
+ -- Schredder Inventar öffnen (tgiann-inventory)
+ exports['tgiann-inventory']:OpenInventory(src, 'stash', 'shredder_' .. src, {
+ maxweight = 50000, -- 50kg max
+ slots = 20, -- 20 Slots
+ label = 'Müllschredder'
+ })
+end)
+
+-- Items aus Schredder abrufen
+RegisterNetEvent('shredder:server:getItems', function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+
+ if not Player then return end
+
+ -- Schredder Inventar Items abrufen
+ local stashId = 'shredder_' .. src
+ local items = exports['tgiann-inventory']:GetInventory(stashId)
+
+ TriggerClientEvent('shredder:client:showMenu', src, items or {})
+end)
+
+-- Einzelnes Item vernichten
+RegisterNetEvent('shredder:server:destroySingle', function(itemName, amount, slot)
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+
+ if not Player then return end
+
+ local stashId = 'shredder_' .. src
+
+ -- Item aus Schredder entfernen
+ local success = exports['tgiann-inventory']:RemoveItemFromInventory(stashId, itemName, amount, slot)
+
+ if success then
+ -- Log für Admins
+ print('^3[SHREDDER]^7 ' .. GetPlayerName(src) .. ' (' .. Player.PlayerData.citizenid .. ') hat ' .. amount .. 'x ' .. itemName .. ' vernichtet')
+
+ -- Discord Webhook
+ TriggerEvent('qb-log:server:CreateLog', 'shredder', 'Item Vernichtet', 'orange',
+ '**Spieler:** ' .. GetPlayerName(src) .. '\n**Citizen ID:** ' .. Player.PlayerData.citizenid .. '\n**Item:** ' .. amount .. 'x ' .. itemName .. '\n**Aktion:** Einzelnes Item vernichtet')
+
+ TriggerClientEvent('shredder:client:itemDestroyed', src, amount .. 'x ' .. itemName .. ' wurde vernichtet!')
+
+ -- Menü neu laden
+ Wait(1000)
+ TriggerEvent('shredder:server:getItems', src)
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'Fehler beim Vernichten des Items!', 'error')
+ end
+end)
+
+-- Alle Items vernichten
+RegisterNetEvent('shredder:server:destroyAll', function()
+ local src = source
+ local Player = QBCore.Functions.GetPlayer(src)
+
+ if not Player then return end
+
+ local stashId = 'shredder_' .. src
+ local items = exports['tgiann-inventory']:GetInventory(stashId)
+
+ if not items or next(items) == nil then
+ TriggerClientEvent('QBCore:Notify', src, 'Der Schredder ist bereits leer!', 'error')
+ return
+ end
+
+ local destroyedItems = {}
+ local totalItems = 0
+
+ -- Alle Items vernichten
+ for slot, item in pairs(items) do
+ if item and item.amount and item.amount > 0 then
+ local success = exports['tgiann-inventory']:RemoveItemFromInventory(stashId, item.name, item.amount, slot)
+ if success then
+ table.insert(destroyedItems, {name = item.name, amount = item.amount})
+ totalItems = totalItems + item.amount
+ end
+ end
+ end
+
+ if #destroyedItems > 0 then
+ -- Log für Admins
+ print('^3[SHREDDER]^7 ' .. GetPlayerName(src) .. ' (' .. Player.PlayerData.citizenid .. ') hat ALLE Items vernichtet (' .. totalItems .. ' Items)')
+
+ -- Discord Webhook mit Item Liste
+ local itemList = ""
+ for _, item in pairs(destroyedItems) do
+ itemList = itemList .. '• ' .. item.amount .. 'x ' .. item.name .. '\n'
+ end
+
+ TriggerEvent('qb-log:server:CreateLog', 'shredder', 'Alle Items Vernichtet', 'red',
+ '**Spieler:** ' .. GetPlayerName(src) .. '\n**Citizen ID:** ' .. Player.PlayerData.citizenid .. '\n**Aktion:** Alle Items vernichtet\n**Anzahl Items:** ' .. totalItems .. '\n**Items:**\n' .. itemList)
+
+ TriggerClientEvent('shredder:client:itemDestroyed', src, 'ALLE Items (' .. totalItems .. ' Stück) wurden vernichtet!')
+ else
+ TriggerClientEvent('QBCore:Notify', src, 'Keine Items zum Vernichten gefunden!', 'error')
+ end
+end)
diff --git a/resources/[inventory]/tgiann-inventory/items/items.lua b/resources/[inventory]/tgiann-inventory/items/items.lua
index cb12ca7dc..e28e5a5c1 100644
--- a/resources/[inventory]/tgiann-inventory/items/items.lua
+++ b/resources/[inventory]/tgiann-inventory/items/items.lua
@@ -4783,7 +4783,7 @@ itemsData = {
useable = true,
weight = 150,
type = 'item',
- unique = false,
+ unique = true,
description = 'Spritzig, lecker, absolut neu und revolutionär. Ähnlichkeiten zu anderen Limos? Niemals. Reinste Zufälle. Wirklich.',
image = 'spazi_limo.png',
shouldClose = true,
@@ -8574,7 +8574,7 @@ itemsData = {
type = 'item',
unique = true,
description = 'Kult-Getränk aus Japan: Erfrischende Limonade mit fruchtigem Geschmack und der typischen Glasmurmel',
- image = 'marblepop.png',
+ image = 'marble_pop_limo.png',
shouldClose = true,
label = 'Marble Pop Limo',
name = 'marble_pop_limo',
diff --git a/resources/[inventory]/tgiann-inventory/items/weapons.lua b/resources/[inventory]/tgiann-inventory/items/weapons.lua
index 309457b51..d5f923468 100644
--- a/resources/[inventory]/tgiann-inventory/items/weapons.lua
+++ b/resources/[inventory]/tgiann-inventory/items/weapons.lua
@@ -72,7 +72,7 @@ local weaponsList = {
-- Assault Rifles
weapon_assaultrifle = { name = 'weapon_assaultrifle', label = 'AK 75', weight = 1000, ammotype = 'AMMO_RIFLE', image = 'weapon_assaultrifle.png', description = 'A rapid-fire, magazine-fed automatic rifle designed for infantry use' },
weapon_assaultrifle_mk2 = { name = 'weapon_assaultrifle_mk2', label = 'Assault Rifle Mk II', weight = 1000, ammotype = 'AMMO_RIFLE', image = 'weapon_assaultrifle_mk2.png', description = 'Assault Rifle MK2' },
- weapon_carbinerifle = { name = 'weapon_carbinerifle', label = 'AR 15', weight = 1000, ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle.png', description = 'A light weight automatic rifle' },
+ weapon_carbinerifle = { name = 'weapon_carbinerifle', label = 'AR 15', weight = 1000, ammotype = 'AMMO_RIFLE', image = 'weapon_carbinerifle.png', description = 'Carbine Rifle' }, weight automatic rifle' },
weapon_carbinerifle_mk2 = { name = 'weapon_carbinerifle_mk2', label = 'Trainings Gewehr', weight = 1000, ammotype = 'AMMO_TRAINING', image = 'weapon_carbinerifle_mk2.png', description = 'Carbine Rifle MK2' },
weapon_advancedrifle = { name = 'weapon_advancedrifle', label = 'Advanced Rifle', weight = 1000, ammotype = 'AMMO_RIFLE', image = 'weapon_advancedrifle.png', description = 'An assault version of a rapid-fire, magazine-fed automatic rifle designed for infantry use' },
weapon_specialcarbine = { name = 'weapon_specialcarbine', label = 'KH 450', weight = 1000, ammotype = 'AMMO_RIFLE', image = 'weapon_specialcarbine.png', description = 'An extremely versatile assault rifle for any combat situation' },
diff --git a/resources/[inventory]/tgiann-weapons-on-back/.fxap b/resources/[inventory]/tgiann-weapons-on-back/.fxap
new file mode 100644
index 000000000..f01780bd6
Binary files /dev/null and b/resources/[inventory]/tgiann-weapons-on-back/.fxap differ
diff --git a/resources/[inventory]/tgiann-weapons-on-back/checkInv.lua b/resources/[inventory]/tgiann-weapons-on-back/checkInv.lua
new file mode 100644
index 000000000..c7a602bab
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/checkInv.lua
@@ -0,0 +1,28 @@
+config.useDefaultInventory = true
+
+local function log(msg)
+ print(string.format('\x1b[32m[tgiann-weapons-on-back]\x1b[0m %s', msg))
+end
+
+-- Chezza Studios inventory works fine with normal esx(don't add to the list)
+local inventorys = {
+ "tgiann-inventory",
+ "mf-inventory",
+ "ox_inventory",
+ "core_inventory",
+ "qs-inventory",
+ "codem-inventory",
+ "origen_inventory"
+}
+
+for i = 1, #inventorys do
+ local inventory = inventorys[i]
+ local isStarted = GetResourceState(inventory) == "started"
+ if isStarted then
+ config[inventory] = true
+ config.useDefaultInventory = false
+ log(string.format("Started with %s inventory", inventory))
+ end
+end
+
+if config.useDefaultInventory then log(string.format("Started with %s default inventory", config.framework == "qb" and "QB" or "ESX")) end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/codem_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/codem_inv.lua
new file mode 100644
index 000000000..490b46e57
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/codem_inv.lua
@@ -0,0 +1,89 @@
+if not config["codem-inventory"] then return end
+
+local playerJob = ""
+local lastItems = {}
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ SetTimeout(2000, function() -- some waiting time because the character's inventory data is loaded later
+ lastItems = exports['codem-inventory']:GetClientPlayerInventory()
+ weaponCheck()
+ end)
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+RegisterNetEvent('codem-inventory:client:additem')
+AddEventHandler('codem-inventory:client:additem', function(slot, data)
+ lastItems[tostring(slot)] = data
+ weaponCheck()
+end)
+
+RegisterNetEvent('codem-inventory:client:removeitemtoclientInventory')
+AddEventHandler('codem-inventory:client:removeitemtoclientInventory', function(slot, amount)
+ slot = tostring(slot)
+ if lastItems[slot] then
+ local itemAmount = lastItems[slot].count or lastItems[slot].amount
+ if itemAmount == amount then
+ lastItems[slot] = nil
+ end
+ end
+ weaponCheck()
+end)
+
+RegisterNetEvent('codem-inventory:client:clearinventory')
+AddEventHandler('codem-inventory:client:clearinventory', function()
+ lastItems = {}
+ weaponCheck()
+end)
+
+RegisterNetEvent('codem-inventory:client:setitembyslot')
+AddEventHandler('codem-inventory:client:setitembyslot', function(slot, itemData)
+ lastItems[tostring(slot)] = itemData
+ weaponCheck()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if key == item.info?.serie or item.name then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ if not lastItems then return end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and item.type == "weapon" then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item?.info?.serie or item.name,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info.attachments,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/core_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/core_inv.lua
new file mode 100644
index 000000000..4c3a8ae84
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/core_inv.lua
@@ -0,0 +1,116 @@
+-- https://docs.c8re.store/core-inventory/api
+if not config.core_inventory then return end
+
+local function splitStr(str, delimiter)
+ local result = {}
+ local from = 1
+ local delim_from, delim_to = string.find(str, delimiter, from)
+ while delim_from do
+ result[#result + 1] = string.sub(str, from, delim_from - 1)
+ from = delim_to + 1
+ delim_from, delim_to = string.find(str, delimiter, from)
+ end
+ result[#result + 1] = string.sub(str, from)
+ return result
+end
+
+local playerJob = ""
+local invItems = {}
+local playerItems = {}
+
+local function getInventoryItems()
+ tgiCore.cbFunction('tgiann-weapons-on-back:core_inventory:server:getInventory', function(newPlayerItems)
+ playerItems = newPlayerItems
+ weaponCheck(true)
+ end)
+end
+
+RegisterNetEvent('core_inventory:client:sync', function(inventory, data)
+ local split = splitStr(inventory, '-')[1]
+ if config.enableInv[split] then
+ playerItems[split] = data.content
+ end
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ if not PlayerData then return end
+ playerJob = PlayerData.job.name
+ getInventoryItems(PlayerData.identifier)
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck(false)
+end)
+
+if config.framework == "qb" then
+ RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
+ playerJob = PlayerData.job.name
+ if not config.enableInv["content"] then return end
+ playerItems["content"] = PlayerData?.items
+ weaponCheck(true)
+ end)
+else
+ RegisterNetEvent('esx:addInventoryItem')
+ AddEventHandler('esx:addInventoryItem', function(job)
+ local PlayerData = exports["tgiann-core"]:getPlayerData()
+ if not PlayerData then return end
+ getInventoryItems(PlayerData.identifier)
+ end)
+
+ RegisterNetEvent('esx:removeInventoryItem')
+ AddEventHandler('esx:removeInventoryItem', function(job)
+ local PlayerData = exports["tgiann-core"]:getPlayerData()
+ if not PlayerData then return end
+ getInventoryItems(PlayerData.identifier)
+ end)
+end
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(invItems) do
+ if item and key == (item.metadata?.serial or item.name) then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck(updateData)
+ if updateData then
+ invItems = {}
+ for _, inv in pairs(playerItems) do
+ for _, item in pairs(inv) do
+ invItems[#invItems + 1] = item
+ end
+ end
+ end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(invItems) do
+ if item and string.find(string.lower(item.name), "weapon") then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.metadata?.serial or item.name,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.metadata.tgiattachments, joaat(item.name)) or item.metadata.attachments,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/esx_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/esx_inv.lua
new file mode 100644
index 000000000..ff1881be5
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/esx_inv.lua
@@ -0,0 +1,88 @@
+if config.framework ~= "esx" then return end
+if not config.useDefaultInventory then return end
+
+local playerJob = ""
+local lastItems = {}
+
+local function getInventoryItems()
+ tgiCore.cbFunction('tgiann-weapons-on-back:esx_inv:server:getInventory', function(playerItems, loadout)
+ local itemList = {}
+ -- ESX is suck
+ if loadout and #loadout > 0 then
+ for i = 1, #loadout do
+ itemList[#itemList + 1] = loadout[i]
+ end
+ end
+
+ if playerItems and #playerItems > 0 then
+ for i = 1, #playerItems do
+ if playerItems[i].count > 0 then
+ itemList[#itemList + 1] = playerItems[i]
+ end
+ end
+ end
+ lastItems = itemList
+ weaponCheck()
+ end)
+end
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ getInventoryItems()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('esx:addInventoryItem')
+AddEventHandler('esx:addInventoryItem', function(job)
+ getInventoryItems()
+end)
+
+RegisterNetEvent('esx:removeInventoryItem')
+AddEventHandler('esx:removeInventoryItem', function(job)
+ getInventoryItems()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if item and key == item.name then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ self.Functions.CheckWeaponIsRemoved()
+ Wait(100)
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and string.find(string.lower(item.name), "weapon") then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.name,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item?.info?.tgiattachments, joaat(item.name)) or item.components,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/main.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/main.lua
new file mode 100644
index 000000000..786946d5f
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/main.lua
@@ -0,0 +1,99 @@
+tgiCore = nil
+CreateThread(function()
+ while not tgiCore do
+ tgiCore = tgiCoreExports:getCore()
+ Wait(200)
+ end
+end)
+
+local function LoadModel(model)
+ if HasModelLoaded(model) then return end
+ RequestModel(model)
+ while not HasModelLoaded(model) do Wait(0) end
+end
+
+self.Functions.AddAttachments = function(entity, weaponName, weaponHash, attachments)
+ if not attachments then return end
+ if config.tgiann_attachments then
+ for _, data in pairs(attachments) do
+ local model = GetWeaponComponentTypeModel(data.component)
+ if model ~= 0 then
+ LoadModel(model)
+ GiveWeaponComponentToWeaponObject(entity, data.component)
+ SetModelAsNoLongerNeeded(data.component)
+ else
+ SetWeaponObjectTintIndex(entity, data.component)
+ end
+ end
+ elseif config.core_inventory then
+ for _, data in pairs(attachments) do
+ local model = GetWeaponComponentTypeModel(data.componentHash)
+ if model ~= 0 then
+ LoadModel(model)
+ GiveWeaponComponentToWeaponObject(entity, data.componentHash)
+ SetModelAsNoLongerNeeded(data.componentHash)
+ else
+ SetWeaponObjectTintIndex(entity, data.componentHash)
+ end
+ end
+ elseif config.ox_inventory then
+ if not oxItems then oxItems = exports.ox_inventory:Items() end
+ for i = 1, #attachments do
+ local components = oxItems[attachments[i]].client.component
+ for v = 1, #components do
+ local component = components[v]
+ if DoesWeaponTakeWeaponComponent(weaponHash, component) then
+ local model = GetWeaponComponentTypeModel(component)
+ if model ~= 0 then
+ LoadModel(model)
+ GiveWeaponComponentToWeaponObject(entity, component)
+ SetModelAsNoLongerNeeded(component)
+ end
+ end
+ end
+ end
+ elseif config.framework == "qb" then
+ for _, data in pairs(attachments) do
+ local model = GetWeaponComponentTypeModel(data.component)
+ if model ~= 0 then
+ LoadModel(model)
+ GiveWeaponComponentToWeaponObject(entity, data.component)
+ SetModelAsNoLongerNeeded(data.component)
+ else
+ SetWeaponObjectTintIndex(entity, data.component)
+ end
+ end
+ else
+ --ESX is suck
+ for i = 1, #attachments do
+ local componentData = tgiCore.core.GetWeaponComponent(weaponName, attachments[i])
+ if componentData then
+ local hash = componentData.hash
+ local model = GetWeaponComponentTypeModel(hash)
+ if model ~= 0 then
+ LoadModel(model)
+ GiveWeaponComponentToWeaponObject(entity, hash)
+ SetModelAsNoLongerNeeded(hash)
+ else
+ SetWeaponObjectTintIndex(entity, hash)
+ end
+ end
+ end
+ end
+end
+
+function getTgiannAttachments(tgiattachments, weapon)
+ local invSettings = exports["tgiann-attachment"]:inventoryConfig()
+ if invSettings then
+ return tgiattachments
+ else
+ local returnVal = nil
+ local waitCb = true
+ tgiCore.cbFunction("tgiann-attachment:getAttachment", function(data)
+ returnVal = data
+ waitCb = false
+ end, weapon)
+ while waitCb do Wait(10) end
+ return returnVal
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/mf_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/mf_inv.lua
new file mode 100644
index 000000000..c8bcde8df
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/mf_inv.lua
@@ -0,0 +1,77 @@
+if not config["mf-inventory"] then return end
+
+local playerJob = ""
+local lastItems = {}
+
+local function getInventoryItems(identifier)
+ exports["mf-inventory"]:getInventoryItems(identifier, function(items)
+ lastItems = items
+ weaponCheck()
+ end)
+end
+
+RegisterNetEvent('esx:playerLoaded')
+AddEventHandler('esx:playerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ getInventoryItems(PlayerData.identifier)
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('esx:addInventoryItem')
+AddEventHandler('esx:addInventoryItem', function(job)
+ local PlayerData = exports["tgiann-core"]:getPlayerData()
+ if not PlayerData then return end
+ getInventoryItems(PlayerData.identifier)
+end)
+
+RegisterNetEvent('esx:removeInventoryItem')
+AddEventHandler('esx:removeInventoryItem', function(job)
+ local PlayerData = exports["tgiann-core"]:getPlayerData()
+ if not PlayerData then return end
+ getInventoryItems(PlayerData.identifier)
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if item and key == item.name then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ if not lastItems then return end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved(lastItems)
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and string.find(string.lower(item.name), "weapon") then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.name,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.metadata.tgiattachments, joaat(item.name)),
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/origen_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/origen_inv.lua
new file mode 100644
index 000000000..aee6b831a
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/origen_inv.lua
@@ -0,0 +1,79 @@
+if not config.origen_inventory then return end
+
+local origen_inventory = exports.origen_inventory
+local playerJob = ""
+local lastItems = {}
+
+local function getInventoryItems()
+ lastItems = origen_inventory:GetInventory()
+ weaponCheck()
+end
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ getInventoryItems()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+--QB
+RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
+ playerJob = PlayerData.job.name
+ getInventoryItems()
+end)
+
+--ESX
+RegisterNetEvent('esx:addInventoryItem')
+AddEventHandler('esx:addInventoryItem', function()
+ getInventoryItems()
+end)
+
+RegisterNetEvent('esx:removeInventoryItem')
+AddEventHandler('esx:removeInventoryItem', function()
+ getInventoryItems()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if key == item.info.serie then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ if not lastItems then return end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and item.type == "weapon" then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.info.serie,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info.attachments,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/ox_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/ox_inv.lua
new file mode 100644
index 000000000..84715b1e3
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/ox_inv.lua
@@ -0,0 +1,64 @@
+if not config.ox_inventory then return end
+
+local playerJob = ""
+local lastItems = {}
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ lastItems = exports.ox_inventory:GetPlayerItems() or {}
+ weaponCheck()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+AddEventHandler('ox_inventory:updateInventory', function(changes)
+ for i, value in pairs(changes) do
+ lastItems[i] = value or nil
+ end
+ weaponCheck()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if item and key == (item.metadata.serial or item.name) then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ if not lastItems then return end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and string.find(string.lower(item.name), "weapon") then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.metadata.serial or item.name,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.metadata.tgiattachments, joaat(item.name)) or item.metadata.components,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/qb_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/qb_inv.lua
new file mode 100644
index 000000000..7ee834347
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/qb_inv.lua
@@ -0,0 +1,64 @@
+if config.framework ~= "qb" then return end
+if not config.useDefaultInventory then return end
+
+local playerJob = ""
+local lastItems = {}
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ lastItems = PlayerData?.items
+ weaponCheck()
+end)
+
+RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
+ playerJob = PlayerData.job.name
+ lastItems = PlayerData?.items
+ weaponCheck()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if key == item.info.serie then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ if not lastItems then return end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and item.type == "weapon" then
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.info.serie,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info.attachments,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/qs_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/qs_inv.lua
new file mode 100644
index 000000000..387313a79
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/qs_inv.lua
@@ -0,0 +1,89 @@
+if not config["qs-inventory"] then return end
+
+local playerJob = ""
+local lastItems = {}
+local isBussy = false
+
+local function getInventoryItems()
+ if isBussy then return end
+ isBussy = true
+ while exports['qs-inventory']:inInventory() do Wait(10) end -- getUserInventory not updating when inventory is open
+ Wait(1000) -- getUserInventory is updating late
+ lastItems = exports['qs-inventory']:getUserInventory()
+ weaponCheck(playerJob, true)
+ isBussy = false
+end
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ getInventoryItems()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+--ESX
+RegisterNetEvent('esx:addInventoryItem')
+AddEventHandler('esx:addInventoryItem', function()
+ getInventoryItems()
+end)
+
+RegisterNetEvent('esx:removeInventoryItem')
+AddEventHandler('esx:removeInventoryItem', function()
+ getInventoryItems()
+end)
+
+--QB
+RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
+ playerJob = PlayerData.job.name
+ lastItems = PlayerData?.items
+ weaponCheck()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck(playerJob)
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if item and key == (item.info?.serie or item.name) then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item then
+ local isWeapon = string.find(string.lower(item.name), "weapon")
+ debug(item.name .. " Check For Add Weapon", "isWeapon: " .. tostring(isWeapon))
+ if isWeapon then
+ debug(item.name .. " Added")
+ self.Functions.AddWeapon({
+ weapon = item.name,
+ key = item.info?.serie or item.name,
+ attachments = config.tgiann_attachments and
+ getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info?.attachments,
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/bridge/tgiann_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/tgiann_inv.lua
new file mode 100644
index 000000000..71e036f7f
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/bridge/tgiann_inv.lua
@@ -0,0 +1,62 @@
+if not config["tgiann-inventory"] then return end
+
+local playerJob = ""
+local lastItems = {}
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
+ self.Functions.RemoveAllWeapons()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
+AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
+ playerJob = PlayerData.job.name
+ lastItems = exports["tgiann-inventory"]:GetPlayerItems()
+ weaponCheck()
+end)
+
+RegisterNetEvent('tgiann-inventory:inventoryUpdated')
+AddEventHandler('tgiann-inventory:inventoryUpdated', function(items)
+ lastItems = items
+ weaponCheck()
+end)
+
+RegisterNetEvent('tgiCore:Client:OnJobUpdate')
+AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
+ self.Functions.RemoveAllWeapons()
+ playerJob = job.name
+ weaponCheck()
+end)
+
+self.Functions.CheckWeaponIsRemoved = function()
+ if not next(self.weapons) then return end
+ for key, _ in pairs(self.weapons) do
+ local success = false
+ for _, item in pairs(lastItems) do
+ if key == item?.info?.serie then
+ success = true
+ break
+ end
+ end
+ if not success then
+ self.Functions.RemoveWeapon(key)
+ end
+ end
+end
+
+function weaponCheck()
+ if not lastItems then return end
+ Wait(100)
+ self.Functions.CheckWeaponIsRemoved()
+ local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
+ for _, item in pairs(lastItems) do
+ if item and item.type == "weapon" then
+ self.Functions.AddWeapon({
+ weapon = string.gsub(item.name, "_police", ""),
+ key = item?.info?.serie or item.name,
+ attachments = item?.info?.tgiattachments or {},
+ playerJob = playerJob,
+ isMale = isMale
+ })
+ end
+ end
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/client.lua b/resources/[inventory]/tgiann-weapons-on-back/client/client.lua
new file mode 100644
index 000000000..b45246355
Binary files /dev/null and b/resources/[inventory]/tgiann-weapons-on-back/client/client.lua differ
diff --git a/resources/[inventory]/tgiann-weapons-on-back/client/editable.lua b/resources/[inventory]/tgiann-weapons-on-back/client/editable.lua
new file mode 100644
index 000000000..a5f9866b3
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/client/editable.lua
@@ -0,0 +1,12 @@
+function canShow(targetPed)
+ local isEntityVisible = IsEntityVisible(targetPed)
+ local getEntityAlpha = GetEntityAlpha(targetPed)
+ local pedIsVisible = isEntityVisible and getEntityAlpha == 255
+ debug("pedIsVisible: " .. tostring(pedIsVisible), "ped:" .. targetPed, "isEntityVisible: " .. tostring(isEntityVisible), "getEntityAlpha: " .. getEntityAlpha)
+ return pedIsVisible
+end
+
+function debug(...)
+ if not config.debug then return end
+ print(...)
+end
diff --git a/resources/[inventory]/tgiann-weapons-on-back/configs/config.lua b/resources/[inventory]/tgiann-weapons-on-back/configs/config.lua
new file mode 100644
index 000000000..db92c0b04
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/configs/config.lua
@@ -0,0 +1,206 @@
+--[[
+ - this script needs tgiann-core script to work, you can download the script from your keymaster account
+ Start tgiann-core script after es_extented/qb-core script and before tgiann-* scripts
+ Adjust the tgiann-core config file according to the framework you are using
+
+ https://tgiann.gitbook.io/tgiann/scripts/tgiann-weapons-on-back
+
+ Note: If you want the weapons to be invisible while in Noclip, the character must be completely invisible. If your character is invisible to other players, other players cannot see these weapons.
+ If you want to edit this, take a look at client/editable.lua
+]]
+
+tgiCoreExports = exports["tgiann-core"]
+config = tgiCoreExports:getConfig()
+config.debug = false
+
+config.tgiann_attachments = GetResourceState("tgiann-attachment") ~= "missing" -- https://tgiann.tebex.io/package/5399235
+
+-- Weapon positions for male and female characters. You can add additional positions here if you like.
+config.positions = {
+ male = {
+ back = { -- We have set 3 positions for the back. You can add or remove extra positions if you like. This setting also applies to other positions.
+ { -- position 1
+ bone = 24816,
+ offset = vector3(0.285, -0.17, 0.13),
+ rot = vector3(0.0, 170.0, 0.0),
+ },
+ { -- position 2
+ bone = 24816,
+ offset = vector3(0.285, -0.17, 0.0),
+ rot = vector3(0.0, 170.0, 0.0),
+ },
+ { -- position 3
+ bone = 24816,
+ offset = vector3(0.285, -0.17, -0.13),
+ rot = vector3(0.0, 170.0, 0.0),
+ }
+ },
+ front = {
+ {
+ bone = 24818,
+ offset = vector3(-0.03, 0.19, 0.0),
+ rot = vector3(-10.0, 40.0, 5.0),
+ }
+ },
+ right = {
+ {
+ bone = 11816,
+ offset = vector3(-0.01, 0.02, 0.215),
+ rot = vector3(-100.0, 60.0, 45.0),
+ }
+ },
+ rLegBack = {
+ {
+ bone = 11816,
+ offset = vector3(-0.15, -0.11, 0.22),
+ rot = vector3(0.0, 95.0, 180.0),
+ }
+ },
+ waist = {
+ {
+ bone = 11816,
+ offset = vector3(-0.07, -0.13, 0.05),
+ rot = vector3(180.0, -30.0, 10.0),
+ }
+ },
+ -- You can add extra positions here if you like.
+ -- The positions you add can be used in the `config.weaponPositions`, `config.weaponGroupPositions` and `config.weaponGroupJobPositions` settings.
+ --[[ exampleCustomName = {
+ {
+ bone = 11816,
+ offset = vector3(-0.07, -0.13, 0.05),
+ rot = vector3(180.0, -30.0, 10.0),
+ }
+ }, ]]
+ },
+ female = {
+ back = {
+ {
+ bone = 24816,
+ offset = vector3(0.285, -0.15, 0.13),
+ rot = vector3(0.0, 170.0, 0.0),
+ },
+ {
+ bone = 24816,
+ offset = vector3(0.285, -0.15, 0.0),
+ rot = vector3(0.0, 170.0, 0.0),
+ },
+ {
+ bone = 24816,
+ offset = vector3(0.285, -0.15, -0.13),
+ rot = vector3(0.0, 170.0, 0.0),
+ }
+ },
+ front = {
+ {
+ bone = 24818,
+ offset = vector3(-0.03, 0.21, 0.0),
+ rot = vector3(-10.0, 40.0, 5.0),
+ }
+ },
+ right = {
+ {
+ bone = 11816,
+ offset = vector3(-0.09, 0.03, 0.18),
+ rot = vector3(-105.0, 75.0, 45.0),
+ }
+ },
+ rLegBack = {
+ {
+ bone = 11816,
+ offset = vector3(-0.15, -0.11, 0.22),
+ rot = vector3(0.0, 95.0, 180.0),
+ }
+ },
+ waist = {
+ {
+ bone = 11816,
+ offset = vector3(-0.07, -0.09, 0.05),
+ rot = vector3(180.0, -30.0, 10.0),
+ }
+ }
+ }
+
+}
+
+-- Weapons in the list do not appear on the character
+config.disabledWeapons = {
+ weapon_flashlight = true,
+ weapon_knuckle = true,
+ weapon_bottle = true,
+ weapon_snowball = true,
+}
+
+-- adjusts the location of the weapon regardless of its group
+config.weaponPositions = {
+ --weapon_pistol = "right",
+}
+
+-- adjusts the position of the weapon regardless of its group
+config.weaponCustomPositions = {
+ male = {
+ weapon_bat = {
+ bone = 24816,
+ offset = vector3(0.0, -0.15, 0.03),
+ rot = vector3(0.0, 80.0, 0.0),
+ }
+ },
+ female = {
+ weapon_bat = {
+ bone = 24816,
+ offset = vector3(0.0, -0.15, 0.03),
+ rot = vector3(0.0, 80.0, 0.0),
+ }
+ }
+}
+
+--"waist" - "back" - "front" - "rigt" - "rLegBack" - "none"
+config.weaponGroupPostions = {
+ [3539449195] = "back", --GROUP_DIGISCANNER
+ [-37788308] = "rLegBack", --GROUP_FIREEXTINGUISHER
+ [1175761940] = "none", --GROUP_HACKINGDEVICE
+ [2725924767] = "back", --GROUP_HEAVY
+ [-728555052] = "back", --GROUP_MELEE
+ [3759491383] = "none", --GROUP_METALDETECTOR
+ [1159398588] = "back", --GROUP_MG
+ [3493187224] = "none", --GROUP_NIGHTVISION
+ [431593103] = "none", --GROUP_PARACHUTE
+ [1595662460] = "none", --GROUP_PETROLCAN
+ [416676503] = "waist", --GROUP_PISTOL
+ [970310034] = "back", --GROUP_RIFLE
+ [860033945] = "back", --GROUP_SHOTGUN
+ [-957766203] = "front", --GROUP_SMG
+ [-1212426201] = "back", --GROUP_SNIPER
+ [690389602] = "none", --GROUP_STUNGUN
+ [1548507267] = "none", --GROUP_THROWN
+ [75159441] = "back", --GROUP_TRANQILIZER
+ [2685387236] = "none", --GROUP_UNARMED
+}
+
+-- weapon locations for jobs
+config.weaponGroupJobPostions = {
+ {
+ jobs = { "police" }, -- u can add multible job name
+ postions = {
+ [3539449195] = "back", --GROUP_DIGISCANNER
+ [-37788308] = "rLegBack", --GROUP_FIREEXTINGUISHER
+ [1175761940] = "none", --GROUP_HACKINGDEVICE
+ [2725924767] = "back", --GROUP_HEAVY
+ [-728555052] = "back", --GROUP_MELEE
+ [3759491383] = "none", --GROUP_METALDETECTOR
+ [1159398588] = "back", --GROUP_MG
+ [3493187224] = "none", --GROUP_NIGHTVISION
+ [431593103] = "none", --GROUP_PARACHUTE
+ [1595662460] = "none", --GROUP_PETROLCAN
+ [416676503] = "right", --GROUP_PISTOL
+ [970310034] = "back", --GROUP_RIFLE
+ [860033945] = "back", --GROUP_SHOTGUN
+ [-957766203] = "front", --GROUP_SMG
+ [-1212426201] = "back", --GROUP_SNIPER
+ [690389602] = "none", --GROUP_STUNGUN
+ [1548507267] = "none", --GROUP_THROWN
+ [75159441] = "back", --GROUP_TRANQILIZER
+ [2685387236] = "none", --GROUP_UNARMED
+ }
+ }
+}
diff --git a/resources/[inventory]/tgiann-weapons-on-back/configs/core_inv_config.lua b/resources/[inventory]/tgiann-weapons-on-back/configs/core_inv_config.lua
new file mode 100644
index 000000000..be3ce7e4f
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/configs/core_inv_config.lua
@@ -0,0 +1,5 @@
+config.enableInv = {
+ ["content"] = true,
+ ["primary"] = true,
+ ["secondry"] = true,
+}
\ No newline at end of file
diff --git a/resources/[inventory]/tgiann-weapons-on-back/fxmanifest.lua b/resources/[inventory]/tgiann-weapons-on-back/fxmanifest.lua
new file mode 100644
index 000000000..c59b2fef0
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/fxmanifest.lua
@@ -0,0 +1,34 @@
+fx_version 'cerulean'
+game 'gta5'
+version '1.0.1'
+
+lua54 'yes'
+
+dependencies {
+ 'tgiann-core',
+}
+
+escrow_ignore {
+ 'configs/*.lua',
+ 'checkInv.lua',
+ 'client/bridge/*.lua',
+ 'client/editable.lua',
+ 'server/bridge/*.lua'
+}
+
+shared_script {
+ 'configs/*.lua',
+ 'checkInv.lua',
+}
+
+client_scripts {
+ 'client/*.lua',
+ 'client/bridge/*.lua'
+}
+
+server_scripts {
+ "server/server.lua",
+ 'server/bridge/*.lua',
+}
+
+dependency '/assetpacks'
\ No newline at end of file
diff --git a/resources/[inventory]/tgiann-weapons-on-back/server/bridge/core_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/server/bridge/core_inv.lua
new file mode 100644
index 000000000..b330e546d
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/server/bridge/core_inv.lua
@@ -0,0 +1,13 @@
+if not config.core_inventory then return end
+
+tgiCore.cbFunction('tgiann-weapons-on-back:core_inventory:server:getInventory', function(source, cb)
+ local src = source
+ local xPlayer = tgiCore.getPlayer(src)
+ if not xPlayer then return end
+ local citizenid = tgiCore.getCid(xPlayer)
+ local playerItems = {}
+ for inv, canAdd in pairs(config.enableInv) do
+ if canAdd then playerItems[inv] = exports['core_inventory']:getInventory(string.format("%s-%s", inv, citizenid)) end
+ end
+ cb(playerItems)
+end)
diff --git a/resources/[inventory]/tgiann-weapons-on-back/server/bridge/esx_inv.lua b/resources/[inventory]/tgiann-weapons-on-back/server/bridge/esx_inv.lua
new file mode 100644
index 000000000..a59396790
--- /dev/null
+++ b/resources/[inventory]/tgiann-weapons-on-back/server/bridge/esx_inv.lua
@@ -0,0 +1,10 @@
+if config.framework ~= "esx" then return end
+if not config.useDefaultInventory then return end
+
+-- esx is very bad, I can't access current inventory data from client
+tgiCore.cbFunction('tgiann-weapons-on-back:esx_inv:server:getInventory', function(source, cb)
+ local src = source
+ local xPlayer = tgiCore.getPlayer(src)
+ if not xPlayer then return end
+ cb(xPlayer.getInventory(), xPlayer.getLoadout())
+end)
\ No newline at end of file
diff --git a/resources/[inventory]/tgiann-weapons-on-back/server/server.lua b/resources/[inventory]/tgiann-weapons-on-back/server/server.lua
new file mode 100644
index 000000000..794191b64
Binary files /dev/null and b/resources/[inventory]/tgiann-weapons-on-back/server/server.lua differ
diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua
index 4104bbc54..d1af2034a 100644
--- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua
+++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/client/client.lua
@@ -9,6 +9,8 @@ local PlyInCarCam = false
local bcamstate = false
local carCam = false
local onRec = false
+local isRecording = false
+local isDashcamRecording = false
-- for prop and ped
local propNetID = nil
@@ -767,22 +769,88 @@ RegisterNetEvent('spy-bodycam:client:deleteDecoyPed',function(plyId)
end)
RegisterNetEvent('spy-bodycam:client:startRec',function(webhook,serviceUsed)
- SendNUIMessage({
- action = "toggle_record",
- hook = webhook,
- service = serviceUsed,
- recTiming = Config.RecordTime,
- })
- if Config.ForceViewCam then
- SetTimecycleModifier(Config.CameraEffect.bodycam)
- SetTimecycleModifierStrength(0.5)
- CreateThread(function()
- onRec = true
- while onRec do
- SetFollowPedCamViewMode(4)
- Wait(0)
- end
- end)
+ if isRecording then
+ SendNUIMessage({action = "cancel_rec_force"})
+ isRecording = false
+ NotifyPlayer('Recording stopped!', 'success', 2500)
+
+ if Config.ForceViewCam then
+ onRec = false
+ SetFollowPedCamViewMode(1)
+ SetTimecycleModifier('default')
+ SetTimecycleModifierStrength(1.0)
+ end
+ else
+ SendNUIMessage({
+ action = "toggle_record",
+ hook = webhook,
+ service = serviceUsed,
+ recTiming = Config.RecordTime,
+ })
+ isRecording = true
+ NotifyPlayer('Recording started!', 'success', 2500)
+
+ if Config.ForceViewCam then
+ SetTimecycleModifier(Config.CameraEffect.bodycam)
+ SetTimecycleModifierStrength(0.5)
+ CreateThread(function()
+ onRec = true
+ while onRec do
+ SetFollowPedCamViewMode(4)
+ Wait(0)
+ end
+ end)
+ end
+ end
+end)
+
+RegisterNetEvent('spy-bodycam:client:startDashcamRec', function(webhook, serviceUsed, netId)
+ if isDashcamRecording then
+ SendNUIMessage({action = "stop_dashcam_recording"})
+ isDashcamRecording = false
+ NotifyPlayer('Dashcam recording stopped!', 'success', 2500)
+
+ if Config.ForceViewCam then
+ onRec = false
+ SetFollowPedCamViewMode(1)
+ SetTimecycleModifier('default')
+ SetTimecycleModifierStrength(1.0)
+ end
+ else
+ local veh = NetworkGetEntityFromNetworkId(netId)
+ if not DoesEntityExist(veh) then
+ NotifyPlayer('Vehicle not found!', 'error', 2500)
+ return
+ end
+
+ -- Get vehicle info for recording overlay
+ local carPlate = GetVehicleNumberPlateText(veh)
+ local carName = GetVehDisplayName(GetEntityModel(veh))
+
+ -- Send message to NUI to start recording
+ SendNUIMessage({
+ action = "toggle_dashcam_record",
+ hook = webhook,
+ service = serviceUsed,
+ recTiming = Config.RecordTime,
+ vehicleId = netId,
+ vehiclePlate = carPlate,
+ vehicleName = carName
+ })
+ isDashcamRecording = true
+ NotifyPlayer('Dashcam recording started!', 'success', 2500)
+
+ if Config.ForceViewCam then
+ SetTimecycleModifier(Config.CameraEffect.dashcam)
+ SetTimecycleModifierStrength(0.5)
+ CreateThread(function()
+ onRec = true
+ while onRec do
+ SetFollowPedCamViewMode(4)
+ Wait(0)
+ end
+ end)
+ end
end
end)
@@ -805,6 +873,42 @@ RegisterNetEvent('spy-bodycam:client:refreshRecords',function(records,isBoss)
})
end)
+-- Register hotkeys for recording if enabled in config
+Citizen.CreateThread(function()
+ if Config.EnableRecordingHotkeys then
+ -- Bodycam recording hotkey
+ RegisterKeyMapping('bodycamrecord', 'Start/Stop bodycam recording', 'keyboard', Config.RecordHotkey)
+ RegisterCommand('bodycamrecord', function()
+ if bcamstate then -- Only if bodycam is active
+ TriggerServerEvent('spy-bodycam:server:toggleRecording')
+ else
+ NotifyPlayer('Bodycam not activated!', 'error', 2500)
+ end
+ end, false)
+
+ -- Dashcam recording hotkey
+ RegisterKeyMapping('dashcamrecord', 'Start/Stop dashcam recording', 'keyboard', Config.DashcamHotkey)
+ RegisterCommand('dashcamrecord', function()
+ if IsPedInAnyVehicle(cache.ped, false) then
+ local veh = GetVehiclePedIsIn(cache.ped, false)
+ if isCarAuth(veh) then
+ local netId = NetworkGetNetworkIdFromEntity(veh)
+ if GlobalState.CarsOnBodycam[netId] then
+ TriggerServerEvent('spy-bodycam:server:toggleDashcamRecording', netId)
+ else
+ NotifyPlayer('Dashcam not activated in this vehicle!', 'error', 2500)
+ end
+ else
+ NotifyPlayer('Vehicle not authorized for dashcam!', 'error', 2500)
+ end
+ else
+ NotifyPlayer('You need to be in a vehicle to use dashcam!', 'error', 2500)
+ end
+ end, false)
+ end
+end)
+
+
RegisterKeyMapping('bodycamexit', 'Exit bodycam spectate', 'keyboard', Config.ExitCamKey)
RegisterCommand('bodycamexit', function()
if PlyInCam or PlyInCarCam then
@@ -827,7 +931,7 @@ RegisterNUICallback('videoLog', function(data, cb)
local videoUrl = data.vidurl
local pos = GetEntityCoords(cache.ped)
local s1, s2 = GetStreetNameAtCoord(pos.x, pos.y, pos.z)
- TriggerServerEvent('spy-bodycam:server:logVideoDetails', videoUrl,GetStreetNameFromHashKey(s1))
+ TriggerServerEvent('spy-bodycam:server:logVideoDetails', videoUrl, GetStreetNameFromHashKey(s1), data.isDashcam)
end
end)
@@ -1041,6 +1145,7 @@ function PlayWatchAnim(ped,isNet)
Citizen.Wait(10)
end
local prop = CreateObject(tabletprop, x, y, z + 0.2, isNet, true, false)
+ AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0,
AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), -0.05, 0.0, 0.0, 0.0, 0.0, 0.0, true, true, false, true, 1, true)
local animDict = 'amb@code_human_in_bus_passenger_idles@female@tablet@idle_a'
RequestAnimDict(animDict)
@@ -1220,4 +1325,37 @@ function HasItemsCheck(itemname)
return false
end
+-- Register hotkeys for recording
+if Config.EnableRecordingHotkeys then
+ RegisterCommand('+bodycamrecord', function()
+ if bcamstate then
+ TriggerServerEvent('spy-bodycam:server:toggleRecording')
+ else
+ NotifyPlayer('Bodycam not activated!', 'error', 2500)
+ end
+ end, false)
+
+ RegisterCommand('+dashcamrecord', function()
+ if IsPedInAnyVehicle(cache.ped, false) then
+ local veh = GetVehiclePedIsIn(cache.ped, false)
+ if isCarAuth(veh) then
+ local netId = NetworkGetNetworkIdFromEntity(veh)
+ if GlobalState.CarsOnBodycam[netId] then
+ TriggerServerEvent('spy-bodycam:server:toggleDashcamRecording', netId)
+ else
+ NotifyPlayer('Dashcam not activated in this vehicle!', 'error', 2500)
+ end
+ else
+ NotifyPlayer('Vehicle not authorized for dashcam!', 'error', 2500)
+ end
+ else
+ NotifyPlayer('You need to be in a vehicle to use dashcam!', 'error', 2500)
+ end
+ end, false)
+
+ RegisterKeyMapping('+bodycamrecord', 'Start/Stop bodycam recording', 'keyboard', Config.RecordHotkey)
+ RegisterKeyMapping('+dashcamrecord', 'Start/Stop dashcam recording', 'keyboard', Config.DashcamHotkey)
+end
+
+
diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua
index cb9ef331b..1ac06914d 100644
--- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua
+++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/config.lua
@@ -21,10 +21,13 @@ Config.Dependency = {
UseProgress = 'qb', -- qb | ox | esx
UseMenu = 'qb', -- qb | ox | esx
UseNotify = 'qb', -- qb | ox | esx
- UseAppearance = 'illenium', -- qb | illenium | false
+ UseAppearance = 'illenium', -- qb | illenium | false
}
Config.ExitCamKey = 'BACK'
+Config.RecordHotkey = 'F1' -- Hotkey for bodycam recording
+Config.DashcamHotkey = 'F10' -- Hotkey for dashcam recording
+Config.EnableRecordingHotkeys = true -- Enable/disable hotkey functionality
Config.CameraEffect = {
bodycam = 'Island_CCTV_ChannelFuzz',
@@ -119,4 +122,4 @@ Config.VehCamOffset = {
-- 19: Military
-- 20: Commercial
-- 21: Trains
--- 22: Open Wheel
\ No newline at end of file
+-- 22: Open Wheel
diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua
index bf4ee74dc..8748be1d3 100644
--- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua
+++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/server/server.lua
@@ -161,13 +161,71 @@ Citizen.CreateThread(function()
end
end)
-RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetName)
+-- Handle bodycam recording toggle
+RegisterNetEvent('spy-bodycam:server:toggleRecording', function()
+ local src = source
+ if PlayerOnBodycam[src] then
+ local defwebhook
+ if Upload.ServiceUsed == 'discord' then
+ local jobKey
+ if Config.Framework == 'qb' then
+ local Player = QBCore.Functions.GetPlayer(src)
+ jobKey = Player.PlayerData.job.name
+ else
+ local xPlayer = ESX.GetPlayerFromId(src)
+ jobKey = xPlayer.getJob().name
+ end
+ if Upload.JobUploads[jobKey] then
+ defwebhook = Upload.JobUploads[jobKey].webhook
+ else
+ defwebhook = Upload.DefaultUploads.webhook
+ end
+ elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then
+ defwebhook = Upload.Token
+ end
+ TriggerClientEvent('spy-bodycam:client:startRec', src, defwebhook, Upload.ServiceUsed)
+ else
+ NotifyPlayerSv('Bodycam not turned on!', 'error', 3000, src)
+ end
+end)
+
+-- Handle dashcam recording toggle
+RegisterNetEvent('spy-bodycam:server:toggleDashcamRecording', function(netId)
+ local src = source
+ if CarsOnBodycam[netId] then
+ local defwebhook
+ if Upload.ServiceUsed == 'discord' then
+ local jobKey
+ if Config.Framework == 'qb' then
+ local Player = QBCore.Functions.GetPlayer(src)
+ jobKey = Player.PlayerData.job.name
+ else
+ local xPlayer = ESX.GetPlayerFromId(src)
+ jobKey = xPlayer.getJob().name
+ end
+ if Upload.JobUploads[jobKey] then
+ defwebhook = Upload.JobUploads[jobKey].webhook
+ else
+ defwebhook = Upload.DefaultUploads.webhook
+ end
+ elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then
+ defwebhook = Upload.Token
+ end
+ TriggerClientEvent('spy-bodycam:client:startDashcamRec', src, defwebhook, Upload.ServiceUsed, netId)
+ else
+ NotifyPlayerSv('Dashcam not turned on!', 'error', 3000, src)
+ end
+end)
+
+
+RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl, streetName, isDashcam)
local src = source
local offName
local offJob
local offRank
local jobKey
local date = os.date('%Y-%m-%d')
+ local recordType = isDashcam and "dashcam" or "bodycam"
if Config.Framework == 'qb' then
local Player = QBCore.Functions.GetPlayer(src)
@@ -184,12 +242,13 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN
end
---SQL UPLOAD
- MySQL.Async.execute('INSERT INTO spy_bodycam (job, videolink, street, date, playername) VALUES (@job, @videolink, @street, @date, @playername)', {
+ MySQL.Async.execute('INSERT INTO spy_bodycam (job, videolink, street, date, playername, recordtype) VALUES (@job, @videolink, @street, @date, @playername, @recordtype)', {
['@job'] = jobKey,
['@videolink'] = videoUrl,
['@street'] = streetName,
['@date'] = date,
- ['@playername'] = offName
+ ['@playername'] = offName,
+ ['@recordtype'] = recordType
}, function(rowsChanged) end)
if Upload.DiscordLogs.Enabled then
@@ -204,7 +263,7 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN
end
local embedData = {
{
- title = Upload.DiscordLogs.Title,
+ title = Upload.DiscordLogs.Title .. (isDashcam and " (Dashcam)" or " (Bodycam)"),
color = 16761035,
fields = {
{ name = "Name:", value = offName, inline = false },
@@ -212,7 +271,7 @@ RegisterNetEvent('spy-bodycam:server:logVideoDetails', function(videoUrl,streetN
{ name = "Job Rank:", value = offRank, inline = false },
},
footer = {
- text = "Date: " .. os.date("!%Y-%m-%d %H:%M:%S", os.time()),
+ text = "Date: " .. os.date("!%Y-%m-%d %H:%M:%S", os.time()),
icon_url = "https://i.imgur.com/CuSyeZT.png",
},
author = author
@@ -370,4 +429,58 @@ AddEventHandler('onResourceStart', function(resourceName)
checkForUpdates()
end
end)
+-- Handle bodycam recording toggle
+RegisterNetEvent('spy-bodycam:server:toggleRecording', function()
+ local src = source
+ if PlayerOnBodycam[src] then
+ local defwebhook
+ if Upload.ServiceUsed == 'discord' then
+ local jobKey
+ if Config.Framework == 'qb' then
+ local Player = QBCore.Functions.GetPlayer(src)
+ jobKey = Player.PlayerData.job.name
+ else
+ local xPlayer = ESX.GetPlayerFromId(src)
+ jobKey = xPlayer.getJob().name
+ end
+ if Upload.JobUploads[jobKey] then
+ defwebhook = Upload.JobUploads[jobKey].webhook
+ else
+ defwebhook = Upload.DefaultUploads.webhook
+ end
+ elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then
+ defwebhook = Upload.Token
+ end
+ TriggerClientEvent('spy-bodycam:client:startRec', src, defwebhook, Upload.ServiceUsed)
+ else
+ NotifyPlayerSv('Bodycam not turned on!', 'error', 3000, src)
+ end
+end)
+-- Handle dashcam recording toggle
+RegisterNetEvent('spy-bodycam:server:toggleDashcamRecording', function(netId)
+ local src = source
+ if CarsOnBodycam[netId] then
+ local defwebhook
+ if Upload.ServiceUsed == 'discord' then
+ local jobKey
+ if Config.Framework == 'qb' then
+ local Player = QBCore.Functions.GetPlayer(src)
+ jobKey = Player.PlayerData.job.name
+ else
+ local xPlayer = ESX.GetPlayerFromId(src)
+ jobKey = xPlayer.getJob().name
+ end
+ if Upload.JobUploads[jobKey] then
+ defwebhook = Upload.JobUploads[jobKey].webhook
+ else
+ defwebhook = Upload.DefaultUploads.webhook
+ end
+ elseif Upload.ServiceUsed == 'fivemanage' or Upload.ServiceUsed == 'fivemerr' then
+ defwebhook = Upload.Token
+ end
+ TriggerClientEvent('spy-bodycam:client:startDashcamRec', src, defwebhook, Upload.ServiceUsed, netId)
+ else
+ NotifyPlayerSv('Dashcam not turned on!', 'error', 3000, src)
+ end
+end)
diff --git a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html
index 23ade29bb..d7463b4dd 100644
--- a/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html
+++ b/resources/[jobs]/[police]/[spy-bodycam]/spy-bodycam/web/index.html
@@ -79,9 +79,18 @@
+
+
+
+
Police Cruiser - ABC123
+
00:00
+