How Integrations Work#
Weather and time do not depend on any framework: zones, cycles, the clock and every effect run the same on ESX, QBCore, Qbox or nothing at all. The framework only answers who is this player and which group are they in, through one small adapter file per framework. Everything else is detected at start and steps aside when missing.
Layer | Supported | Without it |
|---|---|---|
Framework |
| Runs standalone. Everything works; panel access is decided by ACE alone. |
Permissions | ACE on every framework, plus the | — |
Notifications |
| ox_lib, which is a dependency anyway. The game's own feed as a last resort. |
HUD |
| The HUD stays on screen while a panel is open. |
Phone |
| Emergency alerts are shown on screen only. |
3D prompts |
| Drawn with the game's own text and a backing box. |
Weather scripts | Stands in for | |
Database |
| Required. The only one. |
Every optional integration degrades silently. A missing resource makes its part stand down, not throw. The console line
framework resolvedat start is the quickest way to see what was picked.
Frameworks#
The framework is detected in config/config.lua from the resources already running when Zone Weather starts:
local frameworks = {
['es_extended'] = 'esx',
['qb-core'] = 'qb',
['qbx_core'] = 'qb',
}
Config.Framework = DependencyCheck(frameworks) or 'standalone'Qbox uses the QBCore adapter. To skip detection — two frameworks installed, or one renamed on your server — set the value by hand after that line:
Config.Framework = 'esx' -- 'esx' · 'qb' · 'standalone' · or your own adapter's nameAdding a framework#
Each adapter is a pair of small, unencrypted files under custom/<name>/. Supporting another framework is one folder plus two lines:
Copy the closest adapter
Copy
custom/esx/(orcustom/standalone/for the bare minimum) tocustom/myframework/.Fill in the functions
Each file returns a table of functions that call your framework:
lua -- custom/myframework/client.lua framework:getObject() -- the core object framework:getPlayerData() -- the local player's data table framework:getIdentifier() -- their identifier framework:isLoaded() -- true once the character is in framework:onPlayerLoaded(cb) -- call cb when the character loads -- custom/myframework/server.lua framework:getObject() framework:isReady() framework:getPlayerFromId(src) framework:getIdentifier(src) framework:getName(src) framework:getGroup(src) -- the admin group, or nil to rely on ACERegister it
Add the client file to the
fileslist infxmanifest.lua, next to the existing adapters, so clients can load it — then pointConfig.Frameworkat it, or add its resource to the detection table above:lua -- fxmanifest.lua, inside files { ... } 'custom/myframework/client.lua', -- config/config.lua ['my_core'] = 'myframework',
If an adapter fails to load, the console says which file and why, and the resource carries on standalone.
Permissions#
Each panel checks its own ACE node: command.weather, command.weatherconfig and command.weathercreator. With a framework running, the player's framework group is checked first — admin and superadmin on ESX — and ACE is the fallback for everyone else; standalone uses ACE only. The check runs on the server for every action, not just when a panel opens.
Notifications and the HUD#
Notifications#
Every message the resource shows — a weather applied, a zone saved, an emergency alert — goes through one function, Notification in custom/client.lua. It uses qs-interface when it is running, then ox_lib, then the game's feed. To use another notification resource, change that one function:
-- custom/client.lua
-- type: 'info' · 'success' · 'warning' · 'error'
-- duration: milliseconds, set for long messages such as emergency alerts
function Notification(msg, type, duration)
exports['my_notify']:Show(msg, type, duration or 5000)
endThe title shown on them is Notification title in Settings → General.
Hiding the HUD#
While any panel is open the player's HUD is hidden, and it comes back when the last one closes. qs-interface is wired in; add any other HUD to the table in client/custom/hud.lua:
QSW.HudResources = {
['qs-interface'] = function(visible)
exports['qs-interface']:ToggleHud(visible)
end,
['my-hud'] = function(visible)
exports['my-hud']:SetVisible(visible)
end,
}Only resources that are started are called, so listing a HUD you do not run is harmless.
qs-smartphone#
With qs-smartphone running, an emergency alert is also sent as a long notification to the phone of every player it covers — everyone in the zone, or everyone for a tsunami. It carries the disaster in the title, the zone underneath and the full instructions with the countdown, and stays in the phone's notification centre if the phone was closed.
It arrives as the app Emergency Alert, in the server's language. Players can mute it from the phone's settings like any other app.
A player with no active phone simply does not receive it.
Switch it off with Phone notification in Settings → Emergency alerts.
State Bags#
With Publish state bags on (the default), weather and time are mirrored into state bags, so any resource can read them without calling an export:
State bag | Holds |
|---|---|
| The weather running in that zone. |
|
|
| Whether the blackout is on. |
| On each client: the zone the player stands in. |
| On each client: the weather that player is under. |
-- any client script
if GlobalState.weatherBlackout then
-- the power is out
end
local clock = GlobalState.weatherTime
if clock and clock.hour >= 22 then
-- night
endThe two LocalPlayer values stay on that player's own machine; the server does not see them.
Languages#
41 translations ship in locales/, covering the panels, the notifications and the emergency alerts. Pick one in Settings → General → Language; it switches for every player as soon as you save.
ar · bg · bn · ca · cs · da · de · el · en · es · et · fa · fi · fr · he · hi · hr · hu · id · it · ja · ko · lt · lv · ms · nl · no · pl · pt · ro · ru · sk · sl · sv · sw · th · tr · uk · ur · vi · zh
To change a text — the wording of an alert, a weather's name — edit it in that language's file and restart the resource. Anything missing from a translation falls back to English.



