Skip to content

Rozdział 6.3: System pogody ​


Wprowadzenie ​

DayZ posiada w pełni dynamiczny system pogody kontrolowany przez klasę Weather. System zarządza zachmurzeniem, deszczem, opadami śniegu, mgłą, wiatrem i burzami. Pogodę można konfigurować przez skrypt (Weather API), przez cfgweather.xml w folderze misji lub przez skryptową maszynę stanów pogody. Ten rozdział obejmuje skryptowe API do odczytu i programowego sterowania pogodą.


Dostęp do obiektu Weather ​

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

Obiekt Weather jest singletonem zarządzanym przez silnik. Jest zawsze dostępny po inicjalizacji świata gry.


Zjawiska pogodowe ​

Każde zjawisko pogodowe (zachmurzenie, mgła, deszcz, opady śniegu, siła wiatru, kierunek wiatru) jest reprezentowane przez obiekt WeatherPhenomenon. Dostęp do nich odbywa się przez metody getter na Weather.

Pobieranie obiektów zjawisk ​

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 ​

Każde zjawisko współdzieli to samo interfejs:

c
class WeatherPhenomenon
{
    // Aktualny stan
    proto native float GetActual();          // Aktualna interpolowana wartość (0.0 - 1.0 dla większości)
    proto native float GetForecast();        // Docelowa wartość do interpolacji
    proto native float GetNextChange();      // Sekundy do obliczenia następnej prognozy

    // Ustaw prognozę (tylko serwer)
    proto native void Set(float forecast, float time = 0, float minDuration = 0);
    // forecast: wartość docelowa
    // time:     sekundy do interpolacji do tej wartości (0 = natychmiast)
    // minDuration: minimalny czas utrzymywania wartości przed automatyczną zmianą

    // Limity (aktualna wartość jest zawsze utrzymywana w [fnMin, fnMax])
    proto native void SetLimits(float fnMin, float fnMax);
    proto void        GetLimits(out float fnMin, out float fnMax);

    // Limity czasu prognozy (zakres sekund, w którym obliczana jest następna prognoza; domyślnie 300-3600)
    proto native void SetForecastTimeLimits(float ftMin, float ftMax);
    proto void        GetForecastTimeLimits(out float ftMin, out float ftMax);

    // Limity zmiany prognozy (o ile wartość prognozy może się zmienić przy każdym przeliczeniu; domyślnie 0-1)
    proto native void SetForecastChangeLimits(float fcMin, float fcMax);
    proto void        GetForecastChangeLimits(out float fcMin, out float fcMax);
}

Przykład --- odczyt aktualnego stanu pogody:

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));

Przykład --- wymuś czystą pogodę (serwer):

c
void ForceClearWeather()
{
    Weather w = GetGame().GetWeather();
    w.GetOvercast().Set(0.0, 30, 600);    // Czyste niebo, 30s przejście, utrzymaj 10 min
    w.GetRain().Set(0.0, 10, 600);        // Bez deszczu
    w.GetFog().Set(0.0, 30, 600);         // Bez mgły
    w.GetSnowfall().Set(0.0, 10, 600);    // Bez śniegu
}

Przykład --- stwórz burzę:

c
void ForceStorm()
{
    Weather w = GetGame().GetWeather();
    w.GetOvercast().Set(1.0, 60, 1800);   // Pełne zachmurzenie, 60s narastanie, utrzymaj 30 min
    w.GetRain().Set(0.8, 120, 1800);      // Silny deszcz
    w.GetFog().Set(0.3, 120, 1800);       // Lekka mgła
    w.GetWindMagnitude().Set(15.0, 60, 1800);  // Silny wiatr (m/s)
}

Progi deszczu ​

Deszcz jest powiązany z poziomem zachmurzenia. Silnik renderuje deszcz tylko gdy zachmurzenie przekracza próg. Możesz to skonfigurować przez cfgweather.xml:

xml
<rain>
    <thresholds min="0.5" max="1.0" end="120" />
</rain>
  • min / max: zakres zachmurzenia, w którym deszcz jest dozwolony
  • end: sekundy na zatrzymanie deszczu jeśli zachmurzenie spadnie poniżej progu

W skrypcie deszcz nie pojawi się wizualnie jeśli zachmurzenie jest zbyt niskie, nawet jeśli GetRain().GetActual() zwraca niezerową wartość.


Wiatr ​

Wiatr używa dwóch zjawisk: siły (prędkość w m/s) i kierunku (kąt w radianach).

Wektor wiatru ​

c
proto native vector GetWind();           // Wektor kierunku wiatru (przestrzeń świata)
proto native float  GetWindSpeed();      // Prędkość wiatru w m/s

Przykład --- pobranie informacji o wietrze:

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

Burze (błyskawice) ​

c
proto native void SetStorm(float density, float threshold, float timeout);
ParametrOpis
densityGęstość błyskawic (0.0 - 1.0)
thresholdMinimalny poziom zachmurzenia dla pojawienia się błyskawic (0.0 - 1.0)
timeoutSekundy między uderzeniami piorunów

Przykład --- włącz częste błyskawice:

c
GetGame().GetWeather().SetStorm(1.0, 0.6, 10);
// Pełna gęstość, wyzwala się przy 60% zachmurzenia, uderzenia co 10 sekund

Kontrola MissionWeather ​

Aby przejąć ręczną kontrolę nad pogodą (wyłączając automatyczną maszynę stanów pogody), wywołaj:

c
void MissionWeather(bool use);

Gdy wywołane jest MissionWeather(true), silnik zatrzymuje automatyczne przejścia pogodowe i tylko twoje skryptowe wywołania Set() kontrolują pogodę.

Przykład --- pełna ręczna kontrola w init.c:

c
void main()
{
    // Przejmij ręczną kontrolę nad pogodą
    GetGame().GetWeather().MissionWeather(true);

    // Ustaw pożądaną pogodę
    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 i czas ​

Data i czas gry wpływają na oświetlenie, pozycję słońca i cykl dzień/noc. Są one kontrolowane przez obiekt World, nie Weather, ale są ściśle powiązane.

Pobieranie aktualnej daty/czasu ​

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

Ustawianie daty/czasu (tylko serwer) ​

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

Przykład --- ustawienie czasu na południe:

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

Przyspieszenie czasu ​

Przyspieszenie czasu jest konfigurowane w serverDZ.cfg przez:

serverTimeAcceleration = 12;      // 12x czas rzeczywisty
serverNightTimeAcceleration = 4;  // 4x przyspieszenie w nocy

W skrypcie możesz zmienić przyspieszenie czasu w trakcie działania (głównie do debugowania) za pomocą GetGame().GetWorld().SetTimeMultiplier(float timeMultiplier), gdzie timeMultiplier to wartość przyspieszenia 0-64 (lub -1, aby przywrócić wartość z konfiguracji). Nie ma skryptowego gettera dla aktualnego mnożnika.


Maszyna stanów pogody WorldData ​

Vanilla DayZ używa skryptowanej maszyny stanów pogody w klasach WorldData (np. ChernarusPlusData, EnochData, SakhalData). Kluczowy punkt nadpisania to:

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

Nadpisz tę metodę w klasie modded WorldData, aby przechwytywać i modyfikować przejścia pogodowe:

c
modded class ChernarusPlusData
{
    // Zwróć true, gdy skrypt modyfikuje stan zjawiska;
    // zwróć false, aby silnik zastosował swoją obliczoną zmianę.
    override bool WeatherOnBeforeChange(EWeatherPhenomenon type, float actual,
                                         float change, float time)
    {
        // Zapobiegaj przekroczeniu 0.5 przez deszcz
        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 ​

Plik cfgweather.xml w folderze misji zapewnia deklaratywny sposób konfiguracji pogody bez skryptowania. Gdy jest obecny, nadpisuje domyślne parametry maszyny stanów pogody.

Kluczowa struktura:

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>
AtrybutOpis
resetCzy resetować pogodę z pamięci przy starcie serwera
enableCzy ten plik jest aktywny
actualWartość początkowa
timeSekundy do osiągnięcia wartości początkowej
durationSekundy utrzymywania wartości początkowej
limits min/maxZakres wartości zjawiska
timelimits min/maxZakres czasu trwania przejścia (sekundy)
changelimits min/maxZakres wielkości zmiany na przejście

Podsumowanie ​

KonceptKluczowy punkt
DostępGetGame().GetWeather() zwraca singleton Weather
ZjawiskaGetOvercast(), GetRain(), GetFog(), GetSnowfall(), GetWindMagnitude(), GetWindDirection()
Odczytphenomenon.GetActual() dla aktualnej wartości (0.0 - 1.0)
Zapisphenomenon.Set(prognoza, czasPrzejścia, czasUtrzymania) (tylko serwer)
BurzeSetStorm(gęstość, próg, limit_czasu)
Tryb ręcznyMissionWeather(true) wyłącza automatyczne zmiany pogody
Data/CzasGetGame().GetWorld().GetDate() / SetDate()
Plik konfiguracjicfgweather.xml w folderze misji dla deklaratywnej konfiguracji

Dobre praktyki ​

  • Wywołaj MissionWeather(true) przed ustawianiem pogody w init.c. Bez tego automatyczna maszyna stanów pogody nadpisze twoje wywołania Set() w ciągu sekund. Zawsze najpierw przejmij ręczną kontrolę, jeśli chcesz deterministyczną pogodę.
  • Zawsze podawaj parametr minDuration w Set(). Ustawienie minDuration na 0 oznacza, że system pogody może natychmiast przejść od twojej wartości. Użyj co najmniej 300-600 sekund, aby utrzymać pożądany stan.
  • Ustaw zachmurzenie przed deszczem. Deszcz jest wizualnie powiązany z progami zachmurzenia. Jeśli zachmurzenie jest poniżej progu skonfigurowanego w cfgweather.xml, deszcz nie będzie renderowany, nawet jeśli GetRain().GetActual() zwraca niezerową wartość.
  • Używaj WeatherOnBeforeChange() dla ogólnoserwerowej polityki pogodowej. Nadpisz to w modded class ChernarusPlusData (lub odpowiedniej podklasie WorldData), aby ograniczać lub przekierowywać przejścia pogodowe bez walki z maszyną stanów.
  • Odczytuj pogodę po obu stronach, zapisuj tylko na serwerze. GetActual() i GetForecast() działają na kliencie i serwerze, ale Set() działa tylko na serwerze.

Kompatybilność i wpływ ​

Kompatybilność modów: Mody pogodowe powszechnie nadpisują WeatherOnBeforeChange() w podklasach WorldData. Tylko jeden łańcuch nadpisań jednego moda działa dla klasy WorldData każdej mapy.

  • Kolejność ładowania: Jeśli wiele modów nadpisuje WeatherOnBeforeChange na tej samej podklasie WorldData (np. ChernarusPlusData), wszystkie muszą wywoływać super, w przeciwnym razie wcześniejsze mody tracą swoją logikę pogodową.
  • Konflikty modded klas: Jeśli jeden mod wywołuje MissionWeather(true), a inny oczekuje automatycznej pogody, są fundamentalnie niekompatybilne. Dokumentuj, czy twój mod przejmuje ręczną kontrolę nad pogodą.
  • Wpływ na wydajność: Wywołania Weather API są lekkie. Interpolacja zjawisk działa w silniku, nie w skrypcie. Częste wywołania Set() (co klatkę) są marnotrawstwem, ale nie są szkodliwe.
  • Serwer/Klient: Wszystkie wywołania Set() działają tylko na serwerze. Klienci otrzymują stan pogody przez automatyczną synchronizację silnika. Wywołania Set() po stronie klienta są po cichu ignorowane.

Zaobserwowane w prawdziwych modach ​

Te wzorce zostały potwierdzone przez analizę kodu źródłowego profesjonalnych modów DayZ.

WzorzecModPlik/Lokalizacja
MissionWeather(true) + skryptowany cykl pogodowy z CallLaterExpansionKontroler pogody w inicjalizacji misji
Nadpisanie WeatherOnBeforeChange aby zapobiec deszczowi w określonych obszarachCOT Weather ModuleModded ChernarusPlusData
Komenda admina do wymuszenia pogody czystej/burzowej przez Set() z długim czasem utrzymaniaVPP Admin ToolsPanel administracji pogodą
cfgweather.xml z niestandardowymi progami dla map tylko ze śniegiemNamalskKonfiguracja w folderze misji

<< Poprzedni: Pojazdy | Pogoda | Następny: Kamery >>

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