From 9ed3fc1f95fe28741686280b1ae7da3b9f9ca403 Mon Sep 17 00:00:00 2001 From: Jesusaves Date: Wed, 14 Apr 2021 21:56:42 -0300 Subject: Rewrite weather code for its greatest challenge: Kaflosh --- db/constants.conf | 8 +-- npc/functions/weather.txt | 121 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 99 insertions(+), 30 deletions(-) diff --git a/db/constants.conf b/db/constants.conf index 97572495..c9e500ee 100644 --- a/db/constants.conf +++ b/db/constants.conf @@ -4082,15 +4082,15 @@ more than one separator can be used in a row (so 12_3___456 is illegal). comment__: "map masks" MASK_NONE: 1 - MASK_MATTACK: 2 - MASK_EVILSANCTUM: 4 + MASK_UNUSED1: 2 + MASK_UNUSED2: 4 MASK_NIGHT: 8 MASK_RAIN: 16 MASK_SANDSTORM: 32 MASK_SNOW: 64 MASK_CHRISTMAS: 128 - MASK_AUTUMN: 256 - MASK_UNUSED: 512 + MASK_UNUSED3: 256 + MASK_UNUSED4: 512 MASK_SPECIAL: 1024 // Usually a warning sign MASK_SPECIAL2: 2048 MASK_SPECIAL3: 4096 diff --git a/npc/functions/weather.txt b/npc/functions/weather.txt index 3cf872c8..1d384a04 100644 --- a/npc/functions/weather.txt +++ b/npc/functions/weather.txt @@ -24,6 +24,7 @@ OnInit: // Determine which maps are subject to weather, and how weather works: // eg. it should never snow on a desert, or happen a sandstorm on icelands. .wcore = htnew; + .wtime = htnew; // Deserts htput(.wcore, "001-1", CLIMATE_DESERT); @@ -75,8 +76,43 @@ OnInit: debugmes("[Weather.sys] Total Maps = " + htsize(.wcore)); + initnpctimer; end; + /////////////////////////////////////////////////////////////////// + // Internal functions to check or change stuff + // WeatherSwitch ( MASK ) + function WeatherSwitch { + // Get map + .@key$=getmap(); + + // Sanitize + .@m = htget(.wcore, .@key$, CLIMATE_NONE); + + // Change Weather or abort + if (.@m == CLIMATE_NONE) + dispbottom l("Command not permitted on this map! Check npc/functions/weather.conf"); + else + addmapmask(.@key$, getarg(0)); + return; + } + + // WeatherClear ( MAP ) + function WeatherClear { + .@key$ = getarg(0); + .@mk=getmapmask(.@key$); + if (.@mk & MASK_NIGHT) + .@mk=.@mk^MASK_NIGHT; + if (.@mk & MASK_RAIN) + .@mk=.@mk^MASK_RAIN; + if (.@mk & MASK_SANDSTORM) + .@mk=.@mk^MASK_SANDSTORM; + if (.@mk & MASK_SNOW) + .@mk=.@mk^MASK_SNOW; + setmapmask(.@key$, .@mk); + return; + } + /////////////////////////////////////////////////////////////////// // "#WeatherCore"::climate(mapid) public function climate { @@ -91,25 +127,68 @@ OnInit: return getmapmask(.@m$) & .@mk; } + // "#WeatherCore"::weather_override(weather, duration{, mapid, override=false}) + public function weather_override { + .@mk=getarg(0); + .@tm=getarg(1); + .@m$=getarg(2, getmapname()); + .@force=getarg(3, false); + + if (!.@force) { + // Obtain map climate & validate + .@cl = htget(.wcore, .@m$, CLIMATE_NONE); + if (.@cl == CLIMATE_NONE) + return false; + + // Forbidden changes (Disallowed by climate) + if (.@cl == CLIMATE_DESERT && (.@mk == MASK_SNOW)) + return false; + if (.@cl == CLIMATE_ICELAND && (.@mk == MASK_SANDSTORM)) + return false; + } + + // Rain is not granted in desert or iceland + // But "#WeatherCore"::climate() will have this handled + // So we assume it is OK here and apply the changes + + // Maybe there's already a timer running? + .@t = htget(.wtime, .@m$, 0); + if (.@t <= 0) { + addmapmask(.@m$, .@mk); + htput(.wtime, .@m$, .@tm); + } else { + htput(.wtime, .@m$, .@t+.@tm); + } + return true; + } /////////////////////////////////////////////////////////////////// - // Function to check stuff - // WeatherSwitch ( MASK, MAP ) - function WeatherSwitch { - // Get map - getmapxy(.@key$,.@a,.@b,0); - - // Sanitize - .@m$ = htget(.wcore, .@key$, "Not found"); - - // Change Weather or abort - if (.@m$ == "Not found") - dispbottom l("Command not permitted on this map! Check npc/functions/weather.conf"); - else - addmapmask(.@key$, getarg(0)); - return; + // Every 5 seconds, we clean up any ongoing weather effects +OnTimer5000: + // No weather effect + if (!htsize(.wtime)) { + initnpctimer; + end; + } + // We got a job to do + .@hti = htiterator(.wtime); + .@cur = gettimetick(2); + for (.@key$ = htinextkey(.@hti); hticheck(.@hti); .@key$ = htinextkey(.@hti)) + { + .@target=htget(.wtime, .@key$, 0); + debugmes "Map %s (Time %d/%d)", .@key$, .@target, .@cur; + // Not yet expired + if (.@target > .@cur) + continue; + // Remove the effect + htput(.wtime, .@key$, 0); + WeatherClear(.@key$); } + htidelete(.@hti); + initnpctimer; + end; +/////////////////////////////////////////////////////////////////// // Some commands, for GMs manually override weather OnRain: WeatherSwitch(MASK_RAIN); @@ -153,17 +232,7 @@ OnManual: // Clear works on any map OnClear: - getmapxy(.@key$,.@a,.@b,0); - .@mk=getmapmask(.@key$); - if (.@mk & MASK_RAIN) - .@mk=.@mk^MASK_RAIN; - if (.@mk & MASK_SANDSTORM) - .@mk=.@mk^MASK_SANDSTORM; - if (.@mk & MASK_SNOW) - .@mk=.@mk^MASK_SNOW; - if (.@mk & MASK_NIGHT) - .@mk=.@mk^MASK_NIGHT; - setmapmask(.@key$, .@mk); + WeatherClear(getmap()); end; // Reset the whole map, including season, event and weather masks -- cgit v1.2.3-60-g2f50