FiveM वेदर सिंक: डायनामिक वेदर और टाइम स्क्रिप्ट्स
अपने FiveM सर्वर पर मौसम और समय सिंक करें। डायनामिक साइकल्स, थंडर, स्नो, सीजन पैक्स और मूड सेट करने के लिए सर्वश्रेष्ठ वेदर स्क्रिप्ट्स।
Agency Scripts
Agency Scripts के संस्थापक और प्रमुख डेवलपर
असामंजस्यपूर्ण मौसम की समस्या
डिफ़ॉल्ट रूप से, GTA V प्रत्येक क्लाइंट पर मौसम और समय को स्वतंत्र रूप से नियंत्रित करता है। इसका मतलब है कि एक खिलाड़ी तेज धूप में ड्राइव कर सकता है जबकि उसके बिल्कुल पास खड़ा दूसरा खिलाड़ी तूफान देख रहा होता है। रोलप्ले सर्वरों के लिए, यह पूरी तरह से immersion तोड़ देता है। कल्पना करें कि एक दृश्य समन्वयित करने की कोशिश कर रहे हैं जहाँ एक चरित्र बारिश की शिकायत करता है जबकि दूसरे खिलाड़ी की स्क्रीन पर साफ आसमान दिख रहा है। एक सिंक्रनाइज़्ड मौसम और समय प्रणाली सुनिश्चित करती है कि सर्वर पर हर खिलाड़ी एक ही समय पर एक ही वातावरण का अनुभव करे, जो सुसंगत रोलप्ले, यथार्थवादी ड्राइविंग स्थितियों, और इवेंट समन्वय के लिए मौलिक है। इस ट्यूटोरियल में, हम एक पूर्ण मौसम सिंक्रनाइज़ेशन सिस्टम बनाएंगे जिसमें कॉन्फ़िगर करने योग्य समय गति, मौसमी परिवर्तन, मौसम मतदान, और ब्लैकआउट इवेंट शामिल हैं।
सर्वर-साइड मौसम स्थिति प्रबंधन
सर्वर मौसम और समय के लिए एकमात्र सत्य स्रोत है। यह वर्तमान मौसम प्रकार, संक्रमण के लिए अगला मौसम प्रकार, और इन-गेम घड़ी बनाए रखता है। प्रत्येक क्लाइंट इस स्थिति के साथ सिंक होता है जब वे जुड़ते हैं और मौसम बदलने पर अपडेट प्राप्त करते हैं। GTA V विशिष्ट मौसम प्रकारों का समर्थन करता है जिनमें शामिल हैं CLEAR, EXTRASUNNY, CLOUDS, OVERCAST, RAIN, THUNDER, CLEARING, FOGGY, SMOG, SNOW, SNOWLIGHT, BLIZZARD, और XMAS. तार्किक संक्रमण नियम परिभाषित करें ताकि मौसम प्राकृतिक रूप से प्रवाहित हो, बिना बर्फ़ीले तूफ़ान से सीधे अत्यधिक धूप में कूदे, मध्यवर्ती अवस्था के बिना।
-- server.lua
local Config = {
timeSpeed = 2, -- how many in-game minutes per real second
syncInterval = 30000, -- full sync broadcast every 30s
autoChange = true, -- automatic weather cycling
changeCooldown = 600, -- seconds between automatic changes
}
local State = {
weather = 'CLEAR',
nextWeather = 'CLOUDS',
hour = 12,
minute = 0,
frozen = false,
blackout = false,
season = 'summer',
}
local weatherTransitions = {
EXTRASUNNY = {'CLEAR', 'CLOUDS'},
CLEAR = {'EXTRASUNNY', 'CLOUDS', 'OVERCAST'},
CLOUDS = {'CLEAR', 'OVERCAST', 'RAIN'},
OVERCAST = {'CLOUDS', 'RAIN', 'THUNDER', 'FOGGY'},
RAIN = {'OVERCAST', 'THUNDER', 'CLEARING'},
THUNDER = {'RAIN', 'OVERCAST'},
CLEARING = {'CLEAR', 'CLOUDS'},
FOGGY = {'CLEAR', 'CLOUDS', 'SMOG'},
SMOG = {'FOGGY', 'CLEAR'},
}
local seasonWeights = {
summer = {EXTRASUNNY = 30, CLEAR = 30, CLOUDS = 20, RAIN = 10, THUNDER = 5, FOGGY = 5},
winter = {CLOUDS = 20, OVERCAST = 20, SNOW = 25, SNOWLIGHT = 15, BLIZZARD = 10, FOGGY = 10},
spring = {CLEAR = 25, CLOUDS = 25, RAIN = 20, CLEARING = 15, FOGGY = 10, OVERCAST = 5},
autumn = {CLOUDS = 25, OVERCAST = 25, RAIN = 20, FOGGY = 15, CLEAR = 10, SMOG = 5},
}
समय प्रगति और सिंक्रनाइज़ेशन लूप
टाइम सिस्टम एक सर्वर-साइड लूप के रूप में चलता है जो कॉन्फ़िगर की गई गति के आधार पर इन-गेम घड़ी को बढ़ाता है। एक timeSpeed 2 का अर्थ है कि हर वास्तविक दुनिया का सेकंड इन-गेम घड़ी को 2 मिनट आगे बढ़ाता है। इससे एक दिन-रात चक्र बनता है जो लगभग 12 वास्तविक मिनट में पूरे 24 इन-गेम घंटे पूरे करता है। सर्वर नियमित अंतराल पर सभी क्लाइंट्स को वर्तमान समय और मौसम की स्थिति प्रसारित करता है और जब कोई एडमिन मौसम बदलता है या blackout इवेंट ट्रिगर करता है तो तुरंत अपडेट भेजता है। मध्य-सत्र में शामिल होने वाले नए खिलाड़ी समर्पित सिंक इवेंट के माध्यम से वर्तमान स्थिति प्राप्त करते हैं ताकि वे तुरंत सभी के साथ मेल खाएं।
-- Time progression loop (server.lua continued)
CreateThread(function()
while true do
Wait(1000)
if not State.frozen then
State.minute = State.minute + Config.timeSpeed
if State.minute >= 60 then
State.hour = State.hour + math.floor(State.minute / 60)
State.minute = State.minute % 60
end
if State.hour >= 24 then
State.hour = State.hour % 24
end
end
end
end)
-- Periodic full sync
CreateThread(function()
while true do
Wait(Config.syncInterval)
TriggerClientEvent('weather:fullSync', -1, State)
end
end)
-- Sync new players on join
AddEventHandler('playerJoining', function()
local src = source
Wait(2000)
TriggerClientEvent('weather:fullSync', src, State)
end)
क्लाइंट-साइड वेदर एप्लीकेशन
क्लाइंट पर, आपको GTA के मूल मौसम और समय प्रणालियों को ओवरराइड करना होगा। मुख्य natives हैं SetWeatherTypeNowPersist तत्काल मौसम परिवर्तनों के लिए, SetWeatherTypeTransition दो मौसम स्थितियों के बीच स्मूद ब्लेंडिंग के लिए, और NetworkOverrideClockTime इन-गेम क्लॉक सेट करने के लिए। आपको कॉल करना होगा NetworkOverrideClockTime खेल को अपनी समय गणना पर वापस जाने से रोकने के लिए हर फ्रेम। मौसम संक्रमण के लिए, GTA 0.0 से 1.0 के बीच एक blend factor का समर्थन करता है जो आपको कई सेकंड में दो मौसम स्थितियों के बीच सहजता से इंटरपोलेट करने देता है, जिससे वास्तविकवादी संक्रमण बनते हैं जहां बादल धीरे-धीरे घिरते हैं और फिर बारिश शुरू होती है।
-- client.lua
local currentWeather = 'CLEAR'
local nextWeather = 'CLEAR'
local weatherBlend = 0.0
local hour, minute = 12, 0
local blackout = false
RegisterNetEvent('weather:fullSync', function(state)
currentWeather = state.weather
nextWeather = state.nextWeather or state.weather
hour = state.hour
minute = state.minute
blackout = state.blackout or false
applyWeather()
end)
function applyWeather()
ClearOverrideWeather()
ClearWeatherTypePersist()
SetWeatherTypeNowPersist(currentWeather)
if currentWeather ~= nextWeather then
SetWeatherTypeTransition(
GetHashKey(currentWeather),
GetHashKey(nextWeather),
weatherBlend
)
end
if blackout then
SetArtificialLightsState(true)
SetArtificialLightsStateAffectsVehicles(false)
else
SetArtificialLightsState(false)
end
end
-- Override clock every frame
CreateThread(function()
while true do
Wait(0)
NetworkOverrideClockTime(hour, minute, 0)
end
end)
Weather Voting System
एक मौसम मतदान प्रणाली आपके समुदाय को लोकतांत्रिक रूप से मौसम तय करने देती है। खिलाड़ी अपनी पसंद के मौसम प्रकार के लिए वोट डाल सकते हैं, और मतदान अवधि के बाद सबसे लोकप्रिय विकल्प जीतता है। यह उन इवेंट्स के लिए अच्छा काम करता है जहां आप खिलाड़ी की भागीदारी चाहते हैं, जैसे यह तय करना कि कार मीट साफ आसमान के नीचे हो या नाटकीय तूफानों के दौरान। स्पैम रोकने के लिए मतदान को प्रति चक्र एक बार सीमित करें, और अपने सूचना प्रणाली या एक सरल NUI ओवरले के माध्यम से वर्तमान वोट गणना प्रदर्शित करें। सर्वर वोट एकत्र करता है, अवधि समाप्त होने पर उन्हें गिनता है, और विजेता मौसम को एक चिकनी संक्रमण के माध्यम से लागू करता है ताकि सभी खिलाड़ी एक साथ परिवर्तन का अनुभव करें।
-- Weather voting (server.lua)
local votes = {}
local voteCooldown = {}
local votingOpen = false
local voteOptions = {'CLEAR', 'RAIN', 'THUNDER', 'FOGGY', 'SNOW'}
RegisterCommand('voteweather', function(source, args)
if not votingOpen then
TriggerClientEvent('chat:addMessage', source, {args = {'Weather', 'No vote is currently active.'}})
return
end
if voteCooldown[source] then
TriggerClientEvent('chat:addMessage', source, {args = {'Weather', 'You already voted this round.'}})
return
end
local choice = string.upper(args[1] or '')
local valid = false
for _, opt in ipairs(voteOptions) do
if opt == choice then valid = true break end
end
if not valid then
TriggerClientEvent('chat:addMessage', source, {
args = {'Weather', 'Options: ' .. table.concat(voteOptions, ', ')}
})
return
end
votes[choice] = (votes[choice] or 0) + 1
voteCooldown[source] = true
TriggerClientEvent('chat:addMessage', -1, {
args = {'Weather', GetPlayerName(source) .. ' voted for ' .. choice}
})
end, false)
function startWeatherVote()
votes = {}
voteCooldown = {}
votingOpen = true
TriggerClientEvent('chat:addMessage', -1, {
args = {'Weather', 'Weather vote started! Use /voteweather [type]. Options: ' .. table.concat(voteOptions, ', ')}
})
SetTimeout(60000, function()
votingOpen = false
local winner, maxVotes = 'CLEAR', 0
for weather, count in pairs(votes) do
if count > maxVotes then winner = weather; maxVotes = count end
end
transitionWeather(winner)
TriggerClientEvent('chat:addMessage', -1, {
args = {'Weather', 'Vote ended! Weather changing to: ' .. winner}
})
end)
end
गेमप्ले पर मौसमी सिस्टम और मौसम प्रभाव
एक मौसमी प्रणाली एक गहराई की परत जोड़ती है जिसे अधिकांश सर्वर नजरअंदाज करते हैं। इन-गेम कैलेंडर को ट्रैक करके या वास्तविक दुनिया के महीनों को मौसमों से मैप करके, आप मौसम की संभावनाओं को तदनुसार वजन दे सकते हैं। गर्मी साफ और धूप वाले मौसम को प्राथमिकता देती है जिसमें कभी-कभी तूफान आते हैं, जबकि सर्दी संतुलन को बर्फ, बादल, और कोहरे की ओर ले जाती है। मौसम केवल दृश्य प्रभावों से परे गेमप्ले मैकेनिक्स को भी प्रभावित कर सकते हैं। बारिश के दौरान, आप सभी सक्रिय वाहनों पर हैंडलिंग मॉडिफायर ट्रिगर करके वाहन ट्रैक्शन को कम कर सकते हैं। कोहरा AI पैड के लिए रेंडर दूरी को कम कर सकता है, जिससे छिपकर खेलने की संभावना बढ़ती है। बर्फ खिलाड़ी की गति को थोड़ा धीमा कर सकती है और धीमी स्वास्थ्य हानि से बचने के लिए सर्दियों के कपड़ों की आवश्यकता होती है। ये छोटे स्पर्श एक ऐसा वातावरण बनाते हैं जो जीवंत और अपने पर्यावरण के प्रति संवेदनशील महसूस होता है।
ब्लैकआउट इवेंट्स और एडमिन कंट्रोल्स
ब्लैकआउट इवेंट्स सर्वर इवेंट्स और रोलप्ले परिदृश्यों के लिए एक शक्तिशाली उपकरण हैं। SetArtificialLightsState native खेल की दुनिया में सभी कृत्रिम प्रकाश स्रोतों को अक्षम करता है, जिससे शहर अंधकार में डूब जाता है। बादल छाए या कोहरे वाले मौसम की स्थिति के साथ मिलकर, यह एक अविश्वसनीय रूप से वातावरणीय माहौल बनाता है जो हॉरर इवेंट्स, डकैती परिदृश्यों, या सर्वाइवल रोलप्ले के लिए उपयुक्त है। एडमिन कमांड्स को मौसम प्रणाली पर पूर्ण नियंत्रण प्रदान करना चाहिए: समय को फ्रीज करना, विशिष्ट घंटे सेट करना, मौसम प्रकारों को मजबूर करना, ब्लैकआउट ट्रिगर करना, और मौसम वोट शुरू करना। इन कमांड्स को ace अनुमतियों से सुरक्षित करें ताकि केवल अधिकृत स्टाफ पर्यावरण को संशोधित कर सके। एक अच्छी तरह से डिज़ाइन किया गया मौसम सिस्टम एक कहानी कहने का उपकरण बन जाता है जिसका उपयोग एडमिन आपके सर्वर पर हर इवेंट और परिदृश्य के मूड को सेट करने के लिए करते हैं।
-- Admin commands (server.lua)
RegisterCommand('setweather', function(source, args)
if source > 0 and not IsPlayerAceAllowed(source, 'command.setweather') then return end
local weather = string.upper(args[1] or 'CLEAR')
transitionWeather(weather)
TriggerClientEvent('chat:addMessage', -1, {
args = {'Admin', 'Weather changed to ' .. weather}
})
end, true)
RegisterCommand('settime', function(source, args)
if source > 0 and not IsPlayerAceAllowed(source, 'command.settime') then return end
State.hour = tonumber(args[1]) or 12
State.minute = tonumber(args[2]) or 0
TriggerClientEvent('weather:fullSync', -1, State)
end, true)
RegisterCommand('blackout', function(source, args)
if source > 0 and not IsPlayerAceAllowed(source, 'command.blackout') then return end
State.blackout = not State.blackout
TriggerClientEvent('weather:fullSync', -1, State)
TriggerClientEvent('chat:addMessage', -1, {
args = {'Admin', 'Blackout ' .. (State.blackout and 'enabled' or 'disabled')}
})
end, true)
RegisterCommand('freezetime', function(source, args)
if source > 0 and not IsPlayerAceAllowed(source, 'command.freezetime') then return end
State.frozen = not State.frozen
TriggerClientEvent('chat:addMessage', -1, {
args = {'Admin', 'Time ' .. (State.frozen and 'frozen' or 'unfrozen')}
})
end, true)