ModernUO/Projects/Scripts/Misc/Weather.cs
Kamron Batman 179cb50557 Updates Packets & Randomizer (#43)
* Fixes a bug with the main loop. Removes unnecessary optimizations for RDRand.

* WIP - Rewriting packets.

* Cleanup and updates README

* Converts more packets

* Fixes header

* Converts Effects packets.

* Forgot the send command

* Adds the start of containers packets.

* Adds message packets with caching

* Extends the send methods

* Starts to add Acquire methods

* Converted the packets

* Cleanup

* Cleanup

* Adds more packets

* Adds more packets

* Fixes clearing arrays from pool. Adds Mobile Incoming

* Converts more packets.

* Moves more packets

* Moves more packets

* Test compression

* Merges

* Migrating to an idiomatic syntax that also supports compression, and proxying.

* Optimize the stack alloc. Changes attributes

* Converted container packets

* Visual Studio doesn't auto save files. I am still getting used to subpar IDEs.

* Adds static packet caching. Will profile later. Converts more packets

* Fixes packets and changes how compression is configured

* WIP - Adds basics for Gumps. Not finished though.

* Fix file

* Fixes formatting

* Changed SpanWriter to be more idiomatic.

* Fixes Span vs RawSpan and missing stackallocs

* Converts over some more gumps

* WIP - Deletes 32bit support.

* Drops RDRand32 support.

* Fixes gump compilation

* Converting gump components

* Removes old huffman compression function

* Revert signature for backwards compatibility

* WIP - Converting more gump components

* Creates ArraySet for the strings. Updates AppendTo to reference that.

* Converts the maining gump components

* Cleans up gump components

* Cleans up directives

* Cleans up ArraySet and moves it. Adds null-coalescing-assignment

* Cleanup, Target Packets, and C# 8 changes.

* Removed OPL Packet

* World packets

* Fixing packet uses

* Cleans up code. Fixes packet uses in various places.

* More cleanup for packets

* Code cleanup

* Converts more packet uses and cleans up more code

* More code cleanup

* Finishes fixing the packets in Item

* Updates secure trade packets

* Updates core and gets it to compile.

* Moved packets to scripts. Fixed account handler use of packets

* Code cleanup

* Updates chat packets

* Code cleanuo

* Adds party packets, but need to implement them.

* Party packets WIP

* Finishes party packets

* Rearrange movement namespaces and classes

* Finishes plant packets

* Code Formatting

* Fixes moving effects

* Code cleanup, eliminates equipinfo

* Adds more packets. Fixes bugs with various packets.

* Finishes mahjon packets

* Fixes mahjong packet

* Code cleanup

* Finishes mahjong packets

* Adds Map packets

* Add multifacet maps and charts

* Cleans up some packets with UTF8

* Optimizes packets

* Cleans up more packets. Moves the MessageHelper

* Removes assistant support. Removes extended protocol. Incorporates MapUO packets as normal packets.

* Updates protocol extensions packet receiver

* Fixes a few bugs. Fixes a few more packets.

* Code cleanup and fixing more packets

* Fixes packet effects

* Cleaned up more code

* Buff Icon cleanup

* Removed unused constructors

* Code Cleanup. Adds BoatHS Packets

* Moves house files. Updates house foundation packets.

* Deployment cleanup

* Fixes:

* Code cleanup

* More code cleanup

* More code cleanup

* Cleaned up BaseHouse

* Enforces styling

* Converts foreach to linq where possible.

* Dont need that

* Goals/Readme updates

* Removes 32bit support at the highest level. Turns on HRT by default.

* Code cleanup. Fixes extended features packet.

* Fixes various bugs

* Code cleanup

* Code cleanup

* Code cleanup. Fixes gump X/Y assignment.

* Code cleanup using |= operator

* More code cleanup

* Cleanup

* Fixes spacing issues. Thanks Visual Studio. You suck.

* Compiler error

* Fixes NPE from RunUO 2.7

* Renames ScriptCompiler to AssemblyHandler. Fixes packets. Updates README

* Fixes more packets. Stupid trailing nulls.

* Fixes various bugs.

* Fixes for gumps

* Fixes more gump stuff. Going to split it out later since it is getting insane

* Recoded the gump writing

* WIP

* *Added output path of scripts project to dev branch
*Activated debugging in code
2019-11-11 12:40:16 +01:00

351 lines
9.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
using Server.Network;
namespace Server.Misc
{
public class Weather
{
private static Map[] m_Facets;
private static Dictionary<Map, List<Weather>> m_WeatherByFacet = new Dictionary<Map, List<Weather>>();
public static void Initialize()
{
m_Facets = new[]{ Map.Felucca, Map.Trammel };
/* Static weather:
*
* Format:
* AddWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, <area ...> );
*/
// ice island
AddWeather( -15, 100, 5, new Rectangle2D( 3850, 160, 390, 320 ), new Rectangle2D( 3900, 480, 380, 180 ), new Rectangle2D( 4160, 660, 150, 110 ) );
// covetous entrance, around vesper and minoc
AddWeather( +15, 50, 5, new Rectangle2D( 2425, 725, 250, 250 ) );
// despise entrance, north of britain
AddWeather( +15, 50, 5, new Rectangle2D( 1245, 1045, 250, 250 ) );
/* Dynamic weather:
*
* Format:
* AddDynamicWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, moveSpeed, width, height, bounds );
*/
for ( int i = 0; i < 15; ++i )
AddDynamicWeather( +15, 100, 5, 8, 400, 400, new Rectangle2D( 0, 0, 5120, 4096 ) );
}
public static List<Weather> GetWeatherList( Map facet )
{
if ( facet == null )
return null;
if (!m_WeatherByFacet.TryGetValue( facet, out List<Weather> list ))
m_WeatherByFacet[facet] = list = new List<Weather>();
return list;
}
public static void AddDynamicWeather( int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, int moveSpeed, int width, int height, Rectangle2D bounds )
{
for ( int i = 0; i < m_Facets.Length; ++i )
{
Rectangle2D area = new Rectangle2D();
bool isValid = false;
for ( int j = 0; j < 10; ++j )
{
area = new Rectangle2D( bounds.X + Utility.Random( bounds.Width - width ), bounds.Y + Utility.Random( bounds.Height - height ), width, height );
if ( !CheckWeatherConflict( m_Facets[i], null, area ) )
isValid = true;
if ( isValid )
break;
}
if ( !isValid )
continue;
new Weather(m_Facets[i], new[] { area }, temperature, chanceOfPercipitation, chanceOfExtremeTemperature,
TimeSpan.FromSeconds(30.0)) { Bounds = bounds, MoveSpeed = moveSpeed };
}
}
public static void AddWeather( int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, params Rectangle2D[] area )
{
for ( int i = 0; i < m_Facets.Length; ++i )
new Weather( m_Facets[i], area, temperature, chanceOfPercipitation, chanceOfExtremeTemperature, TimeSpan.FromSeconds( 30.0 ) );
}
public static bool CheckWeatherConflict( Map facet, Weather exclude, Rectangle2D area )
{
List<Weather> list = GetWeatherList( facet );
if ( list == null )
return false;
for ( int i = 0; i < list.Count; ++i )
{
Weather w = list[i];
if ( w != exclude && w.IntersectsWith( area ) )
return true;
}
return false;
}
public Map Facet { get; }
public Rectangle2D[] Area { get; set; }
public int Temperature { get; set; }
public int ChanceOfPercipitation { get; set; }
public int ChanceOfExtremeTemperature { get; set; }
// For dynamic weather:
public Rectangle2D Bounds { get; set; }
public int MoveSpeed { get; set; }
public int MoveAngleX { get; set; }
public int MoveAngleY { get; set; }
public static bool CheckIntersection( Rectangle2D r1, Rectangle2D r2 ) => r1.X < r2.X + r2.Width && r2.X < r1.X + r1.Width && r1.Y < r2.Y + r2.Height && r2.Y < r1.Y + r1.Height;
public static bool CheckContains( Rectangle2D big, Rectangle2D small ) =>
small.X >= big.X && small.Y >= big.Y && small.X + small.Width <= big.X + big.Width
&& small.Y + small.Height <= big.Y + big.Height;
public virtual bool IntersectsWith( Rectangle2D area )
{
for ( int i = 0; i < Area.Length; ++i )
if ( CheckIntersection( area, Area[i] ) )
return true;
return false;
}
public Weather( Map facet, Rectangle2D[] area, int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, TimeSpan interval )
{
Facet = facet;
Area = area;
Temperature = temperature;
ChanceOfPercipitation = chanceOfPercipitation;
ChanceOfExtremeTemperature = chanceOfExtremeTemperature;
List<Weather> list = GetWeatherList( facet );
list?.Add( this );
Timer.DelayCall( TimeSpan.FromSeconds( (0.2+Utility.RandomDouble()*0.8) * interval.TotalSeconds ), interval, OnTick );
}
public virtual void Reposition()
{
if ( Area.Length == 0 )
return;
int width = Area[0].Width;
int height = Area[0].Height;
Rectangle2D area = new Rectangle2D();
bool isValid = false;
for ( int j = 0; j < 10; ++j )
{
area = new Rectangle2D( Bounds.X + Utility.Random( Bounds.Width - width ), Bounds.Y + Utility.Random( Bounds.Height - height ), width, height );
if ( !CheckWeatherConflict( Facet, this, area ) )
isValid = true;
if ( isValid )
break;
}
if ( !isValid )
return;
Area[0] = area;
}
public virtual void RecalculateMovementAngle()
{
double angle = Utility.RandomDouble() * Math.PI * 2.0;
double cos = Math.Cos( angle );
double sin = Math.Sin( angle );
MoveAngleX = (int)(100 * cos);
MoveAngleY = (int)(100 * sin);
}
public virtual void MoveForward()
{
if ( Area.Length == 0 )
return;
for ( int i = 0; i < 5; ++i ) // try 5 times to find a valid spot
{
int xOffset = MoveSpeed * MoveAngleX / 100;
int yOffset = MoveSpeed * MoveAngleY / 100;
Rectangle2D oldArea = Area[0];
Rectangle2D newArea = new Rectangle2D( oldArea.X + xOffset, oldArea.Y + yOffset, oldArea.Width, oldArea.Height );
if ( !CheckWeatherConflict( Facet, this, newArea ) && CheckContains( Bounds, newArea ) )
{
Area[0] = newArea;
break;
}
RecalculateMovementAngle();
}
}
private int m_Stage;
private bool m_Active;
private bool m_ExtremeTemperature;
public virtual void OnTick()
{
if ( m_Stage == 0 )
{
m_Active = ChanceOfPercipitation > Utility.Random( 100 );
m_ExtremeTemperature = ChanceOfExtremeTemperature > Utility.Random( 100 );
if ( MoveSpeed > 0 )
{
Reposition();
RecalculateMovementAngle();
}
}
if ( m_Active )
{
if ( m_Stage > 0 && MoveSpeed > 0 )
MoveForward();
int type, density;
int temperature = Temperature;
if ( m_ExtremeTemperature )
temperature *= -1;
if ( m_Stage < 15 )
{
density = m_Stage * 5;
}
else
{
density = 150 - m_Stage * 5;
if ( density < 10 )
density = 10;
else if ( density > 70 )
density = 70;
}
if ( density == 0 )
type = 0xFE;
else if ( temperature > 0 )
type = 0;
else
type = 2;
List<NetState> states = NetState.Instances;
Packet weatherPacket = null;
for ( int i = 0; i < states.Count; ++i )
{
NetState ns = states[i];
Mobile mob = ns.Mobile;
if ( mob == null || mob.Map != Facet )
continue;
bool contains = Area.Length == 0;
for ( int j = 0; !contains && j < Area.Length; ++j )
contains = Area[j].Contains( mob.Location );
if ( !contains )
continue;
if ( weatherPacket == null )
weatherPacket = Packet.Acquire( new Server.Network.Weather( type, density, temperature ) );
ns.Send( weatherPacket );
}
Packet.Release( weatherPacket );
}
m_Stage++;
m_Stage %= 30;
}
}
public class WeatherMap : MapItem
{
public override string DefaultName => "weather map";
[Constructible]
public WeatherMap()
{
SetDisplay( 0, 0, 5119, 4095, 400, 400 );
}
public override void OnDoubleClick( Mobile from )
{
Map facet = from.Map;
if ( facet == null )
return;
List<Weather> list = Weather.GetWeatherList( facet );
ClearPins();
for ( int i = 0; i < list.Count; ++i )
{
Weather w = list[i];
for ( int j = 0; j < w.Area.Length; ++j )
AddWorldPin( w.Area[j].X + w.Area[j].Width/2, w.Area[j].Y + w.Area[j].Height/2 );
}
base.OnDoubleClick( from );
}
public WeatherMap( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( 0 );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
}
}