Skip to content

Capitolo 6.3: Sistema Meteo ​


Introduzione ​

DayZ ha un sistema meteo completamente dinamico controllato tramite la classe Weather. Il sistema gestisce nuvolosita, pioggia, nevicata, nebbia, vento e temporali. Il meteo puo essere configurato tramite script (l'API Weather), tramite cfgweather.xml nella cartella della missione, o tramite una macchina a stati meteo scriptata. Questo capitolo copre l'API script per leggere e controllare il meteo programmaticamente.


Accesso all'oggetto Weather ​

c
Weather weather = GetGame().GetWeather();

L'oggetto Weather e un singleton gestito dal motore. E sempre disponibile dopo l'inizializzazione del mondo di gioco.


Fenomeni meteorologici ​

Ogni fenomeno meteorologico (nuvolosita, nebbia, pioggia, nevicata, intensita del vento, direzione del vento) e rappresentato da un oggetto WeatherPhenomenon. Li accedi tramite i metodi getter di Weather.

Ottenere gli oggetti fenomeno ​

c
proto native WeatherPhenomenon GetOvercast();
proto native WeatherPhenomenon GetFog();
proto native WeatherPhenomenon GetRain();
proto native WeatherPhenomenon GetSnowfall();
proto native WeatherPhenomenon GetWindMagnitude();
proto native WeatherPhenomenon GetWindDirection();

API WeatherPhenomenon ​

Ogni fenomeno condivide la stessa interfaccia:

c
class WeatherPhenomenon
{
    // Stato attuale
    proto native float GetActual();          // Valore interpolato attuale (0.0 - 1.0 per la maggior parte)
    proto native float GetForecast();        // Valore obiettivo verso cui si interpola
    proto native float GetNextChange();      // Secondi fino al calcolo della prossima previsione

    // Impostare la previsione (solo server)
    proto native void Set(float forecast, float time = 0, float minDuration = 0);
    // forecast: valore obiettivo
    // time:     secondi per interpolare a quel valore (0 = istantaneo)
    // minDuration: tempo minimo in cui il valore resta prima del cambio automatico

    // Limiti (il valore corrente e sempre mantenuto in [fnMin, fnMax])
    proto native void SetLimits(float fnMin, float fnMax);
    proto void        GetLimits(out float fnMin, out float fnMax);

    // Limiti di tempo della previsione (intervallo di secondi in cui viene calcolata la prossima previsione; predefiniti 300-3600)
    proto native void SetForecastTimeLimits(float ftMin, float ftMax);
    proto void        GetForecastTimeLimits(out float ftMin, out float ftMax);

    // Limiti di cambio della previsione (quanto puo cambiare il valore della previsione a ogni ricalcolo; predefiniti 0-1)
    proto native void SetForecastChangeLimits(float fcMin, float fcMax);
    proto void        GetForecastChangeLimits(out float fcMin, out float fcMax);
}

Esempio --- leggere lo stato meteo attuale:

c
Weather w = GetGame().GetWeather();
float overcast  = w.GetOvercast().GetActual();
float rain      = w.GetRain().GetActual();
float fog       = w.GetFog().GetActual();
float snow      = w.GetSnowfall().GetActual();
float windSpeed = w.GetWindMagnitude().GetActual();
float windDir   = w.GetWindDirection().GetActual();

Print(string.Format("Overcast: %1, Rain: %2, Fog: %3", overcast, rain, fog));

Esempio --- forzare tempo sereno (server):

c
void ForceClearWeather()
{
    Weather w = GetGame().GetWeather();
    w.GetOvercast().Set(0.0, 30, 600);    // Cielo sereno, transizione 30s, mantieni 10 min
    w.GetRain().Set(0.0, 10, 600);        // Nessuna pioggia
    w.GetFog().Set(0.0, 30, 600);         // Nessuna nebbia
    w.GetSnowfall().Set(0.0, 10, 600);    // Nessuna neve
}

Esempio --- creare un temporale:

c
void ForceStorm()
{
    Weather w = GetGame().GetWeather();
    w.GetOvercast().Set(1.0, 60, 1800);   // Nuvolosita totale, rampa 60s, mantieni 30 min
    w.GetRain().Set(0.8, 120, 1800);      // Pioggia intensa
    w.GetFog().Set(0.3, 120, 1800);       // Nebbia leggera
    w.GetWindMagnitude().Set(15.0, 60, 1800);  // Vento forte (m/s)
}

Soglie della pioggia ​

La pioggia e legata ai livelli di nuvolosita. Il motore renderizza la pioggia solo quando la nuvolosita supera una soglia. Puoi configurarlo tramite cfgweather.xml:

xml
<rain>
    <thresholds min="0.5" max="1.0" end="120" />
</rain>
  • min / max: intervallo di nuvolosita in cui la pioggia e consentita
  • end: secondi prima che la pioggia si fermi se la nuvolosita scende sotto la soglia

Nello script, la pioggia non apparira visivamente se la nuvolosita e troppo bassa, anche se GetRain().GetActual() restituisce un valore diverso da zero.


Vento ​

Il vento usa due fenomeni: magnitudine (velocita in m/s) e direzione (angolo in radianti).

Vettore del vento ​

c
proto native vector GetWind();           // Vettore direzione del vento (spazio mondo)
proto native float  GetWindSpeed();      // Velocita del vento in m/s

Esempio --- ottenere informazioni sul vento:

c
Weather w = GetGame().GetWeather();
vector windVec = w.GetWind();
float windSpd = w.GetWindSpeed();
Print(string.Format("Wind: %1 m/s, direction: %2", windSpd, windVec));

Temporali (fulmini) ​

c
proto native void SetStorm(float density, float threshold, float timeout);
ParametroDescrizione
densityDensita dei fulmini (0.0 - 1.0)
thresholdLivello minimo di nuvolosita per la comparsa dei fulmini (0.0 - 1.0)
timeoutSecondi tra i fulmini

Esempio --- abilitare fulmini frequenti:

c
GetGame().GetWeather().SetStorm(1.0, 0.6, 10);
// Densita massima, si attiva al 60% di nuvolosita, fulmine ogni 10 secondi

Controllo MissionWeather ​

Per prendere il controllo manuale del meteo (disabilitando la macchina a stati meteo automatica), chiama:

c
void MissionWeather(bool use);

Quando viene chiamato MissionWeather(true), il motore ferma le transizioni meteo automatiche e solo le tue chiamate Set() guidate dallo script controllano il meteo.

Esempio --- controllo manuale completo in init.c:

c
void main()
{
    // Prendere il controllo manuale del meteo
    GetGame().GetWeather().MissionWeather(true);

    // Impostare il meteo desiderato
    GetGame().GetWeather().GetOvercast().Set(0.3, 0, 0);
    GetGame().GetWeather().GetRain().Set(0.0, 0, 0);
    GetGame().GetWeather().GetFog().Set(0.1, 0, 0);
}

Data e ora ​

La data e l'ora del gioco influenzano l'illuminazione, la posizione del sole e il ciclo giorno/notte. Questi sono controllati tramite l'oggetto World, non Weather, ma sono strettamente correlati.

Ottenere data/ora attuale ​

c
int year, month, day, hour, minute;
GetGame().GetWorld().GetDate(year, month, day, hour, minute);

Impostare data/ora (solo server) ​

c
proto native void SetDate(int year, int month, int day, int hour, int minute);

Esempio --- impostare l'ora a mezzogiorno:

c
int year, month, day, hour, minute;
GetGame().GetWorld().GetDate(year, month, day, hour, minute);
GetGame().GetWorld().SetDate(year, month, day, 12, 0);

Accelerazione del tempo ​

L'accelerazione del tempo e configurata in serverDZ.cfg tramite:

serverTimeAcceleration = 12;      // 12x tempo reale
serverNightTimeAcceleration = 4;  // Accelerazione 4x durante la notte

Nello script, puoi cambiare l'accelerazione del tempo a runtime (principalmente per il debug) con GetGame().GetWorld().SetTimeMultiplier(float timeMultiplier), dove timeMultiplier e un valore di accelerazione 0-64 (oppure -1 per ripristinare il valore della config). Non esiste un getter di script per il moltiplicatore corrente.


Macchina a stati meteo WorldData ​

Il DayZ vanilla usa una macchina a stati meteo scriptata nelle classi WorldData (es. ChernarusPlusData, EnochData, SakhalData). Il punto di override chiave e:

c
class WorldData
{
    bool WeatherOnBeforeChange(EWeatherPhenomenon type, float actual, float change,
                                float time);
}

Sovrascrivi questo metodo in una classe modded WorldData per intercettare e modificare le transizioni meteo:

c
modded class ChernarusPlusData
{
    // Restituisci true quando lo script modifica lo stato del fenomeno;
    // restituisci false per lasciare che il motore applichi il cambio calcolato.
    override bool WeatherOnBeforeChange(EWeatherPhenomenon type, float actual,
                                         float change, float time)
    {
        // Impedire alla pioggia di superare 0.5
        if (type == EWeatherPhenomenon.RAIN && change > 0.5)
        {
            GetGame().GetWeather().GetRain().Set(0.5, time, 300);
            return true;
        }

        return super.WeatherOnBeforeChange(type, actual, change, time);
    }
}

cfgweather.xml ​

Il file cfgweather.xml nella cartella della missione fornisce un modo dichiarativo per configurare il meteo senza scripting. Quando presente, sovrascrive i parametri predefiniti della macchina a stati meteo.

Struttura principale:

xml
<weather reset="0" enable="1">
    <overcast>
        <current actual="0.45" time="120" duration="240" />
        <limits min="0.0" max="1.0" />
        <timelimits min="900" max="1800" />
        <changelimits min="0.0" max="1.0" />
    </overcast>
    <fog>...</fog>
    <rain>
        ...
        <thresholds min="0.5" max="1.0" end="120" />
    </rain>
    <snowfall>...</snowfall>
    <windMagnitude>...</windMagnitude>
    <windDirection>...</windDirection>
    <storm density="1.0" threshold="0.7" timeout="25"/>
</weather>
AttributoDescrizione
resetSe resettare il meteo dalla memorizzazione all'avvio del server
enableSe questo file e attivo
actualValore iniziale
timeSecondi per raggiungere il valore iniziale
durationSecondi in cui il valore iniziale viene mantenuto
limits min/maxIntervallo per il valore del fenomeno
timelimits min/maxIntervallo per la durata della transizione (secondi)
changelimits min/maxIntervallo per la magnitudine del cambio per transizione

ConcettoPunto chiave
AccessoGetGame().GetWeather() restituisce il singleton Weather
FenomeniGetOvercast(), GetRain(), GetFog(), GetSnowfall(), GetWindMagnitude(), GetWindDirection()
Letturaphenomenon.GetActual() per il valore corrente (0.0 - 1.0)
Scritturaphenomenon.Set(previsione, tempoTransizione, durataMantenimento) (solo server)
TemporaliSetStorm(densita, soglia, timeout)
Modalita manualeMissionWeather(true) disabilita i cambiamenti meteo automatici
Data/OraGetGame().GetWorld().GetDate() / SetDate()
File di configurazionecfgweather.xml nella cartella missione per setup dichiarativo

Buone pratiche ​

  • Chiama MissionWeather(true) prima di impostare il meteo in init.c. Senza questo, la macchina a stati meteo automatica sovrascrivera le tue chiamate Set() entro pochi secondi. Prendi sempre il controllo manuale se vuoi un meteo deterministico.
  • Fornisci sempre un parametro minDuration in Set(). Impostare minDuration a 0 significa che il sistema meteo puo immediatamente allontanarsi dal tuo valore. Usa almeno 300-600 secondi per mantenere lo stato desiderato.
  • Imposta la nuvolosita prima della pioggia. La pioggia e visivamente legata alle soglie di nuvolosita. Se la nuvolosita e sotto la soglia configurata in cfgweather.xml, la pioggia non sara renderizzata anche se GetRain().GetActual() restituisce un valore diverso da zero.
  • Usa WeatherOnBeforeChange() per la politica meteo a livello di server. Sovrascrivilo in una modded class ChernarusPlusData (o la sottoclasse WorldData appropriata) per limitare o reindirizzare le transizioni meteo senza combattere la macchina a stati.
  • Leggi il meteo su entrambi i lati, scrivi solo sul server. GetActual() e GetForecast() funzionano su client e server, ma Set() ha effetto solo sul server.

Compatibilita e impatto ​

Compatibilita mod: I mod meteo comunemente sovrascrivono WeatherOnBeforeChange() nelle sottoclassi WorldData. Solo la catena di override di un mod viene eseguita per la classe WorldData di ogni mappa.

  • Ordine di caricamento: Piu mod che sovrascrivono WeatherOnBeforeChange sulla stessa sottoclasse WorldData (es. ChernarusPlusData) devono tutti chiamare super, altrimenti i mod precedenti perdono la loro logica meteo.
  • Conflitti di classi moddate: Se un mod chiama MissionWeather(true) e un altro si aspetta il meteo automatico, sono fondamentalmente incompatibili. Documenta se il tuo mod prende il controllo manuale del meteo.
  • Impatto sulle prestazioni: Le chiamate all'API meteo sono leggere. L'interpolazione dei fenomeni viene eseguita nel motore, non nello script. Chiamate Set() frequenti (ogni frame) sono dispendiose ma non dannose.
  • Server/Client: Tutte le chiamate Set() sono solo server. I client ricevono lo stato meteo tramite la sincronizzazione automatica del motore. Le chiamate Set() lato client vengono silenziosamente ignorate.

Pattern osservati nei mod reali ​

Questi pattern sono stati confermati studiando il codice sorgente di mod DayZ professionali.

PatternModFile/Posizione
MissionWeather(true) + ciclo meteo scriptato con CallLaterExpansionController meteo nell'init della missione
Override WeatherOnBeforeChange per prevenire pioggia in aree specificheCOT Weather ModuleChernarusPlusData moddata
Comando admin per forzare sereno/temporale tramite Set() con lunga durata di mantenimentoVPP Admin ToolsPannello admin meteo
cfgweather.xml con soglie personalizzate per mappe solo neveNamalskConfig cartella missione

<< Precedente: Veicoli | Meteo | Successivo: Telecamere >>

Released under CC BY-SA 4.0 | Code examples under MIT License