├── ACE perms example.cfg ├── LICENSE ├── README.md ├── config ├── Keybinds.lua └── ServerSync.lua ├── fxmanifest.lua ├── ss_cli_indicators.lua ├── ss_cli_time.lua ├── ss_cli_traffic_crowd.lua ├── ss_cli_weather.lua ├── ss_cli_windows.lua ├── ss_shared_functions.lua ├── ss_srv_indicators.lua ├── ss_srv_time.lua ├── ss_srv_weather.lua └── ss_srv_windows.lua /ACE perms example.cfg: -------------------------------------------------------------------------------- 1 | add_principal identifier.steam:110000102D010D9 group.sync #Wyste 2 | 3 | add_ace group.sync "changeWeather" allow 4 | add_ace group.sync "changeTime" allow 5 | add_ace group.sync "freezeTime" allow 6 | 7 | add_ace group.sync command.weather allow 8 | add_ace group.sync command.time allow 9 | add_ace group.sync command.freezetime allow -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Wyste 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ServerSync 2 | A FiveM resource to keep all players synchronized with both time and weather, with smooth transitions and wind. 3 | 4 | ## Features 5 | - Synchronized Time for all players 6 | - Synchronized Weather for all players 7 | - Synchronized Wind for all weather types 8 | - (Optional) Vehicle turn signal indicator synchronization 9 | - (Optional) Vehicle window up/down synchronization 10 | - Customizable weather patterns 11 | - Customizable day / night cycle lengths. 12 | 13 | ## Changelog 14 | v1.1 15 | * Added chat suggestion for the /time command. 16 | * Added error handling for weird /time arguments. 17 | 18 | v1.2 19 | * Fixes Typo error caused by ss_cli_indicators.lua in lines 27 and 31 20 | * Adds functionality for turning the traffic or crowd modules on/off using `ss_enable_traffic_density` or `ss_enable_crowd_density` 21 | 22 | ## Requirements 23 | - None. You only need this resource. 24 | 25 | ## Download / Installation 26 | 27 | ### GIT 28 | 29 | ``` 30 | cd resources 31 | git clone https://github.com/Wyste/ServerSync.git ServerSync 32 | ``` 33 | 34 | ### Manually 35 | - Download https://github.com/Wyste/ServerSync/archive/master.zip 36 | - Put it in the `resource/ServerSync` directory 37 | 38 | ### Installation / Activation 39 | - [Optional] Change your options within `ServerSync\config\ServerSync.lua` 40 | - Configure your `server.cfg` to look like this 41 | 42 | ``` 43 | ensure ServerSync 44 | ``` 45 | 46 | - Add ACE permissions to use the commands: 47 | ``` 48 | add_principal identifier.steam:110000102D010D9 group.sync #Wyste 49 | 50 | add_ace group.sync "changeWeather" allow 51 | add_ace group.sync "changeTime" allow 52 | add_ace group.sync "freezeTime" allow 53 | 54 | add_ace group.sync command.weather allow 55 | add_ace group.sync command.time allow 56 | add_ace group.sync command.freezetime allow 57 | 58 | ``` 59 | -------------------------------------------------------------------------------- /config/Keybinds.lua: -------------------------------------------------------------------------------- 1 | --##################################################################################################################### 2 | --# ServerSync KeyBinding Options # 3 | --##################################################################################################################### 4 | 5 | -- Keybind Reference: https://docs.fivem.net/game-references/controls/ 6 | 7 | -- The below keybinds only apply if ServerSync's window/indicator options are enabled: 8 | keybinds={ indi={}, windows={} } 9 | keybinds.indi.inputGroup = 1 -- Look Mode 10 | keybinds.indi.left = 82 -- Comma Key 11 | keybinds.indi.right = 81 -- Period Key 12 | keybinds.windows.inputGroup = 1 -- Look Mode 13 | keybinds.windows.up = 27 -- Up Arrow 14 | keybinds.windows.down = 173 -- Down Arrow -------------------------------------------------------------------------------- /config/ServerSync.lua: -------------------------------------------------------------------------------- 1 | --##################################################################################################################### 2 | --# ServerSync Main Config Options # 3 | --##################################################################################################################### 4 | -- Enable Debug output to the console window 5 | ss_show_console_output = false 6 | 7 | -- Enable Weather Syncing between all Players? Options: true or false 8 | ss_enable_weather_sync = true 9 | 10 | -- Enable Time Syncing between all Players? Options: true or false 11 | ss_enable_time_sync = true 12 | 13 | -- Enable Dynamic Wind Speed Syncing between all Players? Options: true or false 14 | -- Note: Disabling this option will turn all wind effects in your server OFF (i.e. no wind movement at all). 15 | ss_enable_wind_sync = true 16 | 17 | -- Traffic / Crowd density modules. 18 | ss_enable_traffic_density = true 19 | ss_enable_crowd_density = true 20 | 21 | -- Vehicle syncing between players. If you use another resource, disable these. 22 | ss_enable_turn_signal_sync = true 23 | ss_enable_door_window_sync = true 24 | 25 | -- Extra options if you don't already have these in other resources 26 | ss_enable_police_ignore_player = true 27 | ss_enable_no_wanted_level = true 28 | ss_enable_everyone_ignores_player = true 29 | ss_enable_random_cop_spawn = false -- This will set SetCreateRandomCopsNotOnScenarios and SetCreateRandomCops to what you picked. 30 | ss_enable_random_boat_spawn = true 31 | ss_enable_garbage_truck_spawn = true 32 | 33 | 34 | --##################################################################################################################### 35 | --# ServerSync Traffic / Crowd Options # 36 | --##################################################################################################################### 37 | 38 | -- Maximum traffic density for all players. Default is 0.9999 39 | ss_traffic_max_density = 0.9999 40 | 41 | -- Enable scaling density by players. (More Players = Less AI Traffic, with a absolute minimum setting of 0.5) 42 | ss_enable_traffic_scaling = true 43 | 44 | -- Maximum crowd density for all players. Default is 0.9999 45 | ss_crowd_max_density = 0.9999 46 | 47 | -- Enable scaling density by players. (More Players = Less AI Pedestrians, with a absolute minimum setting of 0.5) 48 | ss_enable_crowd_scaling = true 49 | 50 | --##################################################################################################################### 51 | --# ServerSync WEATHER Options # 52 | --##################################################################################################################### 53 | 54 | -- Enable Dynamic (changing) weather for the players? Options: true or false 55 | ss_enable_dynamic_weather = true 56 | 57 | -- Default weather type for when the resource starts 58 | -- Options: EXTRASUNNY, CLEAR, NEUTRAL, SMOG, FOGGY, OVERCAST, CLOUDS, CLEARING, 59 | -- Options: RAIN, THUNDER, SNOW, BLIZZARD, SNOWLIGHT, XMAS, HALLOWEEN 60 | ss_default_weather = "EXTRASUNNY" 61 | 62 | -- Weather timer (in minutes) between dynamic weather changes (Default: 10minutes) 63 | ss_weather_timer = 15 64 | 65 | ss_reduce_rain_chance = true 66 | 67 | -- Weather timeout for rain (in minutes). This means it can only rain once every X minutes - Default: 60 minutes) 68 | ss_rain_timeout = 45 69 | 70 | -- Weather transitions are configured here, pay attention to the example. 71 | -- Example: ["CurrentWeather"] = {"Next Possible Weather 1", "Next Possible Weather 2"} 72 | -- Note: Default config only uses fairly 'clear' weather options to stay away from foggy environment effects. 73 | ss_weather_Transition = { 74 | ["EXTRASUNNY"] = {"CLEAR","SMOG"}, 75 | ["SMOG"] = {"CLEAR","CLEARING","OVERCAST","CLOUDS","EXTRASUNNY"}, 76 | ["CLEAR"] = {"CLOUDS","EXTRASUNNY","CLEARING","SMOG","OVERCAST"}, 77 | ["CLOUDS"] = {"CLEAR","SMOG","CLEARING","OVERCAST"}, 78 | ["OVERCAST"] = {"CLEAR","CLOUDS","SMOG","CLEARING","THUNDER"}, 79 | ["RAIN"] = {"CLEAR", "OVERCAST", "CLOUDS", "CLEARING"}, 80 | ["THUNDER"] = {"OVERCAST"}, -- Always rotate away from Thunder, as it's annoying 81 | ["CLEARING"] = {"CLEAR","CLOUDS","OVERCAST","SMOG"}, 82 | ["SNOW"] = {"SNOW","SNOWLIGHT"}, -- Usually used for events - never changes and has to be manually set via /weather command 83 | ["SNOWLIGHT"] = {"SNOW","SNOWLIGHT"}, -- Usually used for events - never changes and has to be manually set via /weather command 84 | ["BLIZZARD"] = {"BLIZZARD"}, -- Usually used for events - never changes and has to be manually set via /weather command 85 | ["XMAS"] = {"XMAS"}, -- Usually used for events - never changes and has to be manually set via /weather command 86 | ["HALLOWEEN"] = {"HALLOWEEN"} -- Usually used for events - never changes and has to be manually set via /weather command 87 | } 88 | 89 | --##################################################################################################################### 90 | --# ServerSync WIND Options # 91 | --##################################################################################################################### 92 | 93 | 94 | -- Wind Speed maximum. Default: Max = 2.00 95 | ss_wind_speed_max = 10.00 96 | 97 | -- Effectiveness of Current Weather Wind Speed. 98 | -- Default for Extrasunny is 0.5. This means that the max wind speed above is multiplied by 0.5 to get 1.0 wind speed 99 | ss_wind_speed_Mult = { 100 | ["EXTRASUNNY"] = 0.2 * ss_wind_speed_max, 101 | ["SMOG"] = 0.1 * ss_wind_speed_max, 102 | ["CLEAR"] = 0.3 * ss_wind_speed_max, 103 | ["CLOUDS"] = 0.1 * ss_wind_speed_max, 104 | ["OVERCAST"] = 0.7 * ss_wind_speed_max, 105 | ["THUNDER"] = 1.0 * ss_wind_speed_max, 106 | ["CLEARING"] = 0.7 * ss_wind_speed_max, 107 | ["SNOW"] = 0.6 * ss_wind_speed_max, 108 | ["SNOWLIGHT"] = 0.4 * ss_wind_speed_max, 109 | ["BLIZZARD"] = 0.8 * ss_wind_speed_max, 110 | ["XMAS"] = 0.4 * ss_wind_speed_max, 111 | ["HALLOWEEN"] = 0.8 * ss_wind_speed_max 112 | } 113 | 114 | --##################################################################################################################### 115 | --# ServerSync DAY/NIGHT TIME Speed Options # 116 | --##################################################################################################################### 117 | 118 | -- Lower then 1 = Longer, Higher then 1 = faster. 0.25 would be 4x slower then GTA time. 2.0 would be half as long as default GTA 119 | ss_night_time_speed_mult = 1.0 120 | ss_day_time_speed_mult = 1.0 121 | -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | --ServerSync Resource made by Wyste for Fivem-- 2 | --Repository: https://github.com/Wyste/ServerSync -- 3 | 4 | name 'ServerSync' 5 | description 'Syncronizes Time/Weather/Wind and more.' 6 | author 'Wyste (https://github.com/Wyste) | (https://discordapp.com/invite/byNc6wA)' 7 | version 'v1.0' 8 | url 'https://github.com/Wyste/ServerSync' 9 | 10 | fx_version 'cerulean' 11 | game 'gta5' 12 | 13 | client_scripts { 14 | 'ss_shared_functions.lua', 15 | 'config/Keybinds.lua', 16 | 'config/ServerSync.lua', 17 | 'ss_cli_indicators.lua', 18 | 'ss_cli_windows.lua', 19 | 'ss_cli_traffic_crowd.lua', 20 | 'ss_cli_weather.lua', 21 | 'ss_cli_time.lua' 22 | } 23 | 24 | server_scripts { 25 | 'ss_shared_functions.lua', 26 | 'config/ServerSync.lua', 27 | 'ss_srv_indicators.lua', 28 | 'ss_srv_windows.lua', 29 | 'ss_srv_weather.lua', 30 | 'ss_srv_time.lua' 31 | } 32 | -------------------------------------------------------------------------------- /ss_cli_indicators.lua: -------------------------------------------------------------------------------- 1 | if ss_enable_turn_signal_sync then 2 | 3 | local vehicleState = { 4 | indicator = { 5 | left = false, 6 | right = false 7 | } 8 | } 9 | 10 | RegisterNetEvent('VehicleIndicator') 11 | AddEventHandler( "VehicleIndicator", function( playerID, dir, state ) 12 | SetVehicleIndicatorLights( GetVehiclePedIsIn( GetPlayerPed( GetPlayerFromServerId( playerID ) ), false ), dir, state ) 13 | end) 14 | 15 | 16 | Citizen.CreateThread( function() 17 | while true do 18 | Citizen.Wait(10) 19 | if IsPedInAnyVehicle( GetPlayerPed( -1 ), false ) then 20 | local pressedLeft = IsControlJustPressed( keybinds.indi.inputGroup, keybinds.indi.left ) or false 21 | local pressedRight = IsControlJustPressed( keybinds.indi.inputGroup, keybinds.indi.right ) or false 22 | if pressedLeft or pressedRight then 23 | local vehicle = GetVehiclePedIsIn( GetPlayerPed( -1 ), false ) 24 | if GetPedInVehicleSeat( vehicle, - 1 ) == GetPlayerPed( -1 ) then 25 | if pressedLeft then 26 | vehicleState.indicator.left = not vehicleState.indicator.left 27 | TriggerServerEvent( "ServerSync:SetVehicleIndicator", 1, vehicleState.indicator.left ) 28 | end 29 | if pressedRight then 30 | vehicleState.indicator.right = not vehicleState.indicator.right 31 | TriggerServerEvent( "ServerSync:SetVehicleIndicator", 0, vehicleState.indicator.right ) 32 | end 33 | end 34 | end 35 | end 36 | end 37 | end) 38 | 39 | end -------------------------------------------------------------------------------- /ss_cli_time.lua: -------------------------------------------------------------------------------- 1 | local frozen = false 2 | local client_date = {} 3 | local NEWsecondOfDay = 0 4 | local secondOfDay = 5000 -- this ensure's we are desynced 5 | 6 | AddEventHandler( "onClientMapStart", function() 7 | TriggerServerEvent( "addTimeChatSuggests" ) 8 | end) 9 | 10 | RegisterNetEvent("updateFromServerTime") 11 | AddEventHandler("updateFromServerTime", function(serverSecondOfDay,serverDate,isTimeFrozen) 12 | frozen = isTimeFrozen 13 | NEWsecondOfDay = serverSecondOfDay 14 | client_date = serverDate 15 | end) 16 | 17 | Citizen.CreateThread( function() 18 | local timeBuffer = 0.0 19 | local h = 0 20 | local m = 0 21 | local s = 0 22 | while true do 23 | if NEWsecondOfDay < ( secondOfDay - 400 ) or NEWsecondOfDay > ( secondOfDay + 400) then -- The Actual Sync check 24 | --Citizen.Trace("Time is out of sync... variance (Seconds of Game Day):"..tostring(secondOfDay - NEWsecondOfDay)) 25 | secondOfDay = NEWsecondOfDay 26 | end 27 | Citizen.Wait(33) -- (int)(GetMillisecondsPerGameMinute() / 60) 28 | if not frozen then 29 | local gameSecond = 33.33 / ss_night_time_speed_mult 30 | if secondOfDay >= 19800 and secondOfDay <= 75600 then 31 | gameSecond = 33.333 / ss_day_time_speed_mult 32 | end 33 | timeBuffer = timeBuffer + round( 33.0 / gameSecond, 4 ) 34 | if timeBuffer >= 1.0 then 35 | local skipSeconds = math.floor( timeBuffer ) 36 | timeBuffer = timeBuffer - skipSeconds 37 | secondOfDay = secondOfDay + skipSeconds 38 | if secondOfDay >= 86400 then 39 | secondOfDay = secondOfDay % 86400 40 | end 41 | end 42 | end 43 | h = math.floor( secondOfDay / 3600 ) 44 | m = math.floor( (secondOfDay - (h * 3600)) / 60 ) 45 | s = secondOfDay - (h * 3600) - (m * 60) 46 | secondOfDay = (h * 3600) + (m * 60) + s 47 | NetworkOverrideClockTime( math.floor( secondOfDay / 3600 ), math.floor( (secondOfDay - (h * 3600)) / 60 ), secondOfDay - (math.floor( secondOfDay / 3600 ) * 3600) - (math.floor( (secondOfDay - (h * 3600)) / 60 ) * 60) ) 48 | end 49 | end) 50 | 51 | RegisterNetEvent("addTimeChatSuggests") 52 | AddEventHandler("addTimeChatSuggests", function() 53 | TriggerEvent('chat:addSuggestion', '/time', 'Change the time.', { 54 | { name="hour" , help="Hour of day in 24 hour format."}, 55 | { name="minute", help="Minute of the hour."} 56 | }) 57 | end) -------------------------------------------------------------------------------- /ss_cli_traffic_crowd.lua: -------------------------------------------------------------------------------- 1 | local cv = GetConvarInt('sv_maxclients', 64) -- Future Proofing for oneSync 2 | local onlinePlayers = 1 3 | 4 | local ncrowd = ss_crowd_max_density - ( onlinePlayers / cv / ( 2 / ss_crowd_max_density ) ) 5 | 6 | if ss_enable_traffic_density then 7 | local ntraff = ss_traffic_max_density - ( onlinePlayers / cv / ( 2 / ss_traffic_max_density ) ) 8 | end 9 | 10 | if ss_enable_traffic_density or ss_enable_crowd_density then 11 | Citizen.CreateThread(function() 12 | while true do 13 | Citizen.Wait(10000) -- Check every ten seconds 14 | 15 | local playerpos = GetEntityCoords(GetPlayerPed(-1),false) 16 | if playerpos['z'] < -100.0 then 17 | --Citizen.Trace("Setting Traffic/Ped Density to 0.0 - you are underground, and this be crazy.") 18 | if ss_enable_crowd_density then ncrowd = 0.0 end 19 | if ss_enable_traffic_density and ss_enable_traffic_density then ntraff = 0.0 end -- Can't set absolute zero on floats, so we go REALLY low 20 | else 21 | if ss_enable_traffic_density or ss_enable_crowd_density then 22 | if ss_enable_crowd_scaling or ss_enable_traffic_scaling then 23 | onlinePlayers = 0 24 | for i = 0, 63 do 25 | if NetworkIsPlayerActive(i) then 26 | onlinePlayers = onlinePlayers + 1 27 | end 28 | end 29 | if ss_enable_crowd_density then ncrowd = ss_crowd_max_density - ( onlinePlayers / cv / ( 2 / ss_crowd_max_density ) ) end 30 | if ss_enable_traffic_density then ntraff = ss_traffic_max_density - ( onlinePlayers / cv / ( 2 / ss_traffic_max_density ) ) end 31 | end 32 | end 33 | end 34 | end 35 | end) 36 | end 37 | 38 | Citizen.CreateThread(function() 39 | local player = GetPlayerPed( -1 ) 40 | while true do 41 | Citizen.Wait(0) 42 | 43 | if ss_enable_police_ignore_player then SetPoliceIgnorePlayer(player, true) end 44 | 45 | if ss_enable_no_wanted_level then 46 | SetMaxWantedLevel(0) 47 | ClearPlayerWantedLevel(player) 48 | end 49 | 50 | if ss_enable_everyone_ignores_player then 51 | SetEveryoneIgnorePlayer(player, true) 52 | SetPlayerCanBeHassledByGangs(player, false) 53 | SetIgnoreLowPriorityShockingEvents(player, true) 54 | end 55 | 56 | if ss_enable_random_cop_spawn then 57 | SetCreateRandomCopsNotOnScenarios(false) 58 | SetCreateRandomCops(false) 59 | end 60 | 61 | if ss_enable_random_boat_spawn then SetRandomBoats(true) end 62 | if ss_enable_garbage_truck_spawn then SetGarbageTrucks(true) end 63 | 64 | 65 | if ss_enable_crowd_density then 66 | if ss_enable_crowd_scaling then 67 | SetPedDensityMultiplierThisFrame( ncrowd ) 68 | SetScenarioPedDensityMultiplierThisFrame(ncrowd, ncrowd) 69 | else 70 | SetPedDensityMultiplierThisFrame( ss_crowd_max_density ) 71 | SetScenarioPedDensityMultiplierThisFrame(ss_crowd_max_density, ss_crowd_max_density) 72 | end 73 | end 74 | 75 | --Traffic 76 | if ss_enable_traffic_density then 77 | if ss_enable_traffic_scaling then 78 | SetVehicleDensityMultiplierThisFrame( ntraff ) 79 | SetRandomVehicleDensityMultiplierThisFrame( ntraff ) 80 | SetParkedVehicleDensityMultiplierThisFrame( ntraff ) 81 | else 82 | SetVehicleDensityMultiplierThisFrame( ss_traffic_max_density ) 83 | SetRandomVehicleDensityMultiplierThisFrame( ss_traffic_max_density ) 84 | SetParkedVehicleDensityMultiplierThisFrame( ss_traffic_max_density ) 85 | end 86 | end 87 | 88 | end 89 | end) 90 | -------------------------------------------------------------------------------- /ss_cli_weather.lua: -------------------------------------------------------------------------------- 1 | local currentWeather = ss_default_weather 2 | local transistioning = false 3 | 4 | AddEventHandler( "onClientMapStart", function() 5 | -- We just joined - so get the current weather. 6 | TriggerServerEvent( "changeWeather",true ) 7 | TriggerServerEvent( "addWeatherChatSuggests" ) 8 | end) 9 | 10 | RegisterNetEvent("changeWeather") 11 | AddEventHandler("changeWeather", function(newWeather,blackout,startup) 12 | transistioning = false 13 | if newWeather ~= currentWeather then 14 | --Set Weather (if first joining, we do this immediately, else we do it over 1 minute transition) 15 | if startup then 16 | --TraceMsg("StartUp Weather: " ..newWeather.. "\n",true) 17 | --TraceMsg("StartUp Wind Value: "..tostring(ss_wind_speed_Mult[newWeather] + 0.10).. "\n",true) 18 | SetWeatherTypeOverTime(newWeather, 1.00) 19 | else 20 | --TraceMsg("Change Weather: " ..newWeather.. "\n",true) 21 | --TraceMsg("Change Wind Value: " ..tostring(ss_wind_speed_Mult[newWeather] + 0.10).. "\n",true) 22 | SetWeatherTypeOverTime(newWeather, (ss_weather_timer*60/8) + 0.1) 23 | transistioning = true 24 | --TraceMsg("Weather in transistion ["..currentWeather.."]->["..newWeather.."] for "..tostring((ss_weather_timer*60/8) + 0.1).." seconds.",true) 25 | Citizen.Wait(ss_weather_timer*60/8*1000) 26 | end 27 | Citizen.Wait(100) 28 | currentWeather = newWeather 29 | transistioning = false 30 | --TraceMsg("Weather is ending transistion. ["..currentWeather.."]->["..newWeather.."]",true) 31 | end 32 | 33 | if currentWeather == 'XMAS' then 34 | SetForceVehicleTrails(true) 35 | SetForcePedFootstepsTracks(true) 36 | else 37 | SetForceVehicleTrails(false) 38 | SetForcePedFootstepsTracks(false) 39 | end 40 | 41 | --Currently in a blackout? 42 | SetBlackout(blackout) 43 | 44 | --Set Starting Wind 45 | SetWindDirection(32.1) 46 | SetWind(ss_wind_speed_Mult[newWeather] + 0.1 ) 47 | SetWindSpeed(ss_wind_speed_Mult[newWeather] + 0.1) 48 | 49 | end) 50 | 51 | Citizen.CreateThread(function() 52 | while true do 53 | Citizen.Wait(1000) -- one second = 10 second switches 54 | if transistioning == false then 55 | ClearOverrideWeather() 56 | ClearWeatherTypePersist() 57 | SetWeatherTypePersist(currentWeather) 58 | SetWeatherTypeNow(currentWeather) 59 | SetWeatherTypeNowPersist(currentWeather) 60 | end 61 | end 62 | end) 63 | 64 | Citizen.CreateThread(function() 65 | while true do 66 | Citizen.Wait(30000) -- every 30 seconds 67 | if transistioning == false and IsPedInAnyVehicle(GetPlayerPed(-1), false) then 68 | if string.upper(currentWeather) == string.upper("THUNDER") or string.upper(currentWeather) == string.upper("CLEARING") then 69 | local veh = GetVehiclePedIsIn( GetPlayerPed( -1 ) ) 70 | local curDirt = GetVehicleDirtLevel( veh , false) 71 | if curDirt - 1 < 0 then 72 | SetVehicleDirtLevel(veh, 0) 73 | else 74 | SetVehicleDirtLevel(veh, curDirt - 1.0) 75 | end 76 | end 77 | end 78 | end 79 | end) 80 | 81 | 82 | 83 | RegisterNetEvent("addWeatherChatSuggests") 84 | AddEventHandler("addWeatherChatSuggests", function(newWeather,blackout,startup) 85 | TriggerEvent('chat:addSuggestion', '/weather', 'Change the weather.', {{ name="weatherType", help="Available types: extrasunny, clear, neutral, smog, overcast, clouds, clearing, rain, thunder, snow, blizzard, snowlight, xmas"}}) 86 | end) 87 | -------------------------------------------------------------------------------- /ss_cli_windows.lua: -------------------------------------------------------------------------------- 1 | if ss_enable_door_window_sync then 2 | 3 | local vehicleState = { windowsDown = false } 4 | 5 | RegisterNetEvent('VehicleWindow') 6 | AddEventHandler( "VehicleWindow", function( playerID, windowsDown ) 7 | local vehicle = GetVehiclePedIsIn( GetPlayerPed( GetPlayerFromServerId( playerID ) ), false ) 8 | if windowsDown then 9 | RollDownWindow( vehicle, 0 ) 10 | RollDownWindow( vehicle, 1 ) 11 | else 12 | RollUpWindow( vehicle, 0 ) 13 | RollUpWindow( vehicle, 1 ) 14 | end 15 | end) 16 | 17 | Citizen.CreateThread( function() 18 | while true do 19 | Citizen.Wait(10) 20 | if IsPedInAnyVehicle( GetPlayerPed( -1 ), false ) then 21 | local pressedUp = IsControlJustPressed( keybinds.windows.inputGroup, keybinds.windows.up ) or false 22 | local pressedDown = IsControlJustPressed( keybinds.windows.inputGroup, keybinds.windows.down ) or false 23 | if pressedUp or pressedDown then 24 | local vehicle = GetVehiclePedIsIn( GetPlayerPed( -1 ), false ) 25 | if GetPedInVehicleSeat( vehicle, - 1 ) == GetPlayerPed( -1 ) then 26 | if pressedUp then 27 | vehicleState.windowsDown = false 28 | TriggerServerEvent( "ServerSync:SetVehicleWindow", vehicleState.windowsDown ) 29 | end 30 | if pressedDown then 31 | vehicleState.windowsDown = true 32 | TriggerServerEvent( "ServerSync:SetVehicleWindow", vehicleState.windowsDown ) 33 | end 34 | end 35 | end 36 | end 37 | end 38 | end) 39 | 40 | end -------------------------------------------------------------------------------- /ss_shared_functions.lua: -------------------------------------------------------------------------------- 1 | --server 2 | function getTableLength(T) 3 | local count = 0 4 | for _ in pairs(T) do 5 | count = count + 1 6 | end 7 | return count 8 | end 9 | 10 | --server 11 | function getTableKeys(T) 12 | local keys = {} 13 | for k,v in pairs(T) do 14 | table.insert(keys,k) 15 | end 16 | return keys 17 | end 18 | 19 | function TraceMsg(msg,error) 20 | error = error or false 21 | e = "^2[" 22 | if error then e = "^1[" end 23 | Citizen.Trace(e..GetCurrentResourceName().."] "..msg.."\n^7") 24 | end 25 | 26 | function round( n, precision ) 27 | if precision then 28 | return math.floor( (n * 10^precision) + 0.5 ) / (10^precision) 29 | end 30 | return math.floor( n + 0.5 ) 31 | end -------------------------------------------------------------------------------- /ss_srv_indicators.lua: -------------------------------------------------------------------------------- 1 | if ss_enable_turn_signal_sync then 2 | RegisterServerEvent( "ServerSync:SetVehicleIndicator" ) 3 | AddEventHandler( "ServerSync:SetVehicleIndicator", function( dir, state ) 4 | TriggerClientEvent( "VehicleIndicator", -1, source, dir, state ) 5 | end) 6 | end 7 | -------------------------------------------------------------------------------- /ss_srv_time.lua: -------------------------------------------------------------------------------- 1 | local date = os.date('*t') 2 | local secondOfDay = (7 * 3600) + (30 * 60) + 0 3 | local frozen = false 4 | 5 | RegisterServerEvent( "freezeTime" ) 6 | AddEventHandler( "freezeTime", function() 7 | frozen = not frozen 8 | end) 9 | 10 | Citizen.CreateThread(function() 11 | while true do 12 | Citizen.Wait(2000) -- Every Second, we check these idiots via a time sync with clients. 13 | TriggerClientEvent("updateFromServerTime",-1,secondOfDay,date,frozen) 14 | h = math.floor( secondOfDay / 3600 ) 15 | m = math.floor( (secondOfDay - (h * 3600)) / 60 ) 16 | s = secondOfDay - (h * 3600) - (m * 60) 17 | --TraceMsg("CurrentTime: "..h..":"..m..":"..s) 18 | end 19 | end) 20 | 21 | RegisterServerEvent( "addTimeChatSuggests" ) 22 | AddEventHandler( "addTimeChatSuggests", function() 23 | if IsPlayerAceAllowed(source, "changeTime") then 24 | TriggerClientEvent ("addTimeChatSuggests",source) 25 | end 26 | end) 27 | 28 | 29 | Citizen.CreateThread( function() 30 | local timeBuffer = 0.0 31 | local h = 0 32 | local m = 0 33 | local s = 0 34 | while true do 35 | Citizen.Wait(33) -- (int)(GetMillisecondsPerGameMinute() / 60) 36 | date = os.date('*t') -- Update the in-game date data. 37 | if not frozen then 38 | local gameSecond = 33.33 / ss_night_time_speed_mult 39 | if secondOfDay >= 19800 and secondOfDay <= 75600 then 40 | gameSecond = 33.333 / ss_day_time_speed_mult 41 | end 42 | timeBuffer = timeBuffer + round( 33.0 / gameSecond, 4 ) 43 | if timeBuffer >= 1.0 then 44 | local skipSeconds = math.floor( timeBuffer ) 45 | timeBuffer = timeBuffer - skipSeconds 46 | secondOfDay = secondOfDay + skipSeconds 47 | if secondOfDay >= 86400 then 48 | secondOfDay = secondOfDay % 86400 49 | end 50 | end 51 | end 52 | h = math.floor( secondOfDay / 3600 ) 53 | m = math.floor( (secondOfDay - (h * 3600)) / 60 ) 54 | s = secondOfDay - (h * 3600) - (m * 60) 55 | secondOfDay = (h * 3600) + (m * 60) + s 56 | end 57 | end) 58 | 59 | RegisterCommand('time', function(source,args,rawCommand) 60 | 61 | if source == 0 then 62 | if tonumber(args[1]) ~= nil and tonumber(args[2]) ~= nil then 63 | ProcessTimeCommand(args[1],args[2]) 64 | h = math.floor( secondOfDay / 3600 ) 65 | m = math.floor( (secondOfDay - (h * 3600)) / 60 ) 66 | TraceMsg("CONSOLE has changed time to " ..string.format("%02d", h)..":"..string.format("%02d",m)) 67 | else 68 | TraceMsg("Invalid syntax, correct syntax is: time .",true) 69 | end 70 | else 71 | if IsPlayerAceAllowed(source, "changeTime") then 72 | if tonumber(args[1]) ~= nil and tonumber(args[2]) ~= nil then 73 | ProcessTimeCommand(args[1],args[2]) 74 | h = math.floor( secondOfDay / 3600 ) 75 | m = math.floor( (secondOfDay - (h * 3600)) / 60 ) 76 | TraceMsg(GetPlayerName(source).." has changed time to " ..string.format("%02d", h)..":"..string.format("%02d",m)) 77 | else 78 | TraceMsg("Invalid syntax, correct syntax is: time .",true) 79 | end 80 | else 81 | TraceMsg('Access for command /time denied for player: '.. GetPlayerName(source),true) 82 | end 83 | end 84 | end, true) 85 | 86 | RegisterCommand('freezetime', function(source,args,rawCommand) 87 | h = math.floor( secondOfDay / 3600 ) 88 | m = math.floor( (secondOfDay - (h * 3600)) / 60 ) 89 | 90 | if source == 0 then 91 | TriggerEvent("freezeTime") 92 | TraceMsg("CONSOLE has frozen("..tostring(frozen)..") time at " .. string.format("%02d", h) .. ":" .. string.format("%02d", m)) 93 | else 94 | if IsPlayerAceAllowed(source, "freezeTime") then 95 | TriggerEvent("freezeTime") 96 | TraceMsg(GetPlayerName(source).." has frozen("..tostring(frozen)..") time at " .. string.format("%02d", h) .. ":" .. string.format("%02d", m) .. ".") 97 | else 98 | TraceMsg('Access for command /freezetime denied for player: '.. GetPlayerName(source),true) 99 | end 100 | end 101 | end, true) 102 | 103 | 104 | function ProcessTimeCommand(arg1,arg2) 105 | local h = 0 106 | local m = 0 107 | local argh = tonumber(arg1) 108 | local argm = tonumber(arg2) 109 | if argh < 24 and argh ~= nil then 110 | h = argh 111 | else 112 | h = 0 113 | end 114 | if argm < 60 and argm ~= nil then 115 | m = argm 116 | else 117 | m = 0 118 | end 119 | secondOfDay = (tonumber(h)*3600) + (tonumber(m)*60) + 0 120 | end 121 | -------------------------------------------------------------------------------- /ss_srv_weather.lua: -------------------------------------------------------------------------------- 1 | local currentWeather = ss_default_weather 2 | local blackout = false 3 | local weatherTimer = ss_weather_timer * 60 -- 60 Seconds times whatever config minutes are. 4 | local rainTimer = ss_rain_timeout * 60 5 | local rainPossible = false 6 | 7 | RegisterServerEvent( "changeWeather" ) 8 | AddEventHandler( "changeWeather", function(startup) 9 | if startup then 10 | TriggerClientEvent( 'changeWeather',source,currentWeather, blackout, startup ) 11 | else 12 | TriggerClientEvent( 'changeWeather',-1,currentWeather, blackout, startup ) 13 | end 14 | end) 15 | 16 | RegisterServerEvent( "addWeatherChatSuggests" ) 17 | AddEventHandler( "addWeatherChatSuggests", function() 18 | if IsPlayerAceAllowed(source, "changeWeather") then 19 | TriggerClientEvent ("addWeatherChatSuggests",source) 20 | end 21 | end) 22 | 23 | Citizen.CreateThread(function() 24 | TraceMsg("initialized.") 25 | while true do 26 | weatherTimer = weatherTimer - 1 27 | if rainPossible == true then 28 | rainTimer = -1 29 | else 30 | rainTimer = rainTimer - 1 31 | end 32 | Citizen.Wait(1000) -- one second wait time 33 | if weatherTimer == 0 then 34 | if ss_enable_dynamic_weather then 35 | PushNextWeather() 36 | end 37 | weatherTimer = ss_weather_timer * 60 38 | end 39 | 40 | if rainTimer == 0 then 41 | rainPossible = true 42 | end 43 | end 44 | end) 45 | 46 | function PushNextWeather() 47 | -- We need to find the current weather, selection a transistion weather, then push that to the clients via changeWeather 48 | local reduced = false 49 | local reducedW = "" 50 | math.randomseed(GetGameTimer()) 51 | local count = getTableLength(ss_weather_Transition) 52 | local tableKeys = getTableKeys(ss_weather_Transition) 53 | local currentOptions = ss_weather_Transition[currentWeather] 54 | currentWeather = currentOptions[math.random(1,getTableLength(currentOptions))] 55 | 56 | -- Reduce the chance of rainy weather being selected. (You get a free roll to try and get away) 57 | if ss_reduce_rain_chance == true then 58 | for i,wtype in ipairs(currentOptions) do 59 | if wtype == string.upper("THUNDER") or wtype == string.upper("CLEARING") then 60 | currentWeather = currentOptions[math.random(1,getTableLength(currentOptions))] 61 | reduced = true 62 | reducedW = wtype 63 | end 64 | end 65 | end 66 | 67 | if rainPossible == false then 68 | while currentWeather == "THUNDER" or currentWeather == "CLEARING" do 69 | currentWeather = currentOptions[math.random(1,getTableLength(currentOptions))] 70 | end 71 | end 72 | 73 | if string.upper(currentWeather) == string.upper("THUNDER") or string.upper(currentWeather) == string.upper("CLEARING") then 74 | rainTimer = ss_rain_timeout * 60 75 | rainPossible = false 76 | end 77 | 78 | if ss_show_console_output then 79 | TraceMsg("New Weather: "..currentWeather.." (Tried to reduce: "..tostring(reduced).." from "..reducedW..") PossibleRain: ".. tostring(rainPossible) .. " | rainTimer: " .. tostring(rainTimer)) 80 | end 81 | TriggerEvent("changeWeather",false) 82 | end 83 | 84 | RegisterCommand('weather', function(source, args) 85 | if source == 0 then 86 | local validWeatherType = false 87 | if args[1] == nil then 88 | TraceMsg("Invalid /weather syntax, correct syntax is: /weather \nCurrent Weather: "..currentWeather) 89 | return 90 | else 91 | local tableKeys = getTableKeys(ss_weather_Transition) 92 | for i,wtype in ipairs(tableKeys) do 93 | if wtype == string.upper(args[1]) then 94 | validWeatherType = true 95 | end 96 | end 97 | if validWeatherType then 98 | currentWeather = string.upper(args[1]) 99 | TraceMsg("Console updated weather to "..currentWeather) 100 | weatherTimer = ss_weather_timer * 60 101 | TriggerEvent('changeWeather',false) 102 | else 103 | TraceMsg("Invalid weather Type, valid weather types are: \nEXTRASUNNY CLEAR SMOG FOGGY OVERCAST CLOUDS CLEARING\nRAIN THUNDER SNOW BLIZZARD SNOWLIGHT XMAS",true) 104 | end 105 | end 106 | else 107 | if IsPlayerAceAllowed(source, "changeWeather") then 108 | local validWeatherType = false 109 | if args[1] == nil then 110 | TriggerClientEvent('chatMessage', source, '', {255,255,255}, '^1Error: Invalid syntax, use ^0/weather ^1instead!') 111 | TriggerClientEvent('chatMessage', source, '', {255,255,255}, '^7Current Weather: '..currentWeather) 112 | 113 | else 114 | local tableKeys = getTableKeys(ss_weather_Transition) 115 | for i,wtype in ipairs(tableKeys) do 116 | if wtype == string.upper(args[1]) then 117 | validWeatherType = true 118 | end 119 | end 120 | if validWeatherType then 121 | currentWeather = string.upper(args[1]) 122 | weatherTimer = ss_weather_timer * 60 123 | if args[2] == "1" then 124 | TriggerEvent('changeWeather',true) 125 | else 126 | TriggerEvent("changeWeather",false) 127 | TraceMsg(GetPlayerName(source).." has changed weather to "..currentWeather) 128 | end 129 | else 130 | TriggerClientEvent('chatMessage', source, '', {255,255,255}, '^1Error: Invalid weather type, valid weather types are: ^0\nEXTRASUNNY CLEAR NEUTRAL SMOG FOGGY OVERCAST CLOUDS CLEARING\nRAIN THUNDER SNOW BLIZZARD SNOWLIGHT XMAS') 131 | end 132 | end 133 | else 134 | TraceMsg('Access for command /weather denied for player: '.. GetPlayerName(source),true) 135 | end 136 | 137 | end 138 | end, true) -------------------------------------------------------------------------------- /ss_srv_windows.lua: -------------------------------------------------------------------------------- 1 | if ss_enable_door_window_sync then 2 | RegisterServerEvent( "ServerSync:SetVehicleWindow" ) 3 | AddEventHandler( "ServerSync:SetVehicleWindow", function( windowsDown ) 4 | TriggerClientEvent( "VehicleWindow", -1, source, windowsDown ) 5 | end) 6 | end --------------------------------------------------------------------------------