I have added this comment to the Vault download for my weather system:-
KNOWN ISSUE: LIGHTNING: There is a known NWN2 "Light" issue where Light objects lose their tags between module loads. Therefore, builders should add checks to determine if the "Lightning" object is actually present if they are using the system with more than one module. (I have NOT yet added this fix to the current download, but make builders aware of the issue to sort themselves.) Storing the "Lightning object" as a local object on the PC's current area and recalling it as required does work! If anybody needs this in more detail, then I can update if need be.
Therefore, if you do use this system, please make the required changes if you wish to avoid duplication of the lightning object. I have copied a "fixed" version of the include file below, showing where the fixes have been applied. Two lines have been removed (REMMED BELOW) and three lines have been added. (Emboldened.)
DO NOT FORGET TO RECOMPILE ANY SCRIPTS THAT CALL THIS INCLUDE IF USED
Many Thanks,
Lance
/* WEATHER SYSTEM FOR THE ALTHEA CAMPAIGN BY LANCE BOTELLE
RAINS INCLUDED (AUTOMATIC SWITCHING - OR MANUAL OVERRIDE USING GLOBAL VARIABLE IN "SETWEATHER"):
------------------------------------------------------------------------------------------------
PRECIPITATION SETTINGS: 0 = OFF (SUNNY), 1 = WEAK, 2 = LIGHT, 3 = MEDIUM, 4 = HEAVY, 5 = STORMY
6 = LIGHT SNOW, 7 = HEAVY SNOW, 8 = BLIZZARD, 9 = LIGHT DUST STORM, 10 = MEDIUM DUST STORM, 11 = HEAVY DUST STORM.
If you set a global value to force a weather condition, do not forget to set any other value (< 0 or > 11)
to reset to a random weather effect after you have finished forcing the weather condition.
0 NO PRECIPITATION - SUNNY! On first setup, the global value is set to -1 to make weather variable. (*)
1 AND 2 ARE LIGHT RAIN - PLAY LIGHT RAIN (NO THUNDER AND NO LIGHTNING)
3 AND 4 ARE HEAVY RAIN - PLAY HEAVY RAIN AND DISTANT THUNDER (4 HAS 50% CHANCE LOCAL LIGHTNING/THUNDER)
5 IS STORM RAIN - PLAYS HEAVY STORM, DISTANT THUNDER AND LOCAL LIGHTNING/THUNDER
6-8 ARE SNOW EFFECTS - CAN BE MANUALLY SET TO MAKE IT SNOW. (OTHERWISE GOVERENED BY AREA SETTINGS/SEASON)
6 = The snow effect that comes with NWN2. 7 = My heavy snow effect. 8 = My blizzard snow effect (with sound).
9-11 ARE DUST STORM EFFECTS - CAN BE MANUALLY MADE TO DUST STORM. (OTHERWISE GOVERNED BY AREA/CHANCE SETTING)
Only BLIZZARD and HEAVY DUST STORM HAVE AN "WIND" SOUND ASSOCIATED WITH THEM.
(*) NOTE: If you forget and leave the global value at zero, it will force weather to always be sunny!
AREA SETTINGS POSSIBLE (DEFAULT 0)
----------------------------------
An area can have a LOCAL VARIABLE set inside "WEATHERBIAS". The following options are available:
0 = SUN, RAIN OR SNOW TO SEASON. (CHANCES OF RAIN BEING SNOW IN THE WINTER SEASONS) - DEFAULT SETTING
1 = SUN ONLY - LIKE A DESERT. (CHANCE OF TORRENTIAL DOWN POUR AS A STORM IN WINTER SEASONS OR 20% DUST STORM)
2 = SUN OR SNOW ONLY. (COLD REGIONS ALWAYS PRECIPITATE SNOW INSTEAD OF RAIN - SNOWY DESIGNED AREAS)
SCRIPT/TOOLSET SETUP
--------------------
1) Ensure the five sound objects are placed anywhere in the exterior areas you want to use the weather system.
2) Ensure this include script is within the module and include it in the ON CLIENT ENTER script with #include "alb_weather_system"
3) Ensure the LB_Weather.hak is associated with the module.
4) Add the following 3 lines of code to the ON CLIENT ENTER script for your module, where you have defined oArea already:
if(!GetIsAreaInterior(oArea) && GetGlobalInt("WEATHERSETUP") == 0){SetNewConditions(oArea);}
else if (!GetIsAreaInterior(oArea)){SetLocalInt(oArea, "AREAJUSTENTERED", 1); SetNewConditions(oArea, 1);}
if(GetIsAreaInterior(oArea)){SetGlobalInt("LIGHTNINGON", 0);} // STOP THUNDER SOUND INDOORS
*/
/////////////////////////////////////////////////////////////////////////////////////////////////
// Used to set the fog colours according to the current weather condition.
/////////////////////////////////////////////////////////////////////////////////////////////////
void SetFogColours(int iCurrentPower, object oArea);
/////////////////////////////////////////////////////////////////////////////////////////////////
// Used to update the SEF effect file running on the Weather Units throughout the area.
// DEFAULT USAGE: No parameter sent, removes all current weather effects used in the system.
/////////////////////////////////////////////////////////////////////////////////////////////////
void UpdateUnitEffect(object oPC, string SEFEffectFile = "");
/////////////////////////////////////////////////////////////////////////////////////////////////
// On first entering an area, this sets up the Weather Units across the entire area used to
// play the effects required for the current weather. (Only fires once on first area entry.)
/////////////////////////////////////////////////////////////////////////////////////////////////
void SetupWeatherObjects(object oArea);
/////////////////////////////////////////////////////////////////////////////////////////////////
// Used to create an invisible object close to the player from which a sound file can be played.
// The object is destroyed again after the file has finished playing.
/////////////////////////////////////////////////////////////////////////////////////////////////
void PlayThunder();
/////////////////////////////////////////////////////////////////////////////////////////////////
// Used to play the dedicated lightning light object in the area, which has been created
// when the player first entered the area. Light then turns off after a few seconds.
/////////////////////////////////////////////////////////////////////////////////////////////////
void RandomLightning();
/////////////////////////////////////////////////////////////////////////////////////////////////
// Applies a fog setting to all times of the day. Works better than FOG_TYPE_BOTH parameter.
/////////////////////////////////////////////////////////////////////////////////////////////////
void LBSetAllNWN2Fog(object oTarget, int nColor, float fFogStart, float fFogEnd);
/////////////////////////////////////////////////////////////////////////////////////////////////
// Complementing function to reset my all fog times set with LBSetAllNWN2Fog.
/////////////////////////////////////////////////////////////////////////////////////////////////
void LBResetAllNWN2Fog(object oTarget);
///////////////////////////////////////////////////////////////////////////////////////////
// MAIN FUNCTION FOR WEATHER SYSTEM STARTS HERE
// This function should be called from every area's ON CLIENT ENTER hook with the following 3 lines:
/* if(!GetIsAreaInterior(oArea) && GetGlobalInt("WEATHERSETUP") == 0){SetNewConditions(oArea);}
else if (!GetIsAreaInterior(oArea)){SetLocalInt(oArea, "AREAJUSTENTERED", 1); SetNewConditions(oArea, 1);}
if(GetIsAreaInterior(oArea)){SetGlobalInt("LIGHTNINGON", 0);} // STOP THUNDER SOUND INDOORS */
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// If the function is required to force start an overriding weather condition, then the IgnoreTimer
// parameter should be set as 1 like: SetNewConditions(oArea, 1); This then allows a variable
// to be set prior to calling this function and the changes to take place immediately. The
// parameter fFrequencyChange sets the time between weather update checking. Default is 300 seconds.
// NOTE: GLOBAL "SETWEATHER" values 0-11 force a weather condition. Any other GLOBAL value randomises.
///////////////////////////////////////////////////////////////////////////////////////////
void SetNewConditions(object oArea, int IgnoreTimer = 0, float fFrequencyChange = 300.0);
void SetNewConditions(object oArea, int IgnoreTimer = 0, float fFrequencyChange = 300.0)
{
///////////////////////////////////////////////////////////////////////////////////////////////////
// ONLY DO WEATHER IF THERE IS A VALID PC PRESENT IN THE AREA TO SEE IT
///////////////////////////////////////////////////////////////////////////////////////////////////
object oPC = GetFirstPC();
// UPDATE THE AREA IF THERE HAS BEEN A TRANSITION BETWEEN CHECKS
oArea = GetArea(oPC);
// NOT FOR AN INTERIOR AREA
if(GetIsAreaInterior(oArea)){SetGlobalInt("BEENINDOORS", 1); return;}
// BACK FROM INDOORS (TIMER DOES NEED RESTARTING AS OPPOSED FROM ANOTHER OUTDOOR AREA)
if(GetLocalInt(oArea, "AREAJUSTENTERED") == 1 && GetGlobalInt("BEENINDOORS") == 1)
{SetGlobalInt("BEENINDOORS", 0); IgnoreTimer = 0;}
// SendMessageToAllPCs("SCRIPT FIRED"); // DEBUG
///////////////////////////////////////////////////////////////////////////////////////////////////
// INITIATE RANDOMNESS OF WEATHER SYSTEM (CHANGES HEREAFTER ARE THE SCRIPTORS RESPONSIBILITY TO RESET)
///////////////////////////////////////////////////////////////////////////////////////////////////
if(GetGlobalInt("WEATHERSETUP") == 0)
{
SendMessageToPC(oPC,"<i>The weather looks changeable today.</i>");
SetGlobalInt("SETWEATHER", -1); SetGlobalInt("WEATHERSETUP", 1);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// PREPARE AREA OBJECTS - LIGHTNING LIGHT AND RAIN/WIND/THUNDER SOUNDS
///////////////////////////////////////////////////////////////////////////////////////////////////
int iWithlightning = 0; int iDustStorm = 0; int iChanceSnow = 0;
// RAIN, BLIZZARD/DUST & THUNDER SOUND OBJECTS
object oRainLight = GetNearestObjectByTag("alb_rain_light", oPC);
object oRainHeavy = GetNearestObjectByTag("alb_rain_heavy", oPC);
object oRainStorm = GetNearestObjectByTag("alb_rain_stormheavy", oPC);
object oThunder = GetNearestObjectByTag("alb_thunder_ambient", oPC);
object oBlizzard = GetNearestObjectByTag("alb_snow_blizzard", oPC);
// BUILDER WARNING THAT SOUND FILES ARE MISSING
if(oRainLight == OBJECT_INVALID || oRainHeavy == OBJECT_INVALID
|| oRainStorm == OBJECT_INVALID || oThunder == OBJECT_INVALID || oBlizzard == OBJECT_INVALID)
{SendMessageToPC(oPC, "WARNING - A WEATHER SOUND OBJECT IS MISSING IN THIS AREA - INFORM THE BUILDER");}
// DO NOT DO CLOUDS FOR AREA IF AVERAGE Z AXIS IS TOO HIGH (UNLESS FORCED BY BUILDER)
// SET TO -1 TO FORCE NO CLOUD USE OR 1 TO FORCE CLOUDS (ZERO AUTO)
int USECLOUDS = GetLocalInt(oArea, "USECLOUDS");
// SET UP WEATHER EFFECT UNITS THROUGHOUT THE AREA
object oWeatherUnit = GetNearestObjectByTag("alb_weather_unit", oPC);
if(oWeatherUnit == OBJECT_INVALID)
{
SetupWeatherObjects(oArea);
// TESTING AND SETTING CLOUD USAGE IF NOT ALREADY SET
if(USECLOUDS == 0)
{
float fCount = 0.0; float fZcoord;
object oAreaObject = GetFirstObjectInArea(oPC);
while(oAreaObject != OBJECT_INVALID)
{
vector vObject = GetPosition(oAreaObject);
fZcoord = GetLocalFloat(oArea, "ZAXIS") + vObject.z;
SetLocalFloat(oArea, "ZAXIS", fZcoord);
fCount = fCount + 1.0;
oAreaObject = GetNextObjectInArea(oPC);
}
float AveZCoord = fZcoord/fCount;
// TOO MUCH HEIGHT VARIATION FOR CLOUD USAGE
if(AveZCoord > 2.0 && GetLocalInt(oArea, "USECLOUDS") == 0)
{SetLocalInt(oArea, "USECLOUDS", -1); USECLOUDS = -1;}
// CLOUD USAGE SHOULD BE OK
else{SetLocalInt(oArea, "USECLOUDS", 1); USECLOUDS = 1;}
}
}
// USE ALL POWER SETTINGS TO ALLOW VARIANCE EVEN IF NO DIFF SEEN
// 0 = OFF, 1 = WEAK, 2 = LIGHT, 3 = MEDIUM, 4 = HEAVY; 5 = STORMY.
int iCurrentPower = GetGlobalInt("CURRENTPOWER");
// ALSO COMPARE AS A PREVIOUS SETTING
int iCurrentPowerArea = GetLocalInt(oArea, "CURRENTPOWERAREA");
// MAKE SURE A VALID LIGHTNING LIGHT IS SETUP
//object oLightning = GetNearestObjectByTag("alb_lightning", oPC); // REMOVED
object oLightning = GetLocalObject(oArea, "LIGHTNINGOBJECT"); // ADDED
if(oLightning == OBJECT_INVALID)
{
// PLACE LIGHT AT CENTRAL COORDS (E.g. 16x16 Tiles = 32x32 Size return. 10 Pixels per tile.)
float fAreaWidth = IntToFloat(GetAreaSize(AREA_WIDTH, oArea)/2) * 10.0;
float fAreaHeight = IntToFloat(GetAreaSize(AREA_HEIGHT, oArea)/2) * 10.0;
vector vPosition = Vector(fAreaWidth, fAreaHeight, 50.0);
location lCreate = Location(oArea, vPosition, 0.0);
oLightning = CreateObject(OBJECT_TYPE_LIGHT, "alb_lightning", lCreate);
SetLocalObject(oArea, "LIGHTNINGOBJECT", oLightning); // ADDED
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// SEASON BIAS TO WEATHER EFFECTS (MINUS FIGURES ARE ADDED WHEN APPLIED - MORE CHANCE OF RAIN)
///////////////////////////////////////////////////////////////////////////////////////////////////
int Month = GetCalendarMonth(); int SEASONBIAS;
if(Month == 1){SEASONBIAS = -15;} if(Month == 2){SEASONBIAS = -10;} if(Month == 3){SEASONBIAS = -5;} if(Month == 4){SEASONBIAS = 0;}
if(Month == 5){SEASONBIAS = 0;} if(Month == 6){SEASONBIAS = 5;} if(Month == 7){SEASONBIAS = 10;} if(Month == 8){SEASONBIAS = 15;}
if(Month == 9){SEASONBIAS = 10;} if(Month == 10){SEASONBIAS = 0;}if(Month == 11){SEASONBIAS = -10;}if(Month == 12){SEASONBIAS = -15;}
// WEATHER DIRECTION MODIFIER - ACCELERATION IF ALREADY GOING THIS WAY
string sDirection = GetGlobalString("WEATHERDIRECTION");
if(sDirection == ""){sDirection = "WORSE";}
int iBetterBonus = 1; if(sDirection == "BETTER"){iBetterBonus = 2;} // 5, 3, 1, 0
int iWorseBonus = 1; if(sDirection == "WORSE"){iWorseBonus = 2;} // 0, 2, 4, 5.
// CURRENT POWER CAN GO UP OR DOWN BY ONE CATEGORY (ACCORDING TO CURRENT DIRECTION)
int iVariance = d100() - SEASONBIAS; // NOTE: 45-55 NO CHANGE IN WEATHER
// DO NOT ALTER WEATHER CONDITION ON ENTRY TO THE AREA
int AreaJustEntered = GetLocalInt(oArea, "AREAJUSTENTERED");
DeleteLocalInt(oArea, "AREAJUSTENTERED");
if(AreaJustEntered == 0)
{
if(iVariance < 45){iCurrentPower = iCurrentPower - iBetterBonus;} if(iCurrentPower < 0){iCurrentPower = 0;}
if(iVariance > 55){iCurrentPower = iCurrentPower + iWorseBonus;} if(iCurrentPower > 5){iCurrentPower = 5;}
if(sDirection == "WORSE" && iCurrentPower == 5){SetGlobalString("WEATHERDIRECTION", "BETTER");}
if(sDirection == "BETTER" && iCurrentPower == 0){SetGlobalString("WEATHERDIRECTION", "WORSE");}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CHANGE ANY INSTANCES OF RAIN TO CHANCE OF SNOW IN WINTER SEASON
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iCurrentPower > 0 && iCurrentPower < 6)
{
if(Month == 10){iChanceSnow = 10;} if(Month == 11){iChanceSnow = 25;}
if(Month == 12){iChanceSnow = 50;} if(Month == 1){iChanceSnow = 50;}
if(Month == 2){iChanceSnow = 30;} if(Month == 3){iChanceSnow = 10;}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// WEATHER AREA BIAS (0, 1, OR 2 SET INSIDE "WEATHERBIAS" ON AREA VARIABLES)
// 0 = SUN, RAIN OR SNOW TO SEASON. 1 = SUN/DUST/STORM ONLY LIKE DESERT. 2 = SUN OR SNOW ONLY.
///////////////////////////////////////////////////////////////////////////////////////////////////
int iAreaBias = GetLocalInt(oArea, "WEATHERBIAS");
// CHANCE OF UNUSUAL PRECIPITATION (DESERT RAIN OR SNOW)
int iRoll = d100();
// SNOW REGION (WILL SNOW INSTEAD OF RAIN) OR CHANCE OF SNOW INSTEAD OF RAIN ELSEWHERE
if(iAreaBias == 2 || (iRoll < iChanceSnow && iAreaBias != 1)){iChanceSnow = 1;} else{iChanceSnow = 0;}
// DESERT REGION CHANCE OF DOWNPOUR IN THE WINTER MONTHS
if(iAreaBias == 1 && iRoll < iChanceSnow/10){iCurrentPower = 5;}
// DESERT REGION CHANCE OF DUST STORM IF NOT DOWNPOUR (SET AT 20%)
else if(iAreaBias == 1 && iCurrentPower > 0 && iCurrentPower < 6 && iRoll <= 20){iDustStorm = 1;}
// DESERT REGION - ELSE JUST SUN!
else if(iAreaBias == 1){iCurrentPower = 0;}
///////////////////////////////////////////////////////////////////////////////////////////////////
// WEATHER MANUAL OVERRIDE (SET GLOBAL "SETWEATHER" TO ANY OTHER VALUE OTHER THAN 0-11 TO RANDOMISE AGAIN)
// 0-5 = RAIN TYPES, 6-8 = SNOW TYPES, 9-11 = DUST TYPES.
///////////////////////////////////////////////////////////////////////////////////////////////////
int iOverride = GetGlobalInt("SETWEATHER"); if(iOverride > -1 && iOverride < 12){iCurrentPower = iOverride;}
// MANUAL SNOW OVERRIDE (6-8)
if(iCurrentPower > 5 && iCurrentPower < 9){iChanceSnow = 1;}
// MANUAL DUST OVERRIDE (9-11)
if(iCurrentPower > 8 && iCurrentPower < 12){iDustStorm = 1;}
///////////////////////////////////////////////////////////////////////////////////////////////////
// WEATHER CHANGE CHECK - NO POWER CHANGE THEN DO NOT UPDATE (IGNORE IF WEATHER NOT STARTED ON AREA OR IN COMBAT)
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iCurrentPower == iCurrentPowerArea || GetIsInCombat(oPC))
{
// DO NOT RESTART THE TIMER WITH A DIRECT WEATHER CHANGE CALL (ALREADY RUNNING)
if(IgnoreTimer == 1){if(AreaJustEntered == 1){SetFogColours(iCurrentPower, oArea);} return;}
DelayCommand(fFrequencyChange, SetNewConditions(oArea));
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// WEATHER IS CHANGING !!! - UPDATE CURRENT GLOBAL WEATHER && UPDATE FOR THIS AREA
///////////////////////////////////////////////////////////////////////////////////////////////////
// SendMessageToAllPCs("WEATHER UPDATING: " + IntToString(iCurrentPower)); // DEBUG
// HAVE TO UPDATE THE LOCAL & GLOBAL VARIABLES
SetGlobalInt("CURRENTPOWER", iCurrentPower);
SetLocalInt(oArea, "CURRENTPOWERAREA", iCurrentPower);
// REMOVE ALL CURRENT EFFECTS
UpdateUnitEffect(oPC);
///////////////////////////////////////////////////////////////////////////////////////////////////
// CURRENT == 0 ------------- SUNNY (OR SNOWING OR DUST STORM) - NO RAIN THOUGH
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iCurrentPower == 0 || iChanceSnow == 1 || iDustStorm == 1)
{
// STOP ALL SOUNDS, LIGHTNING & RESET FOG
SoundObjectStop(oRainLight);
SoundObjectStop(oRainHeavy);
SoundObjectStop(oRainStorm);
SoundObjectStop(oThunder);
SoundObjectStop(oBlizzard);
SetLightActive(oLightning, FALSE);
LBResetAllNWN2Fog(oArea);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// SNOW IS POSSIBLE FOR SEASON OR HAS BEEN FORCED - CREATE SNOW VFX & REDUCE LIGHTING
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iChanceSnow == 1)
{
string sSnow = "LBSnow"; // DEFAULT HEAVY SNOW
// RANDOM CHANCE SNOW
if(iCurrentPower < 6)
{
if(iCurrentPower < 3){sSnow = "fx_snowfall";} // LIGHT SNOW (1-2)
if(iCurrentPower > 4){sSnow = "LBSnowBlizzard";} // BLIZZARD (5)
}
// FORCED SNOW CONDITIONS (USE WIND SOUND OBJECT FOR BLIZZARD)
if(iCurrentPower == 6){sSnow = "fx_snowfall";} // LIGHT SNOW
if(iCurrentPower == 8){sSnow = "LBSnowBlizzard";} // BLIZZARD
// UPDATE THE WEATHER UNIT WITH SNOW EFFECT (AND SOUND IF A BLIZZARD)
UpdateUnitEffect(oPC, sSnow); if(sSnow == "LBSnowBlizzard"){DelayCommand(0.5, SoundObjectPlay(oBlizzard));}
// ADD CLOUDS AND REDUCE LIGHTING
if(USECLOUDS == 1){UpdateUnitEffect(oPC, "LBDGreyClouds");}
SetFogColours(iCurrentPower, oArea);
// AREA FLAVOUR TEXT
SetNoticeText(oPC, "It begins to snow!");
// PREVENT DEFAULT NWN2 RAIN VFX FROM SHOWING
iCurrentPower = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// DUST STORM IS POSSIBLE FOR SEASON OR HAS BEEN FORCED - CREATE DUST VFX & REDUCE LIGHTING
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iDustStorm == 1)
{
string sDust = "LBDustMedium"; // DEFAULT MEDIUM STORM
// RANDOM CHANCE DUST STORM
if(iCurrentPower < 6)
{
if(iCurrentPower < 3){sDust = "LBDustLight";} // LIGHT DUST (1-2)
if(iCurrentPower > 4){sDust = "LBDustHeavy";} // HEAVY DUST (5)
}
// FORCED DUST CONDITIONS (USE WIND SOUND OBJECT FOR HEAVY)
if(iCurrentPower == 9){sDust = "LBDustLight";} // LIGHT DUST (9)
if(iCurrentPower == 11){sDust = "LBDustHeavy";} // HEAVY DUST (11)
// UPDATE THE WEATHER UNIT WITH DUST EFFECT (AND SOUND IF A HEAVY ONE)
UpdateUnitEffect(oPC, sDust); if(sDust == "LBDustHeavy"){DelayCommand(0.5, SoundObjectPlay(oBlizzard));}
// REDUCE LIGHTING
SetFogColours(iCurrentPower, oArea);
// AREA FLAVOUR TEXT
SetNoticeText(oPC, "A dust storm!");
// PREVENT DEFAULT NWN2 RAIN VFX FROM SHOWING
iCurrentPower = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// NOT SNOWING OR DUST STORM - RAINING INSTEAD!
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// CURRENT == 1 OR 2 ------------- WEAK OR LIGHT RAIN (1 OR 2)
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iCurrentPower > 0 && iCurrentPower < 3)
{
// START THIS SOUND
DelayCommand(0.5, SoundObjectPlay(oRainLight));
// STOP THESE SOUNDS
SoundObjectStop(oRainHeavy);
SoundObjectStop(oRainStorm);
SoundObjectStop(oThunder);
SoundObjectStop(oBlizzard);
// ADD CLOUDS AND REDUCE LIGHTING
if(USECLOUDS == 1){UpdateUnitEffect(oPC, "LBGreyClouds");}
// REDUCE LIGHTING
SetFogColours(iCurrentPower, oArea);
// CHANCE OF FOG WITH LIGHT RAINS (LIMIT WINDOW TO PREVENT COMING AND GOING IN TIME PERIOD)
if(GetTimeHour() > 6 && GetTimeHour() < 10)
{
DelayCommand(0.5, UpdateUnitEffect(oPC, "fx_area_fog_white"));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CURRENT == 3, 4 OR 5 ------------- MEDIUM, HEAVY OR STORMY (3, 4, OR 5)
///////////////////////////////////////////////////////////////////////////////////////////////////
if(iCurrentPower > 2 && iCurrentPower < 6)
{
// MEDIUM RAIN
if(iCurrentPower == 3 || iCurrentPower == 4)
{
// START THIS SOUND
DelayCommand(0.5, SoundObjectPlay(oRainHeavy));
DelayCommand(0.5, SoundObjectPlay(oThunder));
// STOP THESE SOUNDS
SoundObjectStop(oRainLight);
SoundObjectStop(oRainStorm);
SoundObjectStop(oBlizzard);
// ADD CLOUDS AND REDUCE LIGHTING
if(USECLOUDS == 1){UpdateUnitEffect(oPC, "LBDGreyClouds");}
// REDUCE LIGHTING
SetFogColours(iCurrentPower, oArea);
// ADD RAIN SPLASH
DelayCommand(0.5, UpdateUnitEffect(oPC, "fx_rain_onlysplash02"));
// HEAVY RAIN (50% CHANCE LIGHTNING)
if(iCurrentPower == 4 && d2() == 2){iWithlightning = 1;}
}
// STORM (WITH LIGHTNING)
if(iCurrentPower == 5)
{
// PLAY THIS SOUND
DelayCommand(0.5, SoundObjectPlay(oRainStorm));
DelayCommand(0.5, SoundObjectPlay(oThunder));
// STOP THESE SOUNDS
SoundObjectStop(oRainLight);
SoundObjectStop(oRainHeavy);
SoundObjectStop(oBlizzard);
// ADD CLOUDS AND REDUCE LIGHTING
if(USECLOUDS == 1){UpdateUnitEffect(oPC, "LBDarkClouds");}
// REDUCE LIGHTING
SetFogColours(iCurrentPower, oArea);
// ADD DOWNPOUR RAIN & SPLASH
DelayCommand(0.5, UpdateUnitEffect(oPC, "LBRainSplash"));
// START LIGHTNING
iWithlightning = 1;
// AREA FLAVOUR TEXT
if(iAreaBias == 1){SetNoticeText(oPC, "A desert downpour!");}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// LIGHTNING CONTROL - ALSO STARTS THUNDER SOUNDS
///////////////////////////////////////////////////////////////////////////////////////////////////
// LIGHTNING NO LONGER AROUND
if(iWithlightning == 0){SetGlobalInt("LIGHTNINGON", 0);}
// PLAY LIGHTNING FX AND THUNDER SOUNDS
if(iWithlightning == 1 && GetGlobalInt("LIGHTNINGON") == 0)
{
SetGlobalInt("LIGHTNINGON", 1);
DelayCommand(IntToFloat(Random(10) + 5), RandomLightning());
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// UPDATE THE WEATHER "POWER" USING NWN2 WEATHER FUNCTION (ONLY 0-5 MEAN ANYTHING)
///////////////////////////////////////////////////////////////////////////////////////////////////
SetWeather(oArea, 0, iCurrentPower);
// DO NOT RESTART THE TIMER WITH A DIRECT WEATHER CHANGE CALL (ALREADY RUNNING)
if(IgnoreTimer == 1){return;}
// WEATHER UPDATED AS OFTEN AS fFrequencyChange
DelayCommand(fFrequencyChange, SetNewConditions(oArea));
}
// ----------------------------------------------------------------------------------------------------
// END MAIN WEATHER ROUTINE
// ----------------------------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////////
// WEATHER FUNCTIONS USED WITHIN THIS SCRIPT BELOW
///////////////////////////////////////////////////////////////////////////////////////////////////
void SetFogColours(int iCurrentPower, object oArea)
{
if(iCurrentPower == 1){LBResetAllNWN2Fog(oArea);}
if(iCurrentPower == 2){LBSetAllNWN2Fog(oArea, FOG_COLOR_GREY, 40.0, 75.0);}
if(iCurrentPower == 3){LBSetAllNWN2Fog(oArea, FOG_COLOR_BLACK, 40.0, 75.0);}
if(iCurrentPower == 4){LBSetAllNWN2Fog(oArea, FOG_COLOR_BLACK, 30.0, 75.0);}
if(iCurrentPower == 5){LBSetAllNWN2Fog(oArea, FOG_COLOR_BLACK, 20.0, 75.0);}
if(iCurrentPower == 6){LBSetAllNWN2Fog(oArea, 767676, 35.0, 75.0);}
if(iCurrentPower == 7){LBSetAllNWN2Fog(oArea, 767676, 30.0, 60.0);}
if(iCurrentPower == 8){LBSetAllNWN2Fog(oArea, 767676, 25.0, 50.0);}
if(iCurrentPower == 9){LBSetAllNWN2Fog(oArea, FOG_COLOR_ORANGE_DARK, 30.0, 75.0);}
if(iCurrentPower == 10){LBSetAllNWN2Fog(oArea, FOG_COLOR_ORANGE_DARK, 25.0, 60.0);}
if(iCurrentPower == 11){LBSetAllNWN2Fog(oArea, FOG_COLOR_ORANGE_DARK, 20.0, 50.0);}
}
void LBSetAllNWN2Fog(object oTarget, int nColor, float fFogStart, float fFogEnd)
{
SetNWN2Fog(oTarget, FOG_TYPE_NWN2_SUNRISE, nColor, fFogStart, fFogEnd );
SetNWN2Fog(oTarget, FOG_TYPE_NWN2_DAYTIME, nColor, fFogStart, fFogEnd );
SetNWN2Fog(oTarget, FOG_TYPE_NWN2_SUNSET, nColor, fFogStart, fFogEnd );
SetNWN2Fog(oTarget, FOG_TYPE_NWN2_MOONRISE, nColor, fFogStart, fFogEnd );
SetNWN2Fog(oTarget, FOG_TYPE_NWN2_NIGHTTIME, nColor, fFogStart, fFogEnd );
SetNWN2Fog(oTarget, FOG_TYPE_NWN2_MOONSET, nColor, fFogStart, fFogEnd );
}
void LBResetAllNWN2Fog(object oTarget)
{
ResetNWN2Fog(oTarget, FOG_TYPE_NWN2_SUNRISE);
ResetNWN2Fog(oTarget, FOG_TYPE_NWN2_DAYTIME);
ResetNWN2Fog(oTarget, FOG_TYPE_NWN2_SUNSET);
ResetNWN2Fog(oTarget, FOG_TYPE_NWN2_MOONRISE);
ResetNWN2Fog(oTarget, FOG_TYPE_NWN2_NIGHTTIME);
ResetNWN2Fog(oTarget, FOG_TYPE_NWN2_MOONSET);
}
void UpdateUnitEffect(object oPC, string SEFEffectFile = "")
{
if(SEFEffectFile == "")
{
// USE A STATIC OBJECT TO LOOP FROM (PC MAY MOVE AND CHANGE TARGET)
int iCounter = 1; object oFrom = GetNearestObjectByTag("alb_rain_light", oPC);
object oWeatherUnit = GetNearestObjectByTag("alb_weather_unit", oFrom, iCounter);
while(oWeatherUnit != OBJECT_INVALID)
{
// REMOVE ALL POSSIBLE WEATHER EFFECTS
RemoveSEFFromObject(oWeatherUnit, "fx_snowfall"); // SNOW (LIGHT)
RemoveSEFFromObject(oWeatherUnit, "LBSnow"); // SNOW (HEAVY)
RemoveSEFFromObject(oWeatherUnit, "LBSnowBlizzard"); // SNOW (BLIZZARD)
RemoveSEFFromObject(oWeatherUnit, "LBRainSplash"); // STORM EXTRA RAIN AND SPLASH
RemoveSEFFromObject(oWeatherUnit, "LBDarkClouds"); // DARK (BLACK) CLOUDS
RemoveSEFFromObject(oWeatherUnit, "LBGreyClouds"); // GREY CLOUDS
RemoveSEFFromObject(oWeatherUnit, "LBDGreyClouds"); // DARK GREY CLOUDS
RemoveSEFFromObject(oWeatherUnit, "fx_rain_onlysplash02"); // SPLASH ONLY (LOCAL)
RemoveSEFFromObject(oWeatherUnit, "fx_area_fog_white"); // AREA FOG
RemoveSEFFromObject(oWeatherUnit, "LBDustLight"); // LIGHT DUST STORM
RemoveSEFFromObject(oWeatherUnit, "LBDustMedium"); // MEDIUM DUST STORM
RemoveSEFFromObject(oWeatherUnit, "LBDustHeavy"); // HEAVY DUST STORM
iCounter = iCounter + 1;
oWeatherUnit = GetNearestObjectByTag("alb_weather_unit", oFrom, iCounter);
}
}
else
{
effect eVFX = EffectNWN2SpecialEffectFile(SEFEffectFile);
// USE A STATIC OBJECT TO LOOP FROM (PC MAY MOVE AND CHANGE TARGET)
int iCounter = 1; object oFrom = GetNearestObjectByTag("alb_rain_light", oPC);
object oWeatherUnit = GetNearestObjectByTag("alb_weather_unit", oFrom, iCounter);
while(oWeatherUnit != OBJECT_INVALID)
{
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eVFX, oWeatherUnit);
iCounter = iCounter + 1; oWeatherUnit = GetNearestObjectByTag("alb_weather_unit", oFrom, iCounter);
}
}
}
void SetupWeatherObjects(object oArea)
{
float fAreaWidth = IntToFloat(GetAreaSize(AREA_WIDTH, oArea)); // TILES WIDE (DOUBLES TILES IN TOOLSET)
float fAreaHeight = IntToFloat(GetAreaSize(AREA_HEIGHT, oArea)); // TILES HIGH (DOUBLES TILES IN TOOLSET)
// PIXELS NEED TO GO AT LEAST 20 ABOVE MAXIMUM POSSIBLE TO ENSURE EFFECTS SHOW ALL AROUND
float fMaxWidthPixels = 10 * fAreaWidth; // MAXIMUM WIDTH PIXELS REQUIRED
float fMaxHeightPixels = 10 * fAreaHeight; // MAXIMUM HEIGHT PIXELS REQUIRED
// PLASTER WEATHER UNITS ALL OVER THE AREA
while(fAreaWidth != 0.0)
{
float fPixlesPlaceWidth = fAreaWidth * 10;
if(fAreaWidth > 1.0)
{
while(fAreaHeight != 0.0)
{
float fPixlesPlaceHeight = fAreaHeight * 10;
if(fAreaHeight > 1.0)
{
vector vPosition = Vector(fPixlesPlaceWidth, fPixlesPlaceHeight, 0.0);
location lCreate = Location(oArea, vPosition, 0.0);
if(GetIsLocationValid(lCreate))
{
lCreate = CalcSafeLocation(GetFirstPC(), lCreate, 1.0, FALSE, FALSE);
}
if(lCreate != GetLocation(GetFirstPC()))
{
object oUnit = CreateObject(OBJECT_TYPE_PLACEABLE, "alb_weather_unit", lCreate);
}
}
fAreaHeight = fAreaHeight - 2.0; // KEEP ALTERNATE TO REDUCE LAG
}
fAreaHeight = IntToFloat(GetAreaSize(AREA_HEIGHT, oArea));
}
fAreaWidth = fAreaWidth - 2.0; // KEEP ALTERNATE TO REDUCE LAG
}
}
void PlayThunder()
{
// WE HAVE STOPPED
if(GetGlobalInt("LIGHTNINGON") == 0){return;}
string sThunder = "as_na_thunder_" + IntToString(Random(7) + 1);
object oTemp = CreateObject(OBJECT_TYPE_PLACEABLE, "alb_temp_weather", GetLocation(GetFirstPC()));
DelayCommand(IntToFloat(d2()), AssignCommand(oTemp, PlaySound(sThunder, TRUE)));
DestroyObject(oTemp, 10.0, FALSE);
}
void RandomLightning()
{
// WE HAVE STOPPED
if(GetGlobalInt("LIGHTNINGON") == 0){return;}
// LIGHTNING
//object oLightning = GetNearestObjectByTag("alb_lightning", GetFirstPC()); // REMOVE
object oLightning = GetLocalObject(GetArea(GetFirstPC()), "LIGHTNINGOBJECT"); //ADDED
SetLightActive(oLightning, TRUE);
DelayCommand(IntToFloat(d2()+ 1),SetLightActive(oLightning, FALSE));
DelayCommand(IntToFloat(d2()), PlayThunder());
// KEEP GOING IF REQUIRED
DelayCommand(IntToFloat(Random(10) + 30), RandomLightning());
}
Modifié par Lance Botelle, 17 juin 2013 - 03:10 .





Retour en haut






