forked from Simnation/Main
firework
This commit is contained in:
parent
050ff54c7d
commit
1841025156
6 changed files with 316 additions and 881 deletions
|
@ -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)
|
|
||||||
|
|
||||||
|
|
5
resources/[standalone]/vms_firework/README.md
Normal file
5
resources/[standalone]/vms_firework/README.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|

|
||||||
|
|
||||||
|
# vms_firework
|
||||||
|
|
||||||
|
### https://discord.gg/k4YNwYxE4h
|
111
resources/[standalone]/vms_firework/client.lua
Normal file
111
resources/[standalone]/vms_firework/client.lua
Normal file
|
@ -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)
|
146
resources/[standalone]/vms_firework/config.lua
Normal file
146
resources/[standalone]/vms_firework/config.lua
Normal file
|
@ -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},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
}
|
17
resources/[standalone]/vms_firework/fxmanifest.lua
Normal file
17
resources/[standalone]/vms_firework/fxmanifest.lua
Normal file
|
@ -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'
|
||||||
|
}
|
37
resources/[standalone]/vms_firework/server.lua
Normal file
37
resources/[standalone]/vms_firework/server.lua
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue