From 18410251567c22a81f81792974f8c2d5a4eec40b Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Wed, 2 Jul 2025 17:36:47 +0200 Subject: [PATCH] firework --- .../qb-smallresources/client/fireworks.lua | 881 ------------------ resources/[standalone]/vms_firework/README.md | 5 + .../[standalone]/vms_firework/client.lua | 111 +++ .../[standalone]/vms_firework/config.lua | 146 +++ .../[standalone]/vms_firework/fxmanifest.lua | 17 + .../[standalone]/vms_firework/server.lua | 37 + 6 files changed, 316 insertions(+), 881 deletions(-) delete mode 100644 resources/[qb]/qb-smallresources/client/fireworks.lua create mode 100644 resources/[standalone]/vms_firework/README.md create mode 100644 resources/[standalone]/vms_firework/client.lua create mode 100644 resources/[standalone]/vms_firework/config.lua create mode 100644 resources/[standalone]/vms_firework/fxmanifest.lua create mode 100644 resources/[standalone]/vms_firework/server.lua diff --git a/resources/[qb]/qb-smallresources/client/fireworks.lua b/resources/[qb]/qb-smallresources/client/fireworks.lua deleted file mode 100644 index c7525f867..000000000 --- a/resources/[qb]/qb-smallresources/client/fireworks.lua +++ /dev/null @@ -1,881 +0,0 @@ -local QBCore = exports['qb-core']:GetCoreObject() -local fireworkTime = 0 -local fireworkLoc = nil - --- Modelle für Feuerwerks-Batterien und Raketen -local fireworkModels = { - ["firework1"] = "ind_prop_firework_01", -- Rakete für firework1 - ["firework2"] = "ind_prop_firework_04", -- Standard-Batterie für firework2 (Bunte Sterne) - ["firework3"] = "ind_prop_firework_03", -- Große Batterie für firework3 (Massive Show) - ["firework4"] = "prop_firework_03" -- Fontäne für firework4 (Kreischende Fontäne) -} - --- Spezifische Effekte für jeden Feuerwerkstyp -local firework2Effects = { - "scr_indep_firework_starburst", -- Sternenförmige Explosionen - "scr_firework_indep_spiral_burst_rwb", -- Spiralförmige Explosionen - "scr_indep_firework_shotburst" -- Schrotartige Explosionen -} - -local firework3Effects = { - "scr_firework_indep_ring_burst_rwb", -- Ringförmige Explosionen - "scr_firework_indep_burst_rwb", -- Massive Explosionen - "scr_xmas_firework_burst_fizzle" -- Knisternde Explosionen -} - --- Funktion zum Starten einer Feuerwerksrakete (firework1) -local function launchFireworkRocket(coords) - -- Lade das Raketenmodell - local rocketModel = "ind_prop_firework_01" - RequestModel(GetHashKey(rocketModel)) - while not HasModelLoaded(GetHashKey(rocketModel)) do - Wait(10) - end - - -- Erstelle die Rakete - local rocket = CreateObject(GetHashKey(rocketModel), - coords.x, coords.y, coords.z - 0.5, - true, true, false) - - -- Stelle die Rakete richtig auf den Boden - PlaceObjectOnGroundProperly(rocket) - FreezeEntityPosition(rocket, true) - - -- Warte kurz, damit die Rakete sichtbar ist - Wait(500) - - -- Lade die Feuerwerkseffekte - local ptfxAssets = { - "scr_indep_fireworks", - "proj_xmas_firework", - "proj_indep_firework_v2", - "proj_indep_firework" - } - - for _, asset in ipairs(ptfxAssets) do - RequestNamedPtfxAsset(asset) - while not HasNamedPtfxAssetLoaded(asset) do - Wait(10) - end - end - - -- Füge einen Zündungseffekt hinzu (kleiner Funke statt Flamme) - UseParticleFxAssetNextCall("scr_indep_fireworks") - local ignitionEffect = StartParticleFxLoopedOnEntity("scr_indep_firework_sparkle_spawn", - rocket, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.5, false, false, false) - - -- Zündungsgeräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_LAUNCH_01", rocket, "dlc_sum20_beach_party_sounds", true, 20) - - -- Warte kurz für den Zündungseffekt - Wait(1000) - - -- Stoppe den Zündungseffekt - StopParticleFxLooped(ignitionEffect, 0) - - -- Löse die Rakete vom Boden - FreezeEntityPosition(rocket, false) - - -- Füge einen Aufstiegseffekt hinzu - UseParticleFxAssetNextCall("scr_indep_fireworks") - local trailEffect = StartParticleFxLoopedOnEntity("scr_indep_firework_trail_spawn", - rocket, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, false, false, false) - - -- Bewege die Rakete nach oben - local startTime = GetGameTimer() - local duration = 3000 -- 3 Sekunden Aufstieg - local height = math.random(40, 60) - local startZ = GetEntityCoords(rocket).z - - -- Aufstiegsschleife mit leichter Schwankung - while GetGameTimer() - startTime < duration do - local progress = (GetGameTimer() - startTime) / duration - local newZ = startZ + (height * progress) - - -- Leichte Schwankung für realistischen Flug - local wobbleX = math.sin(GetGameTimer() * 0.01) * 0.3 * progress - local wobbleY = math.cos(GetGameTimer() * 0.01) * 0.3 * progress - - SetEntityCoords(rocket, - coords.x + wobbleX, - coords.y + wobbleY, - newZ) - Wait(0) - end - - -- Stoppe den Aufstiegseffekt - StopParticleFxLooped(trailEffect, 0) - - -- Verstecke die Rakete - SetEntityVisible(rocket, false, 0) - - -- Explosionseffekt in der Luft - local explosionHeight = startZ + height - - -- Hauptexplosion - Spezifisch für Rakete: Große Explosion mit Sternen - UseParticleFxAssetNextCall("proj_indep_firework_v2") - StartParticleFxNonLoopedAtCoord( - "scr_firework_indep_burst_rwb", - coords.x, coords.y, explosionHeight, - 0.0, 0.0, 0.0, - 3.0, -- Größere Skalierung für bessere Sichtbarkeit - false, false, false - ) - - -- Explosionsgeräusch - PlaySoundFromCoord(-1, "DISTANT_FIREWORK_BURST_01", - coords.x, coords.y, explosionHeight, - "dlc_sum20_beach_party_sounds", true, 50, false) - - Wait(300) - - -- Sekundäre Explosionen - Kleinere Sterne, die sich ausbreiten - for i = 1, 5 do - -- Leichte Variation in der Position - local offsetX = math.random(-5, 5) - local offsetY = math.random(-5, 5) - local offsetZ = math.random(-5, 5) - - UseParticleFxAssetNextCall("scr_indep_fireworks") - StartParticleFxNonLoopedAtCoord( - "scr_indep_firework_starburst", - coords.x + offsetX, coords.y + offsetY, explosionHeight + offsetZ, - 0.0, 0.0, 0.0, - math.random(15, 25) / 10, - false, false, false - ) - - -- Sekundäres Explosionsgeräusch - PlaySoundFromCoord(-1, "DISTANT_FIREWORK_BURST_0" .. math.random(2, 3), - coords.x + offsetX, coords.y + offsetY, explosionHeight + offsetZ, - "dlc_sum20_beach_party_sounds", true, 30, false) - - Wait(math.random(100, 300)) - end - - -- Lösche die Rakete nach einer Weile - Wait(5000) - DeleteEntity(rocket) -end - --- Funktion für eine kreischende Fontäne (firework4) -local function launchFireworkFountain(coords) - -- Lade das Fontänenmodell - local fountainModel = "prop_firework_03" - RequestModel(GetHashKey(fountainModel)) - while not HasModelLoaded(GetHashKey(fountainModel)) do - Wait(10) - end - - -- Erstelle die Fontäne - local fountain = CreateObject(GetHashKey(fountainModel), - coords.x, coords.y, coords.z - 0.5, - true, true, false) - - -- Stelle die Fontäne richtig auf den Boden - PlaceObjectOnGroundProperly(fountain) - FreezeEntityPosition(fountain, true) - - -- Warte kurz, damit die Fontäne sichtbar ist - Wait(500) - - -- Lade die Feuerwerkseffekte - local ptfxAssets = { - "scr_indep_fireworks", - "core" - } - - for _, asset in ipairs(ptfxAssets) do - RequestNamedPtfxAsset(asset) - while not HasNamedPtfxAssetLoaded(asset) do - Wait(10) - end - end - - -- Füge einen Zündungseffekt hinzu - UseParticleFxAssetNextCall("scr_indep_fireworks") - local ignitionEffect = StartParticleFxLoopedOnEntity("scr_indep_firework_sparkle_spawn", - fountain, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.5, false, false, false) - - -- Zündungsgeräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_LAUNCH_01", fountain, "dlc_sum20_beach_party_sounds", true, 20) - - -- Warte kurz für den Zündungseffekt - Wait(1000) - - -- Stoppe den Zündungseffekt - StopParticleFxLooped(ignitionEffect, 0) - - -- Starte die Fontäne - print("Starte kreischende Fontäne") - - -- Dauer der Fontäne - local fountainDuration = 15000 -- 15 Sekunden - local startTime = GetGameTimer() - - -- Haupteffekt der Fontäne (kontinuierlich) - UseParticleFxAssetNextCall("scr_indep_fireworks") - local mainEffect = StartParticleFxLoopedOnEntity("scr_indep_firework_fountain", - fountain, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 2.0, false, false, false) - - -- Kreischendes Geräusch in Schleife - local lastSoundTime = 0 - - -- Fontänen-Schleife - while GetGameTimer() - startTime < fountainDuration do - -- Füge zusätzliche Funkeneffekte hinzu - if math.random(1, 100) > 70 then -- 30% Chance pro Frame - UseParticleFxAssetNextCall("scr_indep_fireworks") - StartParticleFxNonLoopedOnEntity( - "scr_indep_firework_sparkle_spawn", - fountain, - math.random(-10, 10) / 10, math.random(-10, 10) / 10, math.random(5, 15) / 10, - 0.0, 0.0, 0.0, - math.random(10, 20) / 10, - false, false, false - ) - end - - -- Kreischendes Geräusch alle 500-1500ms - if GetGameTimer() - lastSoundTime > math.random(500, 1500) then - -- Wähle zufällig zwischen verschiedenen Geräuschen - local sounds = { - "POLICE_SIREN_WAIL", -- Kreischendes Geräusch - "CAR_BOMB_TICK", -- Tickendes Geräusch - "DISTANT_FIREWORK_LAUNCH_01" -- Startgeräusch - } - local sound = sounds[math.random(1, #sounds)] - - PlaySoundFromEntity(-1, sound, fountain, "dlc_sum20_beach_party_sounds", true, math.random(10, 30)) - lastSoundTime = GetGameTimer() - end - - -- Intensivere Effekte gegen Ende - local progress = (GetGameTimer() - startTime) / fountainDuration - if progress > 0.7 and math.random(1, 100) > 50 then -- 50% Chance in der letzten Phase - -- Zusätzliche Funken in verschiedenen Höhen - UseParticleFxAssetNextCall("core") - StartParticleFxNonLoopedOnEntity( - "ent_sht_electrical_box_sp", - fountain, - 0.0, 0.0, math.random(5, 20) / 10, - 0.0, 0.0, 0.0, - math.random(15, 25) / 10, - false, false, false - ) - end - - Wait(0) - end - - -- Stoppe den Haupteffekt - StopParticleFxLooped(mainEffect, 0) - - -- Finale der Fontäne - print("Fontänen-Finale") - - -- Mehrere intensive Funkeneffekte für das Finale - for i = 1, 10 do - UseParticleFxAssetNextCall("scr_indep_fireworks") - StartParticleFxNonLoopedOnEntity( - "scr_indep_firework_starburst", - fountain, - 0.0, 0.0, math.random(5, 15) / 10, - 0.0, 0.0, 0.0, - math.random(15, 25) / 10, - false, false, false - ) - - -- Finale-Geräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_BURST_0" .. math.random(1, 3), - fountain, "dlc_sum20_beach_party_sounds", true, 40) - - Wait(math.random(100, 300)) - end - - -- Lösche die Fontäne nach einer Weile - Wait(2000) - DeleteEntity(fountain) -end - --- Funktion für bunte Sterne (firework2) -local function startFireworkColorStars(coords) - -- Lade das Batteriemodell - local batteryModel = "ind_prop_firework_04" - RequestModel(GetHashKey(batteryModel)) - while not HasModelLoaded(GetHashKey(batteryModel)) do - Wait(10) - end - - -- Erstelle die Batterie - local battery = CreateObject(GetHashKey(batteryModel), - coords.x, coords.y, coords.z - 0.5, - true, true, false) - - -- Stelle die Batterie richtig auf den Boden - PlaceObjectOnGroundProperly(battery) - FreezeEntityPosition(battery, true) - - -- Warte kurz, damit die Batterie sichtbar ist - Wait(500) - - -- Lade die Feuerwerkseffekte - local ptfxAssets = { - "scr_indep_fireworks", - "proj_indep_firework_v2" - } - - for _, asset in ipairs(ptfxAssets) do - RequestNamedPtfxAsset(asset) - while not HasNamedPtfxAssetLoaded(asset) do - Wait(10) - end - end - - -- Füge einen Zündungseffekt hinzu - UseParticleFxAssetNextCall("scr_indep_fireworks") - local ignitionEffect = StartParticleFxLoopedOnEntity("scr_indep_firework_sparkle_spawn", - battery, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.5, false, false, false) - - -- Zündungsgeräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_LAUNCH_01", battery, "dlc_sum20_beach_party_sounds", true, 20) - - -- Warte kurz für den Zündungseffekt - Wait(1000) - - -- Stoppe den Zündungseffekt - StopParticleFxLooped(ignitionEffect, 0) - - -- Anzahl der Schüsse für firework2 - local numShots = 15 - - print("Starte bunte Sterne mit " .. numShots .. " Schüssen") - - -- Starte die Feuerwerksschüsse - for i = 1, numShots do - -- Bestimme die Höhe und Position des Schusses - local height = math.random(30, 50) - local offsetX = math.random(-10, 10) * (i / numShots) -- Größere Streuung bei späteren Schüssen - local offsetY = math.random(-10, 10) * (i / numShots) - - -- Starteffekt (kleiner Funke statt Flamme) - UseParticleFxAssetNextCall("scr_indep_fireworks") - StartParticleFxNonLoopedAtCoord("scr_indep_firework_sparkle_spawn", - coords.x, coords.y, coords.z + 0.5, - 0.0, 0.0, 0.0, - 0.8, false, false, false) - - -- Abschussgeräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_LAUNCH_01", battery, "dlc_sum20_beach_party_sounds", true, 20) - - -- Warte kurz für den visuellen Effekt des Aufstiegs - Wait(math.random(100, 200)) - - -- Explosionseffekt in der Luft (nur Partikel, keine echte Explosion) - local explosionHeight = coords.z + height - - -- Wähle einen zufälligen Effekt aus der Liste für firework2 - local effect = firework2Effects[math.random(1, #firework2Effects)] - - -- Bestimme das richtige Asset für diesen Effekt - local effectAsset = "scr_indep_fireworks" -- Standard - - if effect:find("indep_burst") or effect:find("indep_spiral") or effect:find("indep_ring") then - effectAsset = "proj_indep_firework_v2" - end - - -- Starte den Haupteffekt - UseParticleFxAssetNextCall(effectAsset) - StartParticleFxNonLoopedAtCoord( - effect, - coords.x + offsetX, coords.y + offsetY, explosionHeight, - 0.0, 0.0, 0.0, - math.random(20, 30) / 10, -- Größere Skalierung für bessere Sichtbarkeit - false, false, false - ) - - -- Explosionsgeräusch - PlaySoundFromCoord(-1, "DISTANT_FIREWORK_BURST_0" .. math.random(1, 3), - coords.x + offsetX, coords.y + offsetY, explosionHeight, - "dlc_sum20_beach_party_sounds", true, 50, false) - - -- Warte zwischen den Schüssen - -- Schnellere Abfolge gegen Ende für ein Finale - local waitTime = 0 - if i < numShots * 0.7 then - waitTime = math.random(300, 800) - else - waitTime = math.random(100, 300) - end - Wait(waitTime) - end - - -- Warte nach dem letzten Schuss - Wait(2000) - - -- Finale mit mehreren gleichzeitigen Effekten - for i = 1, 5 do - local finalOffsetX = math.random(-15, 15) - local finalOffsetY = math.random(-15, 15) - local finalHeight = math.random(30, 50) - - -- Wähle einen zufälligen Effekt für das Finale - local finalEffect = firework2Effects[math.random(1, #firework2Effects)] - - -- Bestimme das richtige Asset für diesen Effekt - local finalEffectAsset = "scr_indep_fireworks" -- Standard - - if finalEffect:find("indep_burst") or finalEffect:find("indep_spiral") or finalEffect:find("indep_ring") then - finalEffectAsset = "proj_indep_firework_v2" - end - - UseParticleFxAssetNextCall(finalEffectAsset) - StartParticleFxNonLoopedAtCoord( - finalEffect, - coords.x + finalOffsetX, - coords.y + finalOffsetY, - coords.z + finalHeight, - 0.0, 0.0, 0.0, - math.random(25, 35) / 10, -- Größere Skalierung für das Finale - false, false, false - ) - - -- Finale-Geräusch - PlaySoundFromCoord(-1, "DISTANT_FIREWORK_BURST_0" .. math.random(1, 3), - coords.x + finalOffsetX, coords.y + finalOffsetY, coords.z + finalHeight, - "dlc_sum20_beach_party_sounds", true, 50, false) - - Wait(100) - end - - -- Lösche die Batterie nach einer Weile - Wait(5000) - DeleteEntity(battery) -end - --- Funktion für massive Show (firework3) -local function startFireworkMassiveShow(coords) - -- Lade das Batteriemodell - local batteryModel = "ind_prop_firework_03" - RequestModel(GetHashKey(batteryModel)) - while not HasModelLoaded(GetHashKey(batteryModel)) do - Wait(10) - end - - -- Erstelle die Batterie - local battery = CreateObject(GetHashKey(batteryModel), - coords.x, coords.y, coords.z - 0.5, - true, true, false) - - -- Stelle die Batterie richtig auf den Boden - PlaceObjectOnGroundProperly(battery) - FreezeEntityPosition(battery, true) - - -- Warte kurz, damit die Batterie sichtbar ist - Wait(500) - - -- Lade die Feuerwerkseffekte - local ptfxAssets = { - "scr_indep_fireworks", - "proj_indep_firework_v2", - "proj_xmas_firework" - } - - for _, asset in ipairs(ptfxAssets) do - RequestNamedPtfxAsset(asset) - while not HasNamedPtfxAssetLoaded(asset) do - Wait(10) - end - end - - -- Füge einen Zündungseffekt hinzu - UseParticleFxAssetNextCall("scr_indep_fireworks") - local ignitionEffect = StartParticleFxLoopedOnEntity("scr_indep_firework_sparkle_spawn", - battery, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.5, false, false, false) - - -- Zündungsgeräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_LAUNCH_01", battery, "dlc_sum20_beach_party_sounds", true, 20) - - -- Warte kurz für den Zündungseffekt - Wait(1000) - - -- Stoppe den Zündungseffekt - StopParticleFxLooped(ignitionEffect, 0) - - -- Anzahl der Schüsse für firework3 - local numShots = 30 - - print("Starte massive Show mit " .. numShots .. " Schüssen") - - -- Starte die Feuerwerksschüsse - for i = 1, numShots do - -- Bestimme die Höhe und Position des Schusses - local height = math.random(30, 50) - local offsetX = math.random(-15, 15) * (i / numShots) -- Größere Streuung bei späteren Schüssen - local offsetY = math.random(-15, 15) * (i / numShots) - - -- Starteffekt (kleiner Funke statt Flamme) - UseParticleFxAssetNextCall("scr_indep_fireworks") - StartParticleFxNonLoopedAtCoord("scr_indep_firework_sparkle_spawn", - coords.x, coords.y, coords.z + 0.5, - 0.0, 0.0, 0.0, - 0.8, false, false, false) - - -- Abschussgeräusch - PlaySoundFromEntity(-1, "DISTANT_FIREWORK_LAUNCH_01", battery, "dlc_sum20_beach_party_sounds", true, 20) - - -- Warte kurz für den visuellen Effekt des Aufstiegs - Wait(math.random(100, 200)) - - -- Explosionseffekt in der Luft (nur Partikel, keine echte Explosion) - local explosionHeight = coords.z + height - - -- Wähle einen zufälligen Effekt aus der Liste für firework3 - local effect = firework3Effects[math.random(1, #firework3Effects)] - - -- Bestimme das richtige Asset für diesen Effekt - local effectAsset = "proj_indep_firework_v2" -- Standard für firework3 - - if effect:find("xmas") then - effectAsset = "proj_xmas_firework" - end - - -- Starte den Haupteffekt - UseParticleFxAssetNextCall(effectAsset) - StartParticleFxNonLoopedAtCoord( - effect, - coords.x + offsetX, coords.y + offsetY, explosionHeight, - 0.0, 0.0, 0.0, - math.random(25, 35) / 10, -- Größere Skalierung für bessere Sichtbarkeit - false, false, false - ) - - -- Füge zusätzliche Effekte für mehr Volumen hinzu (nur bei firework3) - for j = 1, 2 do - local subOffsetX = math.random(-5, 5) - local subOffsetY = math.random(-5, 5) - local subOffsetZ = math.random(-5, 5) - - -- Wähle einen anderen zufälligen Effekt - local subEffect = firework3Effects[math.random(1, #firework3Effects)] - - -- Bestimme das richtige Asset für diesen Effekt - local subEffectAsset = "proj_indep_firework_v2" -- Standard für firework3 - - if subEffect:find("xmas") then - subEffectAsset = "proj_xmas_firework" - end - - UseParticleFxAssetNextCall(subEffectAsset) - StartParticleFxNonLoopedAtCoord( - subEffect, - coords.x + offsetX + subOffsetX, - coords.y + offsetY + subOffsetY, - explosionHeight + subOffsetZ, - 0.0, 0.0, 0.0, - math.random(15, 25) / 10, - false, false, false - ) - end - - -- Explosionsgeräusch - PlaySoundFromCoord(-1, "DISTANT_FIREWORK_BURST_0" .. math.random(1, 3), - coords.x + offsetX, coords.y + offsetY, explosionHeight, - "dlc_sum20_beach_party_sounds", true, 50, false) - - -- Warte zwischen den Schüssen - -- Schnellere Abfolge gegen Ende für ein Finale - local waitTime = 0 - if i < numShots * 0.7 then - waitTime = math.random(300, 800) - else - waitTime = math.random(100, 300) - end - Wait(waitTime) - end - - -- Warte nach dem letzten Schuss - Wait(2000) - - -- Finale mit mehreren gleichzeitigen Effekten - for i = 1, 10 do - local finalOffsetX = math.random(-20, 20) - local finalOffsetY = math.random(-20, 20) - local finalHeight = math.random(30, 50) - - -- Wähle einen zufälligen Effekt für das Finale - local finalEffect = firework3Effects[math.random(1, #firework3Effects)] - - -- Bestimme das richtige Asset für diesen Effekt - local finalEffectAsset = "proj_indep_firework_v2" -- Standard für firework3 - - if finalEffect:find("xmas") then - finalEffectAsset = "proj_xmas_firework" - end - - UseParticleFxAssetNextCall(finalEffectAsset) - StartParticleFxNonLoopedAtCoord( - finalEffect, - coords.x + finalOffsetX, - coords.y + finalOffsetY, - coords.z + finalHeight, - 0.0, 0.0, 0.0, - math.random(30, 40) / 10, -- Größere Skalierung für das Finale - false, false, false - ) - - -- Finale-Geräusch - PlaySoundFromCoord(-1, "DISTANT_FIREWORK_BURST_0" .. math.random(1, 3), - coords.x + finalOffsetX, coords.y + finalOffsetY, coords.z + finalHeight, - "dlc_sum20_beach_party_sounds", true, 50, false) - Wait(100) - end - - -- Lösche die Batterie nach einer Weile - Wait(5000) - DeleteEntity(battery) -end - -local function DrawText3D(x, y, z, text) - SetTextScale(0.35, 0.35) - SetTextFont(4) - SetTextProportional(true) - SetTextColour(255, 255, 255, 215) - BeginTextCommandDisplayText('STRING') - SetTextCentre(true) - AddTextComponentSubstringPlayerName(text) - SetDrawOrigin(x, y, z, 0) - EndTextCommandDisplayText(0.0, 0.0) - local factor = (string.len(text)) / 370 - DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75) - ClearDrawOrigin() -end - -local function fireworkText() - CreateThread(function() - while true do - Wait(0) - if fireworkTime > 0 and fireworkLoc then - DrawText3D(fireworkLoc.x, fireworkLoc.y, fireworkLoc.z, Lang:t('firework.time_left') .. fireworkTime) - end - if fireworkTime <= 0 then break end - end - end) -end - --- Verbesserte Feuerwerk-Startfunktion -local function startFirework(asset, coords, itemName) - fireworkTime = Config.Fireworks.delay - fireworkLoc = { x = coords.x, y = coords.y, z = coords.z } - - CreateThread(function() - fireworkText() - while fireworkTime > 0 do - Wait(1000) - fireworkTime = fireworkTime - 1 - end - - print("Countdown beendet, starte Feuerwerk: " .. itemName) - - -- Wähle die richtige Feuerwerksart basierend auf dem Item - if itemName == "firework1" then - -- Rakete für firework1 - launchFireworkRocket(coords) - elseif itemName == "firework2" then - -- Bunte Sterne für firework2 - startFireworkColorStars(coords) - elseif itemName == "firework3" then - -- Massive Show für firework3 - startFireworkMassiveShow(coords) - elseif itemName == "firework4" then - -- Kreischende Fontäne für firework4 - launchFireworkFountain(coords) - else - -- Fallback: Bunte Sterne - startFireworkColorStars(coords) - end - - fireworkLoc = nil - end) -end - --- Animation für das Anzünden mit Feuerzeug -local function playLighterAnimation() - local ped = PlayerPedId() - - -- Lade die Animation - RequestAnimDict("anim@mp_player_intmenu@key_fob@") - while not HasAnimDictLoaded("anim@mp_player_intmenu@key_fob@") do - Wait(10) - end - - -- Spiele die Animation ab - TaskPlayAnim(ped, "anim@mp_player_intmenu@key_fob@", "fob_click", 3.0, 3.0, -1, 49, 0, false, false, false) - - -- Erstelle ein Feuerzeug-Objekt in der Hand - local coords = GetEntityCoords(ped) - local lighter = CreateObject(GetHashKey("prop_cs_lighter_01"), coords.x, coords.y, coords.z, true, true, true) - AttachEntityToEntity(lighter, ped, GetPedBoneIndex(ped, 57005), 0.1, 0.05, 0.0, -60.0, 0.0, 0.0, true, true, false, true, 1, true) - - -- Füge einen kleinen Funkeneffekt statt Flamme hinzu - RequestNamedPtfxAsset("scr_indep_fireworks") - while not HasNamedPtfxAssetLoaded("scr_indep_fireworks") do - Wait(10) - end - - UseParticleFxAssetNextCall("scr_indep_fireworks") - local spark = StartParticleFxLoopedOnEntity("scr_indep_firework_sparkle_spawn", lighter, 0.0, 0.0, 0.15, 0.0, 0.0, 0.0, 0.15, false, false, false) - - -- Warte 2 Sekunden - Wait(2000) - - -- Stoppe die Animation und lösche das Feuerzeug - StopAnimTask(ped, "anim@mp_player_intmenu@key_fob@", "fob_click", 1.0) - StopParticleFxLooped(spark, 0) - DeleteEntity(lighter) -end - --- Überprüfe, ob der Spieler ein Feuerzeug hat -local function hasLighter() - local hasItem = QBCore.Functions.HasItem("lighter") - return hasItem -end - -RegisterNetEvent('fireworks:client:UseFirework', function(itemName, assetName) - print("Feuerwerk-Event ausgelöst mit Item: " .. itemName) - - -- Überprüfe zuerst, ob der Spieler ein Feuerzeug hat - if not hasLighter() then - QBCore.Functions.Notify(Lang:t('firework.no_lighter'), 'error') - return - end - - QBCore.Functions.Progressbar('spawn_object', Lang:t('firework.place_progress'), 3000, false, true, { - disableMovement = true, - disableCarMovement = true, - disableMouse = false, - disableCombat = true, - }, { - animDict = 'anim@narcotics@trash', - anim = 'drop_front', - flags = 16, - }, {}, {}, function() -- Done - StopAnimTask(PlayerPedId(), 'anim@narcotics@trash', 'drop_front', 1.0) - TriggerServerEvent('consumables:server:UseFirework', itemName) - TriggerEvent('qb-inventory:client:ItemBox', QBCore.Shared.Items[itemName], 'remove') - local pos = GetEntityCoords(PlayerPedId()) - - print("Feuerwerk platziert, beginne Anzündung") - - -- Spiele die Feuerzeug-Animation ab - playLighterAnimation() - - -- Starte das Feuerwerk mit dem Itemnamen - startFirework(assetName, pos, itemName) - end, function() -- Cancel - StopAnimTask(PlayerPedId(), 'anim@narcotics@trash', 'drop_front', 1.0) - QBCore.Functions.Notify(Lang:t('firework.canceled'), 'error') - end) -end) - --- Test-Befehl für verschiedene Feuerwerkstypen -RegisterCommand('feuerwerk', function(source, args) - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - -- Überprüfe zuerst, ob der Spieler ein Feuerzeug hat - if not hasLighter() then - QBCore.Functions.Notify(Lang:t('firework.no_lighter'), 'error') - return - end - - -- Item-Name als Argument - local itemName = args[1] or "firework1" - - -- Spiele die Feuerzeug-Animation ab - playLighterAnimation() - - -- Starte das passende Feuerwerk - if itemName == "firework1" then - launchFireworkRocket(coords) - elseif itemName == "firework2" then - startFireworkColorStars(coords) - elseif itemName == "firework3" then - startFireworkMassiveShow(coords) - elseif itemName == "firework4" then - launchFireworkFountain(coords) - else - startFireworkColorStars(coords) - end -end) - --- Spezielle Test-Befehle für die verschiedenen Feuerwerkstypen -RegisterCommand('rakete', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - -- Überprüfe zuerst, ob der Spieler ein Feuerzeug hat - if not hasLighter() then - QBCore.Functions.Notify(Lang:t('firework.no_lighter'), 'error') - return - end - - -- Spiele die Feuerzeug-Animation ab - playLighterAnimation() - - -- Starte die Rakete (firework1) - launchFireworkRocket(coords) -end) - -RegisterCommand('buntesterne', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - -- Überprüfe zuerst, ob der Spieler ein Feuerzeug hat - if not hasLighter() then - QBCore.Functions.Notify(Lang:t('firework.no_lighter'), 'error') - return - end - - -- Spiele die Feuerzeug-Animation ab - playLighterAnimation() - - -- Starte die bunten Sterne (firework2) - startFireworkColorStars(coords) -end) - -RegisterCommand('massiveshow', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - -- Überprüfe zuerst, ob der Spieler ein Feuerzeug hat - if not hasLighter() then - QBCore.Functions.Notify(Lang:t('firework.no_lighter'), 'error') - return - end - - -- Spiele die Feuerzeug-Animation ab - playLighterAnimation() - - -- Starte die massive Show (firework3) - startFireworkMassiveShow(coords) -end) - -RegisterCommand('fontaene', function() - local playerPed = PlayerPedId() - local coords = GetEntityCoords(playerPed) - - -- Überprüfe zuerst, ob der Spieler ein Feuerzeug hat - if not hasLighter() then - QBCore.Functions.Notify(Lang:t('firework.no_lighter'), 'error') - return - end - - -- Spiele die Feuerzeug-Animation ab - playLighterAnimation() - - -- Starte die kreischende Fontäne (firework4) - launchFireworkFountain(coords) -end) - - diff --git a/resources/[standalone]/vms_firework/README.md b/resources/[standalone]/vms_firework/README.md new file mode 100644 index 000000000..a7f14fff9 --- /dev/null +++ b/resources/[standalone]/vms_firework/README.md @@ -0,0 +1,5 @@ +![FIREWORKS](https://user-images.githubusercontent.com/60104107/209708278-b9b55a71-8d64-4917-8c86-4f7002922e10.png) + +# vms_firework + +### https://discord.gg/k4YNwYxE4h diff --git a/resources/[standalone]/vms_firework/client.lua b/resources/[standalone]/vms_firework/client.lua new file mode 100644 index 000000000..04c349d02 --- /dev/null +++ b/resources/[standalone]/vms_firework/client.lua @@ -0,0 +1,111 @@ +local function DrawText3D(coords, text) + local camCoords = GetFinalRenderedCamCoord() + local distance = #(coords - camCoords) + local scale = (0.8 / distance) * 2 + local fov = (1 / GetGameplayCamFov()) * 100 + scale = scale * fov + SetTextScale(0.0 * scale, 0.55 * scale) + SetTextFont(4) + SetTextProportional(1) + SetTextDropShadow() + SetTextColour(240, 240, 240, 185) + BeginTextCommandDisplayText('STRING') + SetTextCentre(true) + AddTextComponentSubstringPlayerName(text) + SetDrawOrigin(coords.xyz, 0) + EndTextCommandDisplayText(0.0, 0.0) + ClearDrawOrigin() +end + +local function reqAnimDict(dict) + while not HasAnimDictLoaded(dict) do + RequestAnimDict(dict) + Wait(2) + end +end + +local function reqParticle(dict) + RequestNamedPtfxAsset(dict) + while not HasNamedPtfxAssetLoaded(dict) do + Wait(1) + end +end + +for k, v in pairs(Config.Fireworks) do + if v.command then + RegisterCommand(v.command, function(source, args, rawCommand) + TriggerEvent('vms_firework:startFirework', k) + end) + end +end + +local hasBox = nil +RegisterNetEvent('vms_firework:startFirework', function(type) + if Config.DisableMultiplyFireworks then + if hasBox then + return Config.Notification(Config.Translate['CANNOT_START'], 4500, 'error') + end + end + if Config.Fireworks[type] then + local myFirework = Config.Fireworks[type] + local myPed = PlayerPedId() + local myOffset = GetOffsetFromEntityInWorldCoords(myPed, 0, .6, 0) + local fireworkShoots = myFirework.shoots + local secondsToStart = myFirework.timeToStart + reqAnimDict(Config.PlacingAnimation[1]) + TaskPlayAnim(myPed, Config.PlacingAnimation[1], Config.PlacingAnimation[2], -1, -8.0, 3000, 0, 0, false, false, false) + Citizen.Wait((GetAnimDuration(Config.PlacingAnimation[1], Config.PlacingAnimation[2]) * 1000) - 2050) + hasBox = CreateObject(myFirework.prop, myOffset.x, myOffset.y, myOffset.z, true, false, false) + PlaceObjectOnGroundProperly(hasBox) + FreezeEntityPosition(hasBox, true) + Config.Notification(Config.Translate['YOU_PLACE_FIREWORK'], 4500, 'success') + local boxCoords = GetEntityCoords(hasBox) + while secondsToStart > 0 do + secondsToStart = secondsToStart - 5 + if Config.Enable3DText then + DrawText3D(boxCoords, secondsToStart/1000) + end + Citizen.Wait(0) + end + + for k, v in pairs(myFirework.particles) do + reqParticle(v.name) + end + + while fireworkShoots ~= 0 do + fireworkShoots = fireworkShoots - 1 + for k, v in pairs(myFirework.particles) do + UseParticleFxAsset(v.name) + local effect = StartNetworkedParticleFxNonLoopedAtCoord( + v.effect, + boxCoords.x + (v.randomizeXY == true and math.random(-10, 10) or 0.0), + boxCoords.y + (v.randomizeXY == true and math.random(-10, 10) or 0.0), + boxCoords.z + v.plusHeight, + 0.0, + 0.0, + 0.0, + v.scale, + false, + false, + false + ) + if Config.Debug then + print('[ Shoots left: '..fireworkShoots..' ]', "ID: "..k, v.name, v.effect) + end + Citizen.Wait(v.timeToNextShoot) + end + Citizen.Wait(myFirework.timeBetweenShoots or 300) + end + NetworkFadeOutEntity(hasBox, true, false) + if Config.Debug then + print('Prop is removed') + end + Citizen.Wait(5000) + DeleteEntity(hasBox) + hasBox = nil + end +end) + +RegisterNetEvent('vms_firework:notification', function(message, time, type) + Config.Notification(Config.Translate[message], time, type) +end) \ No newline at end of file diff --git a/resources/[standalone]/vms_firework/config.lua b/resources/[standalone]/vms_firework/config.lua new file mode 100644 index 000000000..a0ad07d5e --- /dev/null +++ b/resources/[standalone]/vms_firework/config.lua @@ -0,0 +1,146 @@ +-- Hi, if you like the script, join the discord: https://discord.gg/k4YNwYxE4h + +Config = {} + +Config.Debug = false + +Config.Core = "ESX" -- "ESX" / "QB-Core" + +if Config.Core == "ESX" then + ESX = exports['es_extended']:getSharedObject() +elseif Config.Core == "QB-Core" then + QBCore = exports['qb-core']:GetCoreObject() +end + +Config.Notification = function(message, time, type) + if type == "success" then + exports["vms_notify"]:Notification("FIREWORK", message, time, "#27FF09", "fa-solid fa-fire") + -- TriggerEvent('esx:showNotification', message) --[ ESX ] + -- TriggerEvent('QBCore:Notify', message, 'success', time) -- [ QB-Core ] + + elseif type == "error" then + exports["vms_notify"]:Notification("FIREWORK", message, time, "#FF0909", "fa-solid fa-fire") + -- TriggerEvent('esx:showNotification', message) --[ ESX ] + -- TriggerEvent('QBCore:Notify', message, 'error', time) -- [ QB-Core ] + + end +end + +Config.Translate = { + ['CANNOT_START'] = "You can't set off several fireworks at once, wait until the current one goes off", -- Only if: Config.DisableMultiplyFireworks = true + ['NEED_LIGHTER'] = "You need have lighter!", -- Only if: Config.NeedLighter = true + ['YOU_PLACE_FIREWORK'] = "You place the firework!", +} + +Config.Enable3DText = true -- 3DText on fireworks, shows the time to go off + +Config.PlacingAnimation = {'anim@mp_fireworks', 'place_firework_3_box'} -- Animation of placing firework + +Config.DisableMultiplyFireworks = false -- if you set it true, the player will be able to place one firework, the next one only after he finishes shooting + +Config.NeedLighter = true +Config.LighterItem = 'bread' + + +Config.Fireworks = { + [1] = { + item = 'firework_1', -- name or nil + itemRemovable = true, -- if it is on the item, is it to be removed after use + command = 'fire_1', -- name of command or nil + shoots = 50, -- count of shots + prop = "ind_prop_firework_03", + timeToStart = 5500, -- +/- 5000 == 5 seconds + timeBetweenShoots = 1250, + particles = { + {name = "scr_indep_fireworks", effect = "scr_indep_firework_starburst", scale = 2.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 120}, + {name = "proj_indep_firework", effect = "scr_indep_firework_grd_burst", scale = 2.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 300}, + {name = "proj_indep_firework", effect = "scr_indep_firework_air_burst", scale = 2.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 600}, + }, + }, + [2] = { + item = 'firework_2', + itemRemovable = true, + command = 'fire_2', + shoots = 80, + prop = "ind_prop_firework_03", + timeToStart = 5500, + timeBetweenShoots = 250, + particles = { + {name = "scr_indep_fireworks", effect = "scr_indep_firework_trailburst", scale = 2.0, plusHeight = 10.0, randomizeXY = true, timeToNextShoot = 125}, + {name = "proj_indep_firework_v2", effect = "scr_firework_indep_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 125}, + {name = "proj_xmas_firework", effect = "scr_firework_xmas_ring_burst_rgw", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 125}, + }, + }, + [3] = { + item = 'firework_3', + itemRemovable = true, + command = 'fire_3', + shoots = 80, + prop = "ind_prop_firework_03", + timeToStart = 5500, + timeBetweenShoots = 250, + particles = { + {name = "proj_indep_firework", effect = "scr_indep_firework_air_burst", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 125}, + {name = "proj_indep_firework_v2", effect = "scr_firework_indep_spiral_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 125}, + {name = "proj_indep_firework_v2", effect = "scr_firework_indep_repeat_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 125}, + {name = "scr_indep_fireworks", effect = "scr_indep_firework_starburst", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 125}, + }, + }, + [4] = { + item = 'firework_4', + itemRemovable = true, + command = 'fire_4', + shoots = 50, + prop = "ind_prop_firework_03", + timeToStart = 5000, + timeBetweenShoots = 550, + particles = { + {name = "scr_indep_fireworks", effect = "scr_indep_firework_trailburst", scale = 4.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 10}, + }, + }, + [5] = { + item = 'fontain_4', + itemRemovable = true, + command = 'fontain_4', + shoots = 80, + prop = "ind_prop_firework_04", + timeToStart = 3500, + timeBetweenShoots = 700, + particles = { + {name = "scr_indep_fireworks", effect = "scr_indep_firework_fountain", scale = 0.25, plusHeight = 0.25, randomizeXY = false, timeToNextShoot = 500}, + }, + }, + --[[ + [6] = { + item = nil, + itemRemovable = false, + command = '', + shoots = 1, + prop = "ind_prop_firework_04", + timeToStart = 1000, + timeBetweenShoots = 100, + particles = { + -- {name = "proj_indep_firework", effect = "scr_indep_firework_grd_burst", scale = 2.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 600}, + -- {name = "proj_indep_firework", effect = "scr_indep_firework_air_burst", scale = 2.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 600}, + + -- {name = "proj_indep_firework_v2", effect = "scr_firework_indep_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_indep_firework_v2", effect = "scr_firework_indep_spiral_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_indep_firework_v2", effect = "scr_firework_indep_ring_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_indep_firework_v2", effect = "scr_xmas_firework_burst_fizzle", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_indep_firework_v2", effect = "scr_firework_indep_repeat_burst_rwb", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + + -- {name = "proj_xmas_firework", effect = "scr_firework_xmas_ring_burst_rgw", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_xmas_firework", effect = "scr_firework_xmas_burst_rgw", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_xmas_firework", effect = "scr_firework_xmas_repeat_burst_rgw", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "proj_xmas_firework", effect = "scr_firework_xmas_spiral_burst_rgw", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + + -- {name = "scr_indep_fireworks", effect = "scr_indep_firework_starburst", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "scr_indep_fireworks", effect = "scr_indep_firework_shotburst", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "scr_indep_fireworks", effect = "scr_indep_firework_trailburst", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "scr_indep_fireworks", effect = "scr_indep_firework_trailburst_spawn", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "scr_indep_fireworks", effect = "scr_indep_firework_burst_spawn", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + -- {name = "scr_indep_fireworks", effect = "scr_indep_firework_fountain", scale = 1.0, plusHeight = 50.0, randomizeXY = true, timeToNextShoot = 2025}, + }, + } + ]] +} diff --git a/resources/[standalone]/vms_firework/fxmanifest.lua b/resources/[standalone]/vms_firework/fxmanifest.lua new file mode 100644 index 000000000..f295677d9 --- /dev/null +++ b/resources/[standalone]/vms_firework/fxmanifest.lua @@ -0,0 +1,17 @@ +fx_version 'cerulean' +game 'gta5' +lua54 'yes' + +author 'vames™️' +description 'vms_firework' +version '1.0.0' + +shared_script 'config.lua' + +client_scripts { + 'client.lua' +} + +server_scripts { + 'server.lua' +} \ No newline at end of file diff --git a/resources/[standalone]/vms_firework/server.lua b/resources/[standalone]/vms_firework/server.lua new file mode 100644 index 000000000..e944e2788 --- /dev/null +++ b/resources/[standalone]/vms_firework/server.lua @@ -0,0 +1,37 @@ +if Config.Core == "ESX" then + for k, v in pairs(Config.Fireworks) do + if v.item then + ESX.RegisterUsableItem(v.item, function(source) + local xPlayer = ESX.GetPlayerFromId(source) + if Config.NeedLighter then + local isHaveLighter = xPlayer.getInventoryItem(Config.LighterItem).count + if isHaveLighter == 0 then + return TriggerClientEvent('vms_firework:notification', source, 'NEED_LIGHTER', 5000, 'error') + end + end + if v.itemRemovable then + xPlayer.removeInventoryItem(v.item, 1) + end + TriggerClientEvent('vms_firework:startFirework', source, k) + end) + end + end +elseif Config.Core == "QB-Core" then + for k, v in pairs(Config.Fireworks) do + if v.item then + QBCore.Functions.CreateUseableItem(v.item, function(source, item) + local Player = QBCore.Functions.GetPlayer(source) + if Config.NeedLighter then + local isHaveLighter = Player.Functions.GetItemByName(Config.LighterItem) + if isHaveLighter == nil or isHaveLighter.amount == 0 then + return TriggerClientEvent('vms_firework:notification', source, 'NEED_LIGHTER', 5000, 'error') + end + end + if v.itemRemovable then + Player.Functions.RemoveItem(v.item, 1, false) + end + TriggerClientEvent('vms_firework:startFirework', source, k) + end) + end + end +end \ No newline at end of file