#W# Initial Commit: Avatars Conquest
This commit is contained in:
commit
5df497787a
7510 changed files with 416048 additions and 0 deletions
40
Scripts/Misc/AccountPrompt.cs
Normal file
40
Scripts/Misc/AccountPrompt.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class AccountPrompt
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
if ( Accounts.Count == 0 && !Core.Service )
|
||||
{
|
||||
Console.WriteLine( "This server has no accounts." );
|
||||
Console.Write( "Do you want to create the owner account now? (y/n)" );
|
||||
|
||||
if( Console.ReadKey( true ).Key == ConsoleKey.Y )
|
||||
{
|
||||
Console.WriteLine();
|
||||
|
||||
Console.Write( "Username: " );
|
||||
string username = Console.ReadLine();
|
||||
|
||||
Console.Write( "Password: " );
|
||||
string password = Console.ReadLine();
|
||||
|
||||
Account a = new Account( username, password );
|
||||
a.AccessLevel = AccessLevel.Owner;
|
||||
|
||||
Console.WriteLine( "Account created." );
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine( "Account not created." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Scripts/Misc/Animations.cs
Normal file
30
Scripts/Misc/Animations.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Animations
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.AnimateRequest += new AnimateRequestEventHandler( EventSink_AnimateRequest );
|
||||
}
|
||||
|
||||
private static void EventSink_AnimateRequest( AnimateRequestEventArgs e )
|
||||
{
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
int action;
|
||||
|
||||
switch ( e.Action )
|
||||
{
|
||||
case "bow": action = 32; break;
|
||||
case "salute": action = 33; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if ( from.Alive && !from.Mounted && from.Body.IsHuman )
|
||||
from.Animate( action, 5, 1, true, false, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Scripts/Misc/AttackMessage.cs
Normal file
62
Scripts/Misc/AttackMessage.cs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class AttackMessage
|
||||
{
|
||||
private const string AggressorFormat = "You are attacking {0}!";
|
||||
private const string AggressedFormat = "{0} is attacking you!";
|
||||
private const int Hue = 0x22;
|
||||
|
||||
private static TimeSpan Delay = TimeSpan.FromMinutes( 1.0 );
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.AggressiveAction += new AggressiveActionEventHandler( EventSink_AggressiveAction );
|
||||
}
|
||||
|
||||
public static void EventSink_AggressiveAction( AggressiveActionEventArgs e )
|
||||
{
|
||||
Mobile aggressor = e.Aggressor;
|
||||
Mobile aggressed = e.Aggressed;
|
||||
|
||||
if ( !aggressor.Player || !aggressed.Player )
|
||||
return;
|
||||
|
||||
if ( !CheckAggressions( aggressor, aggressed ) )
|
||||
{
|
||||
aggressor.LocalOverheadMessage( MessageType.Regular, Hue, true, String.Format( AggressorFormat, aggressed.Name ) );
|
||||
aggressed.LocalOverheadMessage( MessageType.Regular, Hue, true, String.Format( AggressedFormat, aggressor.Name ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CheckAggressions( Mobile m1, Mobile m2 )
|
||||
{
|
||||
List<AggressorInfo> list = m1.Aggressors;
|
||||
|
||||
for ( int i = 0; i < list.Count; ++i )
|
||||
{
|
||||
AggressorInfo info = list[i];
|
||||
|
||||
if ( info.Attacker == m2 && DateTime.Now < (info.LastCombatTime + Delay) )
|
||||
return true;
|
||||
}
|
||||
|
||||
list = m2.Aggressors;
|
||||
|
||||
for ( int i = 0; i < list.Count; ++i )
|
||||
{
|
||||
AggressorInfo info = list[i];
|
||||
|
||||
if ( info.Attacker == m1 && DateTime.Now < (info.LastCombatTime + Delay) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Scripts/Misc/AutoRestart.cs
Normal file
88
Scripts/Misc/AutoRestart.cs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Server;
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class AutoRestart : Timer
|
||||
{
|
||||
public static bool Enabled = false; // is the script enabled?
|
||||
|
||||
private static TimeSpan RestartTime = TimeSpan.FromHours( 2.0 ); // time of day at which to restart
|
||||
private static TimeSpan RestartDelay = TimeSpan.Zero; // how long the server should remain active before restart (period of 'server wars')
|
||||
|
||||
private static TimeSpan WarningDelay = TimeSpan.FromMinutes( 1.0 ); // at what interval should the shutdown message be displayed?
|
||||
|
||||
private static bool m_Restarting;
|
||||
private static DateTime m_RestartTime;
|
||||
|
||||
public static bool Restarting
|
||||
{
|
||||
get{ return m_Restarting; }
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register( "Restart", AccessLevel.Administrator, new CommandEventHandler( Restart_OnCommand ) );
|
||||
new AutoRestart().Start();
|
||||
}
|
||||
|
||||
public static void Restart_OnCommand( CommandEventArgs e )
|
||||
{
|
||||
if ( m_Restarting )
|
||||
{
|
||||
e.Mobile.SendMessage( "The server is already restarting." );
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage( "You have initiated server shutdown." );
|
||||
Enabled = true;
|
||||
m_RestartTime = DateTime.Now;
|
||||
}
|
||||
}
|
||||
|
||||
public AutoRestart() : base( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ) )
|
||||
{
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
|
||||
m_RestartTime = DateTime.Now.Date + RestartTime;
|
||||
|
||||
if ( m_RestartTime < DateTime.Now )
|
||||
m_RestartTime += TimeSpan.FromDays( 1.0 );
|
||||
}
|
||||
|
||||
private void Warning_Callback()
|
||||
{
|
||||
World.Broadcast( 0x22, true, "The server is going down shortly." );
|
||||
}
|
||||
|
||||
private void Restart_Callback()
|
||||
{
|
||||
Core.Kill( true );
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( m_Restarting || !Enabled )
|
||||
return;
|
||||
|
||||
if ( DateTime.Now < m_RestartTime )
|
||||
return;
|
||||
|
||||
if ( WarningDelay > TimeSpan.Zero )
|
||||
{
|
||||
Warning_Callback();
|
||||
Timer.DelayCall( WarningDelay, WarningDelay, new TimerCallback( Warning_Callback ) );
|
||||
}
|
||||
|
||||
AutoSave.Save();
|
||||
|
||||
m_Restarting = true;
|
||||
|
||||
Timer.DelayCall( RestartDelay, new TimerCallback( Restart_Callback ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
187
Scripts/Misc/AutoSave.cs
Normal file
187
Scripts/Misc/AutoSave.cs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Server;
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class AutoSave : Timer
|
||||
{
|
||||
private static TimeSpan m_Delay = TimeSpan.FromMinutes( Server.Misc.Settings.SaveInterval() );
|
||||
private static TimeSpan m_Warning = TimeSpan.Zero;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
new AutoSave().Start();
|
||||
CommandSystem.Register( "SetSaves", AccessLevel.Administrator, new CommandEventHandler( SetSaves_OnCommand ) );
|
||||
}
|
||||
|
||||
private static bool m_SavesEnabled = true;
|
||||
|
||||
public static bool SavesEnabled
|
||||
{
|
||||
get{ return m_SavesEnabled; }
|
||||
set{ m_SavesEnabled = value; }
|
||||
}
|
||||
|
||||
[Usage( "SetSaves <true | false>" )]
|
||||
[Description( "Enables or disables automatic shard saving." )]
|
||||
public static void SetSaves_OnCommand( CommandEventArgs e )
|
||||
{
|
||||
if ( e.Length == 1 )
|
||||
{
|
||||
m_SavesEnabled = e.GetBoolean( 0 );
|
||||
e.Mobile.SendMessage( "Saves have been {0}.", m_SavesEnabled ? "enabled" : "disabled" );
|
||||
}
|
||||
else
|
||||
{
|
||||
e.Mobile.SendMessage( "Format: SetSaves <true | false>" );
|
||||
}
|
||||
}
|
||||
|
||||
public AutoSave() : base( m_Delay - m_Warning, m_Delay )
|
||||
{
|
||||
Priority = TimerPriority.OneMinute;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( !m_SavesEnabled || AutoRestart.Restarting )
|
||||
return;
|
||||
|
||||
if ( m_Warning == TimeSpan.Zero )
|
||||
{
|
||||
Save( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
int s = (int)m_Warning.TotalSeconds;
|
||||
int m = s / 60;
|
||||
s %= 60;
|
||||
|
||||
if ( m > 0 && s > 0 )
|
||||
World.Broadcast( 0x35, true, "The world will save in {0} minute{1} and {2} second{3}.", m, m != 1 ? "s" : "", s, s != 1 ? "s" : "" );
|
||||
else if ( m > 0 )
|
||||
World.Broadcast( 0x35, true, "The world will save in {0} minute{1}.", m, m != 1 ? "s" : "" );
|
||||
else
|
||||
World.Broadcast( 0x35, true, "The world will save in {0} second{1}.", s, s != 1 ? "s" : "" );
|
||||
|
||||
Timer.DelayCall( m_Warning, new TimerCallback( Save ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
AutoSave.Save( false );
|
||||
}
|
||||
|
||||
public static void Save( bool permitBackgroundWrite )
|
||||
{
|
||||
if ( AutoRestart.Restarting )
|
||||
return;
|
||||
|
||||
World.WaitForWriteCompletion();
|
||||
|
||||
try{ Backup(); }
|
||||
catch ( Exception e ) { Console.WriteLine("WARNING: Automatic backup FAILED: {0}", e); }
|
||||
|
||||
World.Save( true, permitBackgroundWrite );
|
||||
}
|
||||
|
||||
private static string[] m_Backups = new string[]
|
||||
{
|
||||
"Third Backup",
|
||||
"Second Backup",
|
||||
"Most Recent"
|
||||
};
|
||||
|
||||
private static void Backup()
|
||||
{
|
||||
if ( m_Backups.Length == 0 )
|
||||
return;
|
||||
|
||||
string root = Path.Combine( Core.BaseDirectory, "Backups/Automatic" );
|
||||
|
||||
if ( !Directory.Exists( root ) )
|
||||
Directory.CreateDirectory( root );
|
||||
|
||||
string[] existing = Directory.GetDirectories( root );
|
||||
|
||||
for ( int i = 0; i < m_Backups.Length; ++i )
|
||||
{
|
||||
DirectoryInfo dir = Match( existing, m_Backups[i] );
|
||||
|
||||
if ( dir == null )
|
||||
continue;
|
||||
|
||||
if ( i > 0 )
|
||||
{
|
||||
string timeStamp = FindTimeStamp( dir.Name );
|
||||
|
||||
if ( timeStamp != null )
|
||||
{
|
||||
try{ dir.MoveTo( FormatDirectory( root, m_Backups[i - 1], timeStamp ) ); }
|
||||
catch{}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try{ dir.Delete( true ); }
|
||||
catch{}
|
||||
}
|
||||
}
|
||||
|
||||
string saves = Path.Combine( Core.BaseDirectory, "Saves" );
|
||||
|
||||
if ( Directory.Exists( saves ) )
|
||||
Directory.Move( saves, FormatDirectory( root, m_Backups[m_Backups.Length - 1], GetTimeStamp() ) );
|
||||
}
|
||||
|
||||
private static DirectoryInfo Match( string[] paths, string match )
|
||||
{
|
||||
for ( int i = 0; i < paths.Length; ++i )
|
||||
{
|
||||
DirectoryInfo info = new DirectoryInfo( paths[i] );
|
||||
|
||||
if ( info.Name.StartsWith( match ) )
|
||||
return info;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string FormatDirectory( string root, string name, string timeStamp )
|
||||
{
|
||||
return Path.Combine( root, String.Format( "{0} ({1})", name, timeStamp ) );
|
||||
}
|
||||
|
||||
private static string FindTimeStamp( string input )
|
||||
{
|
||||
int start = input.IndexOf( '(' );
|
||||
|
||||
if ( start >= 0 )
|
||||
{
|
||||
int end = input.IndexOf( ')', ++start );
|
||||
|
||||
if ( end >= start )
|
||||
return input.Substring( start, end-start );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetTimeStamp()
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
return String.Format( "{0}-{1}-{2} {3}-{4:D2}-{5:D2}",
|
||||
now.Day,
|
||||
now.Month,
|
||||
now.Year,
|
||||
now.Hour,
|
||||
now.Minute,
|
||||
now.Second
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Scripts/Misc/Broadcasts.cs
Normal file
36
Scripts/Misc/Broadcasts.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Broadcasts
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Crashed += new CrashedEventHandler( EventSink_Crashed );
|
||||
EventSink.Shutdown += new ShutdownEventHandler( EventSink_Shutdown );
|
||||
}
|
||||
|
||||
public static void EventSink_Crashed( CrashedEventArgs e )
|
||||
{
|
||||
try
|
||||
{
|
||||
World.Broadcast( 0x35, true, "The server has crashed." );
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void EventSink_Shutdown( ShutdownEventArgs e )
|
||||
{
|
||||
try
|
||||
{
|
||||
World.Broadcast( 0x35, true, "The server has shut down." );
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
495
Scripts/Misc/CharacterCreation.cs
Normal file
495
Scripts/Misc/CharacterCreation.cs
Normal file
|
|
@ -0,0 +1,495 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Accounting;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class CharacterCreation
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
// Register our event handler
|
||||
EventSink.CharacterCreated += new CharacterCreatedEventHandler( EventSink_CharacterCreated );
|
||||
}
|
||||
|
||||
private static void AddBackpack( Mobile m )
|
||||
{
|
||||
Container pack = m.Backpack;
|
||||
|
||||
if ( pack == null )
|
||||
{
|
||||
pack = new Backpack();
|
||||
pack.Movable = false;
|
||||
|
||||
m.AddItem( pack );
|
||||
}
|
||||
|
||||
PackItem( new RedBook( "a book", m.Name, 20, true ) );
|
||||
PackItem( new Gold( Server.Misc.Settings.StartGold() ) );
|
||||
PackItem( new Dagger() );
|
||||
PackItem( new Candle() );
|
||||
}
|
||||
|
||||
private static void AddShirt( Mobile m )
|
||||
{
|
||||
switch ( Utility.Random( 5 ) )
|
||||
{
|
||||
case 0: EquipItem( new FancyShirt( Utility.RandomHue() ), true ); break;
|
||||
case 1: EquipItem( new Doublet( Utility.RandomHue() ), true ); break;
|
||||
case 2: EquipItem( new Shirt( Utility.RandomHue() ), true ); break;
|
||||
case 3: EquipItem( new Tunic( Utility.RandomHue() ), true ); break;
|
||||
case 4: EquipItem( new Surcoat( Utility.RandomHue() ), true ); break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddPants( Mobile m )
|
||||
{
|
||||
if ( m.Female )
|
||||
{
|
||||
switch ( Utility.Random( 4 ) )
|
||||
{
|
||||
case 0: EquipItem( new Skirt( Utility.RandomHue() ), true ); break;
|
||||
case 1: EquipItem( new Kilt( Utility.RandomHue() ), true ); break;
|
||||
case 2: EquipItem( new LongPants( Utility.RandomHue() ), true ); break;
|
||||
case 3: EquipItem( new ShortPants( Utility.RandomHue() ), true ); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( Utility.Random( 3 ) )
|
||||
{
|
||||
case 0: EquipItem( new LongPants( Utility.RandomHue() ), true ); break;
|
||||
case 1: EquipItem( new ShortPants( Utility.RandomHue() ), true ); break;
|
||||
case 2: EquipItem( new Kilt( Utility.RandomHue() ), true ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddShoes( Mobile m )
|
||||
{
|
||||
switch ( Utility.Random( 4 ) )
|
||||
{
|
||||
case 0: EquipItem( new Shoes( Utility.RandomNeutralHue() ), true ); break;
|
||||
case 1: EquipItem( new Boots( Utility.RandomNeutralHue() ), true ); break;
|
||||
case 2: EquipItem( new Sandals( Utility.RandomNeutralHue() ), true ); break;
|
||||
case 3: EquipItem( new ThighBoots( Utility.RandomNeutralHue() ), true ); break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddHat( Mobile m, int color )
|
||||
{
|
||||
switch ( Utility.Random( 7 ) )
|
||||
{
|
||||
case 0: EquipItem( new FloppyHat( Utility.RandomHue() ), true ); break;
|
||||
case 1: EquipItem( new Hood( color ), true ); break;
|
||||
case 2: EquipItem( new WideBrimHat( Utility.RandomHue() ), true ); break;
|
||||
case 3: EquipItem( new Cap( Utility.RandomHue() ), true ); break;
|
||||
case 4: EquipItem( new SkullCap( Utility.RandomHue() ), true ); break;
|
||||
case 5: EquipItem( new Bandana( Utility.RandomHue() ), true ); break;
|
||||
case 6: EquipItem( new FeatheredHat( Utility.RandomHue() ), true ); break;
|
||||
}
|
||||
}
|
||||
|
||||
private static Mobile CreateMobile( Account a )
|
||||
{
|
||||
if ( a.Count >= a.Limit )
|
||||
return null;
|
||||
|
||||
for ( int i = 0; i < a.Length; ++i )
|
||||
{
|
||||
if ( a[i] == null )
|
||||
return (a[i] = new PlayerMobile());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void EventSink_CharacterCreated( CharacterCreatedEventArgs args )
|
||||
{
|
||||
if ( !VerifyProfession( args.Profession ) )
|
||||
args.Profession = 0;
|
||||
|
||||
NetState state = args.State;
|
||||
|
||||
if ( state == null )
|
||||
return;
|
||||
|
||||
Mobile newChar = CreateMobile( args.Account as Account );
|
||||
|
||||
if ( newChar == null )
|
||||
{
|
||||
Console.WriteLine( "Login: {0}: Character creation failed, account full", state );
|
||||
return;
|
||||
}
|
||||
|
||||
args.Mobile = newChar;
|
||||
m_Mobile = newChar;
|
||||
|
||||
newChar.Player = true;
|
||||
newChar.StatCap = 200;
|
||||
newChar.Skills.Cap = 7000;
|
||||
newChar.AccessLevel = args.Account.AccessLevel;
|
||||
newChar.Female = args.Female;
|
||||
newChar.Race = Race.Human;
|
||||
newChar.Hue = newChar.Race.ClipSkinHue( args.Hue & 0x3FFF ) | 0x8000;
|
||||
newChar.Hunger = 20;
|
||||
newChar.Thirst = 20;
|
||||
|
||||
if ( newChar is PlayerMobile )
|
||||
{
|
||||
PlayerMobile pm = (PlayerMobile) newChar;
|
||||
|
||||
pm.Profession = args.Profession;
|
||||
}
|
||||
|
||||
SetName( newChar, args.Name );
|
||||
|
||||
AddBackpack( newChar );
|
||||
|
||||
SetStats( newChar, state, args.Str, args.Dex, args.Int, args.Profession );
|
||||
SetSkills( newChar, args.Skills, args.Profession );
|
||||
|
||||
newChar.HairItemID = args.HairID;
|
||||
newChar.HairHue = ClipHairHue( args.HairHue & 0x3FFF );
|
||||
newChar.FacialHairItemID = args.BeardID;
|
||||
newChar.FacialHairHue = ClipHairHue( args.BeardHue & 0x3FFF );
|
||||
|
||||
newChar.RecordHair = newChar.HairItemID;;
|
||||
newChar.RecordBeard = newChar.FacialHairItemID;;
|
||||
|
||||
AddShirt( newChar );
|
||||
AddPants( newChar );
|
||||
AddShoes( newChar );
|
||||
|
||||
int hatColor = 0;
|
||||
int robeColor = 0;
|
||||
|
||||
if ( Utility.RandomBool() )
|
||||
{
|
||||
hatColor = Utility.RandomHue();
|
||||
EquipItem( new Cloak( hatColor ), true );
|
||||
}
|
||||
if ( Utility.RandomBool() )
|
||||
{
|
||||
robeColor = Utility.RandomHue();
|
||||
EquipItem( new Robe( robeColor ), true );
|
||||
if ( hatColor > 0 && Utility.RandomBool() ){ hatColor = robeColor; }
|
||||
else if ( hatColor == 0 ){ hatColor = robeColor; }
|
||||
}
|
||||
if ( Utility.RandomBool() ){ AddHat( newChar, hatColor ); }
|
||||
|
||||
CityInfo city = GetStartLocation( args );
|
||||
|
||||
newChar.MoveToWorld( city.Location, city.Map );
|
||||
|
||||
Console.WriteLine( "Login: {0}: New character being created (account={1})", state, args.Account.Username );
|
||||
Console.WriteLine( " - Character: {0} (serial={1})", newChar.Name, newChar.Serial );
|
||||
Console.WriteLine( " - Started: {0} {1} in {2}", city.City, city.Location, city.Map.ToString() );
|
||||
|
||||
new WelcomeTimer( newChar ).Start();
|
||||
}
|
||||
|
||||
public static int ClipHairHue( int hue )
|
||||
{
|
||||
if( hue < 1102 )
|
||||
return 1102;
|
||||
else if( hue > 1149 )
|
||||
return 1149;
|
||||
else
|
||||
return hue;
|
||||
}
|
||||
|
||||
public static bool VerifyProfession( int profession )
|
||||
{
|
||||
if ( profession < 8 )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private class BadStartMessage : Timer
|
||||
{
|
||||
Mobile m_Mobile;
|
||||
int m_Message;
|
||||
public BadStartMessage( Mobile m, int message ) : base( TimeSpan.FromSeconds ( 3.5 ) )
|
||||
{
|
||||
m_Mobile = m;
|
||||
m_Message = message;
|
||||
this.Start();
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Mobile.SendLocalizedMessage( m_Message );
|
||||
}
|
||||
}
|
||||
|
||||
private static CityInfo GetStartLocation( CharacterCreatedEventArgs args )
|
||||
{
|
||||
return args.City;
|
||||
}
|
||||
|
||||
private static void FixStats( ref int str, ref int dex, ref int intel, int max )
|
||||
{
|
||||
int vMax = max - 30;
|
||||
|
||||
int vStr = str - 10;
|
||||
int vDex = dex - 10;
|
||||
int vInt = intel - 10;
|
||||
|
||||
if ( vStr < 0 )
|
||||
vStr = 0;
|
||||
|
||||
if ( vDex < 0 )
|
||||
vDex = 0;
|
||||
|
||||
if ( vInt < 0 )
|
||||
vInt = 0;
|
||||
|
||||
int total = vStr + vDex + vInt;
|
||||
|
||||
if ( total == 0 || total == vMax )
|
||||
return;
|
||||
|
||||
double scalar = vMax / (double)total;
|
||||
|
||||
vStr = (int)(vStr * scalar);
|
||||
vDex = (int)(vDex * scalar);
|
||||
vInt = (int)(vInt * scalar);
|
||||
|
||||
FixStat( ref vStr, (vStr + vDex + vInt) - vMax, vMax );
|
||||
FixStat( ref vDex, (vStr + vDex + vInt) - vMax, vMax );
|
||||
FixStat( ref vInt, (vStr + vDex + vInt) - vMax, vMax );
|
||||
|
||||
str = vStr + 10;
|
||||
dex = vDex + 10;
|
||||
intel = vInt + 10;
|
||||
}
|
||||
|
||||
private static void FixStat( ref int stat, int diff, int max )
|
||||
{
|
||||
stat += diff;
|
||||
|
||||
if ( stat < 0 )
|
||||
stat = 0;
|
||||
else if ( stat > max )
|
||||
stat = max;
|
||||
}
|
||||
|
||||
private static void SetStats( Mobile m, NetState state, int str, int dex, int intel, int prof )
|
||||
{
|
||||
int max = state.NewCharacterCreation ? 90 : 80;
|
||||
|
||||
FixStats( ref str, ref dex, ref intel, max );
|
||||
|
||||
if ( str < 10 || str > 60 || dex < 10 || dex > 60 || intel < 10 || intel > 60 || (str + dex + intel) != max )
|
||||
{
|
||||
str = 10;
|
||||
dex = 10;
|
||||
intel = 10;
|
||||
}
|
||||
|
||||
if ( prof > 0 )
|
||||
{
|
||||
switch ( prof )
|
||||
{
|
||||
case 1: // Swordsman
|
||||
{
|
||||
m.InitStats( 45, 25, 10 ); break;
|
||||
}
|
||||
case 2: // Magician
|
||||
{
|
||||
m.InitStats( 15, 20, 45 ); break;
|
||||
}
|
||||
case 3: // Thief
|
||||
{
|
||||
m.InitStats( 20, 45, 15 ); break;
|
||||
}
|
||||
case 4: // Fencer
|
||||
{
|
||||
m.InitStats( 30, 40, 10 ); break;
|
||||
}
|
||||
case 5: // Mace Fighter
|
||||
{
|
||||
m.InitStats( 45, 25, 10 ); break;
|
||||
}
|
||||
case 6: // Archer
|
||||
{
|
||||
m.InitStats( 25, 45, 10 ); break;
|
||||
}
|
||||
case 7: // Bard
|
||||
{
|
||||
m.InitStats( 25, 35, 20 ); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
m.InitStats( str, dex, intel );
|
||||
}
|
||||
|
||||
private static void SetName( Mobile m, string name )
|
||||
{
|
||||
name = name.Trim();
|
||||
|
||||
if ( !NameVerification.Validate( name, 2, 16, true, false, true, 1, NameVerification.SpaceDashPeriodQuote ) )
|
||||
name = "Generic Player";
|
||||
|
||||
m.Name = name;
|
||||
}
|
||||
|
||||
private static bool ValidSkills( SkillNameValue[] skills )
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
for ( int i = 0; i < skills.Length; ++i )
|
||||
{
|
||||
if ( skills[i].Value < 0 || skills[i].Value > 50 )
|
||||
return false;
|
||||
|
||||
total += skills[i].Value;
|
||||
|
||||
for ( int j = i + 1; j < skills.Length; ++j )
|
||||
{
|
||||
if ( skills[j].Value > 0 && skills[j].Name == skills[i].Name )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return ( total == 100 || total == 120 );
|
||||
}
|
||||
|
||||
private static Mobile m_Mobile;
|
||||
|
||||
private static void SetSkills( Mobile m, SkillNameValue[] skills, int prof )
|
||||
{
|
||||
switch ( prof )
|
||||
{
|
||||
case 1: // Swordsman
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Healing, 30 ),
|
||||
new SkillNameValue( SkillName.Swords, 40 ),
|
||||
new SkillNameValue( SkillName.Tactics, 30 )
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Magician
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Magery, 50 ),
|
||||
new SkillNameValue( SkillName.Meditation, 50 )
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Thief
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Hiding, 50 ),
|
||||
new SkillNameValue( SkillName.Stealing, 50 )
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // Fencer
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Healing, 30 ),
|
||||
new SkillNameValue( SkillName.Fencing, 40 ),
|
||||
new SkillNameValue( SkillName.Tactics, 30 )
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: // Mace Fighter
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Healing, 30 ),
|
||||
new SkillNameValue( SkillName.Bludgeoning, 40 ),
|
||||
new SkillNameValue( SkillName.Tactics, 30 )
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: // Archer
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Archery, 50 ),
|
||||
new SkillNameValue( SkillName.Tactics, 50 )
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 7: // Bard
|
||||
{
|
||||
skills = new SkillNameValue[]
|
||||
{
|
||||
new SkillNameValue( SkillName.Musicianship, 40 ),
|
||||
new SkillNameValue( SkillName.Discordance, 30 ),
|
||||
new SkillNameValue( SkillName.Peacemaking, 30 )
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if ( !ValidSkills( skills ) )
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < skills.Length; ++i )
|
||||
{
|
||||
SkillNameValue snv = skills[i];
|
||||
|
||||
if ( snv.Value > 0 )
|
||||
{
|
||||
Skill skill = m.Skills[snv.Name];
|
||||
|
||||
if ( skill != null )
|
||||
{
|
||||
skill.BaseFixedPoint = snv.Value * 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void EquipItem( Item item )
|
||||
{
|
||||
EquipItem( item, false );
|
||||
}
|
||||
|
||||
private static void EquipItem( Item item, bool mustEquip )
|
||||
{
|
||||
if ( m_Mobile != null && m_Mobile.EquipItem( item ) )
|
||||
return;
|
||||
|
||||
Container pack = m_Mobile.Backpack;
|
||||
|
||||
if ( !mustEquip && pack != null )
|
||||
pack.DropItem( item );
|
||||
else
|
||||
item.Delete();
|
||||
}
|
||||
|
||||
private static void PackItem( Item item )
|
||||
{
|
||||
Container pack = m_Mobile.Backpack;
|
||||
|
||||
if ( pack != null )
|
||||
pack.DropItem( item );
|
||||
else
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Scripts/Misc/Cleanup.cs
Normal file
150
Scripts/Misc/Cleanup.cs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Multis;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Cleanup
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 2.5 ), new TimerCallback( Run ) );
|
||||
}
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
List<Item> items = new List<Item>();
|
||||
List<Item> validItems = new List<Item>();
|
||||
List<Mobile> hairCleanup = new List<Mobile>();
|
||||
|
||||
int boxes = 0;
|
||||
|
||||
foreach ( Item item in World.Items.Values )
|
||||
{
|
||||
if ( item.Map == null )
|
||||
{
|
||||
items.Add( item );
|
||||
continue;
|
||||
}
|
||||
else if ( item is BaseHouse )
|
||||
{
|
||||
BaseHouse house = (BaseHouse)item;
|
||||
|
||||
foreach ( RelocatedEntity relEntity in house.RelocatedEntities )
|
||||
{
|
||||
if ( relEntity.Entity is Item )
|
||||
validItems.Add( (Item)relEntity.Entity );
|
||||
}
|
||||
|
||||
foreach ( VendorInventory inventory in house.VendorInventories )
|
||||
{
|
||||
foreach ( Item subItem in inventory.Items )
|
||||
validItems.Add( subItem );
|
||||
}
|
||||
}
|
||||
else if ( item is InnBox )
|
||||
{
|
||||
InnBox box = (InnBox)item;
|
||||
Mobile owner = box.Owner;
|
||||
|
||||
if ( owner == null )
|
||||
{
|
||||
items.Add( box );
|
||||
++boxes;
|
||||
}
|
||||
else if ( box.Items.Count == 0 )
|
||||
{
|
||||
items.Add( box );
|
||||
++boxes;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
else if ( (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair) )
|
||||
{
|
||||
object rootParent = item.RootParent;
|
||||
|
||||
if ( rootParent is Mobile )
|
||||
{
|
||||
Mobile rootMobile = (Mobile)rootParent;
|
||||
if ( item.Parent != rootMobile && rootMobile.AccessLevel == AccessLevel.Player )
|
||||
{
|
||||
items.Add( item );
|
||||
continue;
|
||||
}
|
||||
else if( item.Parent == rootMobile )
|
||||
{
|
||||
hairCleanup.Add( rootMobile );
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( item.Parent != null || item.Map != Map.Internal || item.HeldBy != null )
|
||||
continue;
|
||||
|
||||
if ( item.Location != Point3D.Zero )
|
||||
continue;
|
||||
|
||||
if ( !IsBuggable( item ) )
|
||||
continue;
|
||||
|
||||
items.Add( item );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < validItems.Count; ++i )
|
||||
items.Remove( validItems[i] );
|
||||
|
||||
if ( items.Count > 0 )
|
||||
{
|
||||
for ( int i = 0; i < items.Count; ++i )
|
||||
items[i].Delete();
|
||||
}
|
||||
|
||||
if ( hairCleanup.Count > 0 )
|
||||
{
|
||||
for ( int i = 0; i < hairCleanup.Count; i++ )
|
||||
hairCleanup[i].ConvertHair();
|
||||
}
|
||||
|
||||
ArrayList cleanup = new ArrayList();
|
||||
foreach ( Mobile creature in World.Mobiles.Values )
|
||||
{
|
||||
if ( creature is BaseCreature && creature.Map == Map.Internal )
|
||||
{
|
||||
if (((BaseCreature)creature).IsStabled){} // DO NOTHING
|
||||
else if ( creature is BaseMount && ((BaseMount)creature).Rider != null ){} // DO NOTHING
|
||||
else { cleanup.Add( creature ); }
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i < cleanup.Count; ++i )
|
||||
{
|
||||
Mobile creature = ( Mobile )cleanup[ i ];
|
||||
creature.Delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsBuggable( Item item )
|
||||
{
|
||||
if ( item is Fists )
|
||||
return false;
|
||||
|
||||
if ( item is Multis.BaseBoat
|
||||
|| item is Fish || item is BigFish
|
||||
|| item is BasePotion || item is Food || item is CookableFood
|
||||
|| item is SpecialFishingNet || item is BaseMagicFish
|
||||
|| item is Shoes || item is Sandals
|
||||
|| item is Boots || item is ThighBoots
|
||||
|| item is TreasureMap || item is MessageInABottle
|
||||
|| item is BaseArmor || item is BaseWeapon
|
||||
|| item is BaseClothing)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
221
Scripts/Misc/ClientVerification.cs
Normal file
221
Scripts/Misc/ClientVerification.cs
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
using System;
|
||||
using Server;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Server.Network;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class ClientVerification
|
||||
{
|
||||
private enum OldClientResponse
|
||||
{
|
||||
Ignore,
|
||||
Warn,
|
||||
Annoy,
|
||||
LenientKick,
|
||||
Kick
|
||||
}
|
||||
|
||||
private static bool m_DetectClientRequirement = true;
|
||||
private static OldClientResponse m_OldClientResponse = OldClientResponse.LenientKick;
|
||||
|
||||
private static ClientVersion m_Required;
|
||||
private static bool m_AllowRegular = true, m_AllowUOTD = true, m_AllowGod = true;
|
||||
|
||||
private static TimeSpan m_AgeLeniency = TimeSpan.FromDays( 10 );
|
||||
private static TimeSpan m_GameTimeLeniency = TimeSpan.FromHours( 25 );
|
||||
|
||||
private static TimeSpan m_KickDelay = TimeSpan.FromSeconds( 20.0 );
|
||||
|
||||
public static ClientVersion Required
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Required;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_Required = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool AllowRegular
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_AllowRegular;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_AllowRegular = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool AllowUOTD
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_AllowUOTD;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_AllowUOTD = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool AllowGod
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_AllowGod;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_AllowGod = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static TimeSpan KickDelay
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_KickDelay;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_KickDelay = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.ClientVersionReceived += new ClientVersionReceivedHandler( EventSink_ClientVersionReceived );
|
||||
|
||||
//ClientVersion.Required = null;
|
||||
//Required = new ClientVersion( "6.0.0.0" );
|
||||
|
||||
if( m_DetectClientRequirement )
|
||||
{
|
||||
string path = Core.FindDataFile( "client.exe" );
|
||||
|
||||
if( File.Exists( path ) )
|
||||
{
|
||||
FileVersionInfo info = FileVersionInfo.GetVersionInfo( path );
|
||||
|
||||
if ( info.FileMajorPart != 0 || info.FileMinorPart != 0 || info.FileBuildPart != 0 || info.FilePrivatePart != 0 )
|
||||
{
|
||||
Required = new ClientVersion( info.FileMajorPart, info.FileMinorPart, info.FileBuildPart, info.FilePrivatePart );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( Required != null )
|
||||
{
|
||||
Utility.PushColor( ConsoleColor.White );
|
||||
Console.WriteLine( "Restricting client version to {0}. Action to be taken: {1}", Required, m_OldClientResponse );
|
||||
Utility.PopColor();
|
||||
}
|
||||
}
|
||||
|
||||
private static void EventSink_ClientVersionReceived( ClientVersionReceivedArgs e )
|
||||
{
|
||||
string kickMessage = null;
|
||||
NetState state = e.State;
|
||||
ClientVersion version = e.Version;
|
||||
|
||||
if ( state.Mobile.AccessLevel > AccessLevel.Player )
|
||||
return;
|
||||
|
||||
if( Required != null && version < Required && ( m_OldClientResponse == OldClientResponse.Kick ||( m_OldClientResponse == OldClientResponse.LenientKick && (DateTime.Now - state.Mobile.CreationTime) > m_AgeLeniency && state.Mobile is PlayerMobile && ((PlayerMobile)state.Mobile).GameTime > m_GameTimeLeniency )))
|
||||
{
|
||||
kickMessage = String.Format( "This server requires your client version be at least {0}.", Required );
|
||||
}
|
||||
else if( !AllowGod || !AllowRegular || !AllowUOTD )
|
||||
{
|
||||
if( !AllowGod && version.Type == ClientType.God )
|
||||
kickMessage = "This server does not allow god clients to connect.";
|
||||
else if( !AllowRegular && version.Type == ClientType.Regular )
|
||||
kickMessage = "This server does not allow regular clients to connect.";
|
||||
else if( !AllowUOTD && state.IsUOTDClient )
|
||||
kickMessage = "This server does not allow UO:TD clients to connect.";
|
||||
|
||||
if( !AllowGod && !AllowRegular && !AllowUOTD )
|
||||
{
|
||||
kickMessage = "This server does not allow any clients to connect.";
|
||||
}
|
||||
else if( AllowGod && !AllowRegular && !AllowUOTD && version.Type != ClientType.God )
|
||||
{
|
||||
kickMessage = "This server requires you to use the god client.";
|
||||
}
|
||||
else if( kickMessage != null )
|
||||
{
|
||||
if( AllowRegular && AllowUOTD )
|
||||
kickMessage += " You can use regular or UO:TD clients.";
|
||||
else if( AllowRegular )
|
||||
kickMessage += " You can use regular clients.";
|
||||
else if( AllowUOTD )
|
||||
kickMessage += " You can use UO:TD clients.";
|
||||
}
|
||||
}
|
||||
|
||||
if( kickMessage != null )
|
||||
{
|
||||
state.Mobile.SendMessage( 0x22, kickMessage );
|
||||
state.Mobile.SendMessage( 0x22, "You will be disconnected in {0} seconds.", KickDelay.TotalSeconds );
|
||||
|
||||
Timer.DelayCall( KickDelay, delegate
|
||||
{
|
||||
if( state.Socket != null )
|
||||
{
|
||||
Console.WriteLine( "Client: {0}: Disconnecting, bad version", state );
|
||||
state.Dispose();
|
||||
}
|
||||
} );
|
||||
}
|
||||
else if( Required != null && version < Required )
|
||||
{
|
||||
switch( m_OldClientResponse )
|
||||
{
|
||||
case OldClientResponse.Warn:
|
||||
{
|
||||
state.Mobile.SendMessage( 0x22, "Your client is out of date. Please update your client.", Required );
|
||||
state.Mobile.SendMessage( 0x22, "This server reccomends that your client version be at least {0}.", Required );
|
||||
break;
|
||||
}
|
||||
case OldClientResponse.LenientKick:
|
||||
case OldClientResponse.Annoy:
|
||||
{
|
||||
SendAnnoyGump( state.Mobile );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SendAnnoyGump( Mobile m )
|
||||
{
|
||||
if( m.NetState != null && m.NetState.Version < Required )
|
||||
{
|
||||
Gump g = new WarningGump( 1060637, 30720, String.Format( "Your client is out of date. Please update your client.<br>This server recommends that your client version be at least {0}.<br> <br>You are currently using version {1}.<br> <br>To patch, run UOPatch.exe inside your Ultima Online folder.", Required, m.NetState.Version ), 0xFFC000, 480, 360,
|
||||
delegate( Mobile mob, bool selection, object o )
|
||||
{
|
||||
m.SendMessage( "You will be reminded of this again." );
|
||||
|
||||
if ( m_OldClientResponse == OldClientResponse.LenientKick )
|
||||
m.SendMessage( "Old clients will be kicked after {0} days of character age and {1} hours of play time", m_AgeLeniency, m_GameTimeLeniency );
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromMinutes( Utility.Random( 5, 15 ) ), delegate { SendAnnoyGump( m ); } );
|
||||
}, null, false );
|
||||
|
||||
g.Dragable = false;
|
||||
g.Closable = false;
|
||||
g.Resizable = false;
|
||||
|
||||
m.SendGump( g );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
263
Scripts/Misc/CrashGuard.cs
Normal file
263
Scripts/Misc/CrashGuard.cs
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Mail;
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class CrashGuard
|
||||
{
|
||||
private static bool Enabled = true;
|
||||
private static bool SaveBackup = true;
|
||||
private static bool RestartServer = true;
|
||||
private static bool GenerateReport = true;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if ( Enabled ) // If enabled, register our crash event handler
|
||||
EventSink.Crashed += new CrashedEventHandler( CrashGuard_OnCrash );
|
||||
}
|
||||
|
||||
public static void CrashGuard_OnCrash( CrashedEventArgs e )
|
||||
{
|
||||
if ( GenerateReport )
|
||||
GenerateCrashReport( e );
|
||||
|
||||
World.WaitForWriteCompletion();
|
||||
|
||||
if ( SaveBackup )
|
||||
Backup();
|
||||
|
||||
|
||||
/*if ( Core.Service )
|
||||
e.Close = true;
|
||||
else */ if ( RestartServer )
|
||||
Restart( e );
|
||||
}
|
||||
|
||||
private static void SendEmail( string filePath )
|
||||
{
|
||||
Console.Write( "Crash: Sending email..." );
|
||||
|
||||
MailMessage message = new MailMessage( "RunUO", Email.CrashAddresses );
|
||||
|
||||
message.Subject = "Automated RunUO Crash Report";
|
||||
|
||||
message.Body = "Automated RunUO Crash Report. See attachment for details.";
|
||||
|
||||
message.Attachments.Add( new Attachment( filePath ) );
|
||||
|
||||
if ( Email.Send( message ) )
|
||||
Console.WriteLine( "done" );
|
||||
else
|
||||
Console.WriteLine( "failed" );
|
||||
}
|
||||
|
||||
private static string GetRoot()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Path.GetDirectoryName( Environment.GetCommandLineArgs()[0] );
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static string Combine( string path1, string path2 )
|
||||
{
|
||||
if ( path1.Length == 0 )
|
||||
return path2;
|
||||
|
||||
return Path.Combine( path1, path2 );
|
||||
}
|
||||
|
||||
private static void Restart( CrashedEventArgs e )
|
||||
{
|
||||
string root = GetRoot();
|
||||
|
||||
Console.Write( "Crash: Restarting..." );
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start( Core.ExePath, Core.Arguments );
|
||||
Console.WriteLine( "done" );
|
||||
|
||||
e.Close = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine( "failed" );
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateDirectory( string path )
|
||||
{
|
||||
if ( !Directory.Exists( path ) )
|
||||
Directory.CreateDirectory( path );
|
||||
}
|
||||
|
||||
private static void CreateDirectory( string path1, string path2 )
|
||||
{
|
||||
CreateDirectory( Combine( path1, path2 ) );
|
||||
}
|
||||
|
||||
private static void CopyFile( string rootOrigin, string rootBackup, string path )
|
||||
{
|
||||
string originPath = Combine( rootOrigin, path );
|
||||
string backupPath = Combine( rootBackup, path );
|
||||
|
||||
try
|
||||
{
|
||||
if ( File.Exists( originPath ) )
|
||||
File.Copy( originPath, backupPath );
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static void Backup()
|
||||
{
|
||||
Console.Write( "Crash: Backing up..." );
|
||||
|
||||
try
|
||||
{
|
||||
string timeStamp = GetTimeStamp();
|
||||
|
||||
string root = GetRoot();
|
||||
string rootBackup = Combine( root, String.Format( "Backups/Crashed/{0}/", timeStamp ) );
|
||||
string rootOrigin = Combine( root, String.Format( "Saves/" ) );
|
||||
|
||||
// Create new directories
|
||||
CreateDirectory( rootBackup );
|
||||
CreateDirectory( rootBackup, "Accounts/" );
|
||||
CreateDirectory( rootBackup, "Items/" );
|
||||
CreateDirectory( rootBackup, "Mobiles/" );
|
||||
CreateDirectory( rootBackup, "Guilds/" );
|
||||
CreateDirectory( rootBackup, "Regions/" );
|
||||
|
||||
// Copy files
|
||||
CopyFile( rootOrigin, rootBackup, "Accounts/Accounts.xml" );
|
||||
|
||||
CopyFile( rootOrigin, rootBackup, "Items/Items.bin" );
|
||||
CopyFile( rootOrigin, rootBackup, "Items/Items.idx" );
|
||||
CopyFile( rootOrigin, rootBackup, "Items/Items.tdb" );
|
||||
|
||||
CopyFile( rootOrigin, rootBackup, "Mobiles/Mobiles.bin" );
|
||||
CopyFile( rootOrigin, rootBackup, "Mobiles/Mobiles.idx" );
|
||||
CopyFile( rootOrigin, rootBackup, "Mobiles/Mobiles.tdb" );
|
||||
|
||||
CopyFile( rootOrigin, rootBackup, "Guilds/Guilds.bin" );
|
||||
CopyFile( rootOrigin, rootBackup, "Guilds/Guilds.idx" );
|
||||
|
||||
CopyFile( rootOrigin, rootBackup, "Regions/Regions.bin" );
|
||||
CopyFile( rootOrigin, rootBackup, "Regions/Regions.idx" );
|
||||
|
||||
Console.WriteLine( "done" );
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine( "failed" );
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateCrashReport( CrashedEventArgs e )
|
||||
{
|
||||
Console.Write( "Crash: Generating report..." );
|
||||
|
||||
try
|
||||
{
|
||||
string timeStamp = GetTimeStamp();
|
||||
string fileName = String.Format( "Crash {0}.log", timeStamp );
|
||||
|
||||
string root = GetRoot();
|
||||
string filePath = Combine( root, fileName );
|
||||
|
||||
using ( StreamWriter op = new StreamWriter( filePath ) )
|
||||
{
|
||||
Version ver = Core.Assembly.GetName().Version;
|
||||
|
||||
op.WriteLine( "Server Crash Report" );
|
||||
op.WriteLine( "===================" );
|
||||
op.WriteLine();
|
||||
op.WriteLine( "RunUO Version {0}.{1}, Build {2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision );
|
||||
op.WriteLine( "Operating System: {0}", Environment.OSVersion );
|
||||
op.WriteLine( ".NET Framework: {0}", Environment.Version );
|
||||
op.WriteLine( "Time: {0}", DateTime.Now );
|
||||
|
||||
try { op.WriteLine( "Mobiles: {0}", World.Mobiles.Count ); }
|
||||
catch {}
|
||||
|
||||
try { op.WriteLine( "Items: {0}", World.Items.Count ); }
|
||||
catch {}
|
||||
|
||||
op.WriteLine( "Exception:" );
|
||||
op.WriteLine( e.Exception );
|
||||
op.WriteLine();
|
||||
|
||||
op.WriteLine( "Clients:" );
|
||||
|
||||
try
|
||||
{
|
||||
List<NetState> states = NetState.Instances;
|
||||
|
||||
op.WriteLine( "- Count: {0}", states.Count );
|
||||
|
||||
for ( int i = 0; i < states.Count; ++i )
|
||||
{
|
||||
NetState state = states[i];
|
||||
|
||||
op.Write( "+ {0}:", state );
|
||||
|
||||
Account a = state.Account as Account;
|
||||
|
||||
if ( a != null )
|
||||
op.Write( " (account = {0})", a.Username );
|
||||
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
if ( m != null )
|
||||
op.Write( " (mobile = 0x{0:X} '{1}')", m.Serial.Value, m.Name );
|
||||
|
||||
op.WriteLine();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
op.WriteLine( "- Failed" );
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine( "done" );
|
||||
|
||||
if ( Email.CrashAddresses != null )
|
||||
SendEmail( filePath );
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine( "failed" );
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetTimeStamp()
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
|
||||
return String.Format( "{0}-{1}-{2}-{3}-{4}-{5}",
|
||||
now.Day,
|
||||
now.Month,
|
||||
now.Year,
|
||||
now.Hour,
|
||||
now.Minute,
|
||||
now.Second
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Scripts/Misc/DataPath.cs
Normal file
64
Scripts/Misc/DataPath.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.Win32;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class DataPath
|
||||
{
|
||||
private static string CustomPath = "Data/Files";
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
if ( CustomPath != null )
|
||||
Core.DataDirectories.Add( CustomPath );
|
||||
|
||||
if ( Core.DataDirectories.Count == 0 && !Core.Service )
|
||||
{
|
||||
Console.WriteLine( "Enter the Ultima Online directory:" );
|
||||
Console.Write( "> " );
|
||||
|
||||
Core.DataDirectories.Add( Console.ReadLine() );
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPath( string subName, string keyName )
|
||||
{
|
||||
try
|
||||
{
|
||||
string keyString;
|
||||
|
||||
if( Core.Is64Bit )
|
||||
keyString = @"SOFTWARE\Wow6432Node\{0}";
|
||||
else
|
||||
keyString = @"SOFTWARE\{0}";
|
||||
|
||||
using( RegistryKey key = Registry.LocalMachine.OpenSubKey( String.Format( keyString, subName ) ) )
|
||||
{
|
||||
if( key == null )
|
||||
return null;
|
||||
|
||||
string v = key.GetValue( keyName ) as string;
|
||||
|
||||
if( String.IsNullOrEmpty( v ) )
|
||||
return null;
|
||||
|
||||
if ( keyName == "InstallDir" )
|
||||
v = v + @"\";
|
||||
|
||||
v = Path.GetDirectoryName( v );
|
||||
|
||||
if ( String.IsNullOrEmpty( v ) )
|
||||
return null;
|
||||
|
||||
return v;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Scripts/Misc/DispellableAttribute.cs
Normal file
10
Scripts/Misc/DispellableAttribute.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
[AttributeUsage( AttributeTargets.Class )]
|
||||
public class DispellableAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
10
Scripts/Misc/DispellableFieldAttribute.cs
Normal file
10
Scripts/Misc/DispellableFieldAttribute.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
[AttributeUsage( AttributeTargets.Class )]
|
||||
public class DispellableFieldAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
78
Scripts/Misc/Email.cs
Normal file
78
Scripts/Misc/Email.cs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.Net.Mail;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Email
|
||||
{
|
||||
/* In order to support emailing, fill in EmailServer:
|
||||
* Example:
|
||||
* public static readonly string EmailServer = "mail.domain.com";
|
||||
*
|
||||
* If you want to add crash reporting emailing, fill in CrashAddresses:
|
||||
* Example:
|
||||
* public static readonly string CrashAddresses = "first@email.here;second@email.here;third@email.here";
|
||||
*
|
||||
* If you want to add speech log page emailing, fill in SpeechLogPageAddresses:
|
||||
* Example:
|
||||
* public static readonly string SpeechLogPageAddresses = "first@email.here;second@email.here;third@email.here";
|
||||
*/
|
||||
|
||||
public static readonly string EmailServer = null;
|
||||
|
||||
public static readonly string CrashAddresses = null;
|
||||
public static readonly string SpeechLogPageAddresses = null;
|
||||
|
||||
private static Regex _pattern = new Regex( @"^[a-z0-9.+_-]+@([a-z0-9-]+.)+[a-z]+$", RegexOptions.IgnoreCase );
|
||||
|
||||
public static bool IsValid( string address )
|
||||
{
|
||||
if ( address == null || address.Length > 320 )
|
||||
return false;
|
||||
|
||||
return _pattern.IsMatch( address );
|
||||
}
|
||||
|
||||
private static SmtpClient _Client;
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
if ( EmailServer != null )
|
||||
_Client = new SmtpClient( EmailServer );
|
||||
}
|
||||
|
||||
public static bool Send( MailMessage message )
|
||||
{
|
||||
try
|
||||
{
|
||||
lock ( _Client ) {
|
||||
_Client.Send( message );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AsyncSend( MailMessage message )
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem( new WaitCallback( SendCallback ), message );
|
||||
}
|
||||
|
||||
private static void SendCallback( object state )
|
||||
{
|
||||
MailMessage message = (MailMessage) state;
|
||||
|
||||
if ( Send( message ) )
|
||||
Console.WriteLine( "Sent e-mail '{0}' to '{1}'.", message.Subject, message.To );
|
||||
else
|
||||
Console.WriteLine( "Failure sending e-mail '{0}' to '{1}'.", message.Subject, message.To );
|
||||
}
|
||||
}
|
||||
}
|
||||
740
Scripts/Misc/Emitter.cs
Normal file
740
Scripts/Misc/Emitter.cs
Normal file
|
|
@ -0,0 +1,740 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using Emit = System.Reflection.Emit;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class AssemblyEmitter
|
||||
{
|
||||
private string m_AssemblyName;
|
||||
|
||||
private AppDomain m_AppDomain;
|
||||
private AssemblyBuilder m_AssemblyBuilder;
|
||||
private ModuleBuilder m_ModuleBuilder;
|
||||
|
||||
public AssemblyEmitter( string assemblyName, bool canSave )
|
||||
{
|
||||
m_AssemblyName = assemblyName;
|
||||
|
||||
m_AppDomain = AppDomain.CurrentDomain;
|
||||
|
||||
m_AssemblyBuilder = m_AppDomain.DefineDynamicAssembly(
|
||||
new AssemblyName( assemblyName ),
|
||||
canSave ? AssemblyBuilderAccess.RunAndSave : AssemblyBuilderAccess.Run
|
||||
);
|
||||
|
||||
if ( canSave )
|
||||
{
|
||||
m_ModuleBuilder = m_AssemblyBuilder.DefineDynamicModule(
|
||||
assemblyName,
|
||||
String.Format( "{0}.dll", assemblyName.ToLower() ),
|
||||
false
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ModuleBuilder = m_AssemblyBuilder.DefineDynamicModule(
|
||||
assemblyName,
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public TypeBuilder DefineType( string typeName, TypeAttributes attrs, Type parentType )
|
||||
{
|
||||
return m_ModuleBuilder.DefineType( typeName, attrs, parentType );
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
m_AssemblyBuilder.Save(
|
||||
String.Format( "{0}.dll", m_AssemblyName.ToLower() )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodEmitter
|
||||
{
|
||||
private TypeBuilder m_TypeBuilder;
|
||||
|
||||
private MethodBuilder m_Builder;
|
||||
private ILGenerator m_Generator;
|
||||
|
||||
private Type[] m_ArgumentTypes;
|
||||
|
||||
public TypeBuilder Type
|
||||
{
|
||||
get { return m_TypeBuilder; }
|
||||
}
|
||||
|
||||
public ILGenerator Generator
|
||||
{
|
||||
get { return m_Generator; }
|
||||
}
|
||||
|
||||
private class CallInfo
|
||||
{
|
||||
public Type type;
|
||||
public MethodInfo method;
|
||||
|
||||
public int index;
|
||||
public ParameterInfo[] parms;
|
||||
|
||||
public CallInfo( Type type, MethodInfo method )
|
||||
{
|
||||
this.type = type;
|
||||
this.method = method;
|
||||
|
||||
this.parms = method.GetParameters();
|
||||
}
|
||||
}
|
||||
|
||||
private Stack<Type> m_Stack;
|
||||
private Stack<CallInfo> m_Calls;
|
||||
|
||||
private Dictionary<Type, Queue<LocalBuilder>> m_Temps;
|
||||
|
||||
public MethodBuilder Method
|
||||
{
|
||||
get { return m_Builder; }
|
||||
}
|
||||
|
||||
public MethodEmitter( TypeBuilder typeBuilder )
|
||||
{
|
||||
m_TypeBuilder = typeBuilder;
|
||||
|
||||
m_Temps = new Dictionary<Type, Queue<LocalBuilder>>();
|
||||
|
||||
m_Stack = new Stack<Type>();
|
||||
m_Calls = new Stack<CallInfo>();
|
||||
}
|
||||
|
||||
public void Define( string name, MethodAttributes attr, Type returnType, Type[] parms )
|
||||
{
|
||||
m_Builder = m_TypeBuilder.DefineMethod( name, attr, returnType, parms );
|
||||
m_Generator = m_Builder.GetILGenerator();
|
||||
|
||||
m_ArgumentTypes = parms;
|
||||
}
|
||||
|
||||
public LocalBuilder CreateLocal( Type localType )
|
||||
{
|
||||
return m_Generator.DeclareLocal( localType );
|
||||
}
|
||||
|
||||
public LocalBuilder AcquireTemp( Type localType )
|
||||
{
|
||||
Queue<LocalBuilder> list;
|
||||
|
||||
if ( !m_Temps.TryGetValue( localType, out list ) )
|
||||
m_Temps[localType] = list = new Queue<LocalBuilder>();
|
||||
|
||||
if ( list.Count > 0 )
|
||||
return list.Dequeue();
|
||||
|
||||
return CreateLocal( localType );
|
||||
}
|
||||
|
||||
public void ReleaseTemp( LocalBuilder local )
|
||||
{
|
||||
Queue<LocalBuilder> list;
|
||||
|
||||
if ( !m_Temps.TryGetValue( local.LocalType, out list ) )
|
||||
m_Temps[local.LocalType] = list = new Queue<LocalBuilder>();
|
||||
|
||||
list.Enqueue( local );
|
||||
}
|
||||
|
||||
public void Branch( Label label )
|
||||
{
|
||||
m_Generator.Emit( OpCodes.Br, label );
|
||||
}
|
||||
|
||||
public void BranchIfFalse( Label label )
|
||||
{
|
||||
Pop( typeof( object ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Brfalse, label );
|
||||
}
|
||||
|
||||
public void BranchIfTrue( Label label )
|
||||
{
|
||||
Pop( typeof( object ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Brtrue, label );
|
||||
}
|
||||
|
||||
public Label CreateLabel()
|
||||
{
|
||||
return m_Generator.DefineLabel();
|
||||
}
|
||||
|
||||
public void MarkLabel( Label label )
|
||||
{
|
||||
m_Generator.MarkLabel( label );
|
||||
}
|
||||
|
||||
public void Pop()
|
||||
{
|
||||
m_Stack.Pop();
|
||||
}
|
||||
|
||||
public void Pop( Type expected )
|
||||
{
|
||||
if ( expected == null )
|
||||
throw new InvalidOperationException( "Expected type cannot be null." );
|
||||
|
||||
Type onStack = m_Stack.Pop();
|
||||
|
||||
if ( expected == typeof( bool ) )
|
||||
expected = typeof( int );
|
||||
|
||||
if ( onStack == typeof( bool ) )
|
||||
onStack = typeof( int );
|
||||
|
||||
if ( !expected.IsAssignableFrom( onStack ) )
|
||||
throw new InvalidOperationException( "Unexpected stack state." );
|
||||
}
|
||||
|
||||
public void Push( Type type )
|
||||
{
|
||||
m_Stack.Push( type );
|
||||
}
|
||||
|
||||
public void Return()
|
||||
{
|
||||
if ( m_Stack.Count != ( m_Builder.ReturnType == typeof( void ) ? 0 : 1 ) )
|
||||
throw new InvalidOperationException( "Stack return mismatch." );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ret );
|
||||
}
|
||||
|
||||
public void LoadNull()
|
||||
{
|
||||
LoadNull( typeof( object ) );
|
||||
}
|
||||
|
||||
public void LoadNull( Type type )
|
||||
{
|
||||
Push( type );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ldnull );
|
||||
}
|
||||
|
||||
public void Load( string value )
|
||||
{
|
||||
Push( typeof( string ) );
|
||||
|
||||
if ( value != null )
|
||||
m_Generator.Emit( OpCodes.Ldstr, value );
|
||||
else
|
||||
m_Generator.Emit( OpCodes.Ldnull );
|
||||
}
|
||||
|
||||
public void Load( Enum value )
|
||||
{
|
||||
int toLoad = ((IConvertible)value).ToInt32( null );
|
||||
Load( toLoad );
|
||||
|
||||
Pop();
|
||||
Push( value.GetType() );
|
||||
}
|
||||
|
||||
public void Load( long value )
|
||||
{
|
||||
Push( typeof( long ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ldc_I8, value );
|
||||
}
|
||||
|
||||
public void Load( float value )
|
||||
{
|
||||
Push( typeof( float ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ldc_R4, value );
|
||||
}
|
||||
|
||||
public void Load( double value )
|
||||
{
|
||||
Push( typeof( double ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ldc_R8, value );
|
||||
}
|
||||
|
||||
public void Load( char value )
|
||||
{
|
||||
Load( (int) value );
|
||||
|
||||
Pop();
|
||||
Push( typeof( char ) );
|
||||
}
|
||||
|
||||
public void Load( bool value )
|
||||
{
|
||||
Push( typeof( bool ) );
|
||||
|
||||
if ( value )
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_1 );
|
||||
else
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_0 );
|
||||
}
|
||||
|
||||
public void Load( int value )
|
||||
{
|
||||
Push( typeof( int ) );
|
||||
|
||||
switch ( value )
|
||||
{
|
||||
case -1:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_M1 );
|
||||
break;
|
||||
|
||||
case 0:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_0 );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_1 );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_2 );
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_3 );
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_4 );
|
||||
break;
|
||||
|
||||
case 5:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_5 );
|
||||
break;
|
||||
|
||||
case 6:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_6 );
|
||||
break;
|
||||
|
||||
case 7:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_7 );
|
||||
break;
|
||||
|
||||
case 8:
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_8 );
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( value >= sbyte.MinValue && value <= sbyte.MaxValue )
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_S, (sbyte) value );
|
||||
else
|
||||
m_Generator.Emit( OpCodes.Ldc_I4, value );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadField( FieldInfo field )
|
||||
{
|
||||
Pop( field.DeclaringType );
|
||||
|
||||
Push( field.FieldType );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ldfld, field );
|
||||
}
|
||||
|
||||
public void LoadLocal( LocalBuilder local )
|
||||
{
|
||||
Push( local.LocalType );
|
||||
|
||||
int index = local.LocalIndex;
|
||||
|
||||
switch ( index )
|
||||
{
|
||||
case 0:
|
||||
m_Generator.Emit( OpCodes.Ldloc_0 );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_Generator.Emit( OpCodes.Ldloc_1 );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_Generator.Emit( OpCodes.Ldloc_2 );
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_Generator.Emit( OpCodes.Ldloc_3 );
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( index >= byte.MinValue && index <= byte.MinValue )
|
||||
m_Generator.Emit( OpCodes.Ldloc_S, (byte) index );
|
||||
else
|
||||
m_Generator.Emit( OpCodes.Ldloc, (short) index );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void StoreLocal( LocalBuilder local )
|
||||
{
|
||||
Pop( local.LocalType );
|
||||
|
||||
m_Generator.Emit( OpCodes.Stloc, local );
|
||||
}
|
||||
|
||||
public void LoadArgument( int index )
|
||||
{
|
||||
if ( index > 0 )
|
||||
Push( m_ArgumentTypes[index - 1] );
|
||||
else
|
||||
Push( m_TypeBuilder );
|
||||
|
||||
switch ( index )
|
||||
{
|
||||
case 0:
|
||||
m_Generator.Emit( OpCodes.Ldarg_0 );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
m_Generator.Emit( OpCodes.Ldarg_1 );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_Generator.Emit( OpCodes.Ldarg_2 );
|
||||
break;
|
||||
|
||||
case 3:
|
||||
m_Generator.Emit( OpCodes.Ldarg_3 );
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( index >= byte.MinValue && index <= byte.MaxValue )
|
||||
m_Generator.Emit( OpCodes.Ldarg_S, (byte) index );
|
||||
else
|
||||
m_Generator.Emit( OpCodes.Ldarg, (short) index );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void CastAs( Type type )
|
||||
{
|
||||
Pop( typeof( object ) );
|
||||
Push( type );
|
||||
|
||||
m_Generator.Emit( OpCodes.Isinst, type );
|
||||
}
|
||||
|
||||
public void Neg()
|
||||
{
|
||||
Pop( typeof( int ) );
|
||||
|
||||
Push( typeof( int ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Neg );
|
||||
}
|
||||
|
||||
public void Compare( OpCode opCode )
|
||||
{
|
||||
Pop();
|
||||
Pop();
|
||||
|
||||
Push( typeof( int ) );
|
||||
|
||||
m_Generator.Emit( opCode );
|
||||
}
|
||||
|
||||
public void LogicalNot()
|
||||
{
|
||||
Pop( typeof( int ) );
|
||||
|
||||
Push( typeof( int ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Ldc_I4_0 );
|
||||
m_Generator.Emit( OpCodes.Ceq );
|
||||
}
|
||||
|
||||
public void Xor()
|
||||
{
|
||||
Pop( typeof( int ) );
|
||||
Pop( typeof( int ) );
|
||||
|
||||
Push( typeof( int ) );
|
||||
|
||||
m_Generator.Emit( OpCodes.Xor );
|
||||
}
|
||||
|
||||
public Type Active
|
||||
{
|
||||
get { return m_Stack.Peek(); }
|
||||
}
|
||||
|
||||
public void Chain( Property prop )
|
||||
{
|
||||
for ( int i = 0; i < prop.Chain.Length; ++i )
|
||||
Call( prop.Chain[i].GetGetMethod() );
|
||||
}
|
||||
|
||||
public void Call( MethodInfo method )
|
||||
{
|
||||
BeginCall( method );
|
||||
|
||||
CallInfo call = m_Calls.Peek();
|
||||
|
||||
if ( call.parms.Length > 0 )
|
||||
throw new InvalidOperationException( "Method requires parameters." );
|
||||
|
||||
FinishCall();
|
||||
}
|
||||
|
||||
public delegate void Callback();
|
||||
|
||||
#if MONO
|
||||
private static bool GenericComparator( Type type, object obj )
|
||||
{
|
||||
return ( type.IsGenericType )
|
||||
&& ( type.GetGenericTypeDefinition() == typeof( IComparable<> ) )
|
||||
&& ( type.GetGenericArguments()[0].IsAssignableFrom(obj as Type) );
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool CompareTo( int sign, Callback argGenerator )
|
||||
{
|
||||
Type active = this.Active;
|
||||
|
||||
MethodInfo compareTo = active.GetMethod( "CompareTo", new Type[] { active } );
|
||||
|
||||
if ( compareTo == null )
|
||||
{
|
||||
/* This gets a little tricky...
|
||||
*
|
||||
* There's a scenario where we might be trying to use CompareTo on an interface
|
||||
* which, while it doesn't explicitly implement CompareTo itself, is said to
|
||||
* extend IComparable indirectly. The implementation is implicitly passed off
|
||||
* to implementers...
|
||||
*
|
||||
* interface ISomeInterface : IComparable
|
||||
* {
|
||||
* void SomeMethod();
|
||||
* }
|
||||
*
|
||||
* class SomeClass : ISomeInterface
|
||||
* {
|
||||
* void SomeMethod() { ... }
|
||||
* int CompareTo( object other ) { ... }
|
||||
* }
|
||||
*
|
||||
* In this case, calling ISomeInterface.GetMethod( "CompareTo" ) will return null.
|
||||
*
|
||||
* Bleh.
|
||||
*/
|
||||
|
||||
#if MONO
|
||||
Type[] ifaces = active.FindInterfaces( GenericComparator, active );
|
||||
#else
|
||||
Type[] ifaces = active.FindInterfaces( delegate( Type type, object obj )
|
||||
{
|
||||
return ( type.IsGenericType )
|
||||
&& ( type.GetGenericTypeDefinition() == typeof( IComparable<> ) )
|
||||
&& ( type.GetGenericArguments()[0].IsAssignableFrom( active ) );
|
||||
}, null );
|
||||
#endif
|
||||
|
||||
if ( ifaces.Length > 0 )
|
||||
{
|
||||
compareTo = ifaces[0].GetMethod( "CompareTo", new Type[] { active } );
|
||||
}
|
||||
else
|
||||
{
|
||||
ifaces = active.FindInterfaces( delegate( Type type, object obj )
|
||||
{
|
||||
return ( type == typeof( IComparable ) );
|
||||
}, null );
|
||||
|
||||
if ( ifaces.Length > 0 )
|
||||
compareTo = ifaces[0].GetMethod( "CompareTo", new Type[] { active } );
|
||||
}
|
||||
}
|
||||
|
||||
if ( compareTo == null )
|
||||
return false;
|
||||
|
||||
if ( !active.IsValueType )
|
||||
{
|
||||
/* This object is a reference type, so we have to make it behave
|
||||
*
|
||||
* null.CompareTo( null ) = 0
|
||||
* real.CompareTo( null ) = -1
|
||||
* null.CompareTo( real ) = +1
|
||||
*
|
||||
*/
|
||||
|
||||
LocalBuilder aValue = AcquireTemp( active );
|
||||
LocalBuilder bValue = AcquireTemp( active );
|
||||
|
||||
StoreLocal( aValue );
|
||||
|
||||
argGenerator();
|
||||
|
||||
StoreLocal( bValue );
|
||||
|
||||
/* if ( aValue == null )
|
||||
* {
|
||||
* if ( bValue == null )
|
||||
* v = 0;
|
||||
* else
|
||||
* v = +1;
|
||||
* }
|
||||
* else if ( bValue == null )
|
||||
* {
|
||||
* v = -1;
|
||||
* }
|
||||
* else
|
||||
* {
|
||||
* v = aValue.CompareTo( bValue );
|
||||
* }
|
||||
*/
|
||||
|
||||
Label store = CreateLabel();
|
||||
|
||||
Label aNotNull = CreateLabel();
|
||||
|
||||
LoadLocal( aValue );
|
||||
BranchIfTrue( aNotNull );
|
||||
// if ( aValue == null )
|
||||
{
|
||||
Label bNotNull = CreateLabel();
|
||||
|
||||
LoadLocal( bValue );
|
||||
BranchIfTrue( bNotNull );
|
||||
// if ( bValue == null )
|
||||
{
|
||||
Load( 0 );
|
||||
Pop( typeof( int ) );
|
||||
Branch( store );
|
||||
}
|
||||
MarkLabel( bNotNull );
|
||||
// else
|
||||
{
|
||||
Load( sign );
|
||||
Pop( typeof( int ) );
|
||||
Branch( store );
|
||||
}
|
||||
}
|
||||
MarkLabel( aNotNull );
|
||||
// else
|
||||
{
|
||||
Label bNotNull = CreateLabel();
|
||||
|
||||
LoadLocal( bValue );
|
||||
BranchIfTrue( bNotNull );
|
||||
// bValue == null
|
||||
{
|
||||
Load( -sign );
|
||||
Pop( typeof( int ) );
|
||||
Branch( store );
|
||||
}
|
||||
MarkLabel( bNotNull );
|
||||
// else
|
||||
{
|
||||
LoadLocal( aValue );
|
||||
BeginCall( compareTo );
|
||||
|
||||
LoadLocal( bValue );
|
||||
ArgumentPushed();
|
||||
|
||||
FinishCall();
|
||||
|
||||
if ( sign == -1 )
|
||||
Neg();
|
||||
}
|
||||
}
|
||||
|
||||
MarkLabel( store );
|
||||
|
||||
ReleaseTemp( aValue );
|
||||
ReleaseTemp( bValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
BeginCall( compareTo );
|
||||
|
||||
argGenerator();
|
||||
|
||||
ArgumentPushed();
|
||||
|
||||
FinishCall();
|
||||
|
||||
if ( sign == -1 )
|
||||
Neg();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void BeginCall( MethodInfo method )
|
||||
{
|
||||
Type type;
|
||||
|
||||
if ( ( method.CallingConvention & CallingConventions.HasThis ) != 0 )
|
||||
type = m_Stack.Peek();
|
||||
else
|
||||
type = method.DeclaringType;
|
||||
|
||||
m_Calls.Push( new CallInfo( type, method ) );
|
||||
|
||||
if ( type.IsValueType )
|
||||
{
|
||||
LocalBuilder temp = AcquireTemp( type );
|
||||
|
||||
m_Generator.Emit( OpCodes.Stloc, temp );
|
||||
m_Generator.Emit( OpCodes.Ldloca, temp );
|
||||
|
||||
ReleaseTemp( temp );
|
||||
}
|
||||
}
|
||||
|
||||
public void FinishCall()
|
||||
{
|
||||
CallInfo call = m_Calls.Pop();
|
||||
|
||||
if ( ( call.type.IsValueType || call.type.IsByRef ) && call.method.DeclaringType != call.type )
|
||||
m_Generator.Emit( OpCodes.Constrained, call.type );
|
||||
|
||||
if ( call.method.DeclaringType.IsValueType || call.method.IsStatic )
|
||||
m_Generator.Emit( OpCodes.Call, call.method );
|
||||
else
|
||||
m_Generator.Emit( OpCodes.Callvirt, call.method );
|
||||
|
||||
for ( int i = call.parms.Length - 1; i >= 0; --i )
|
||||
Pop( call.parms[i].ParameterType );
|
||||
|
||||
if ( ( call.method.CallingConvention & CallingConventions.HasThis ) != 0 )
|
||||
Pop( call.method.DeclaringType );
|
||||
|
||||
if ( call.method.ReturnType != typeof( void ) )
|
||||
Push( call.method.ReturnType );
|
||||
}
|
||||
|
||||
public void ArgumentPushed()
|
||||
{
|
||||
CallInfo call = m_Calls.Peek();
|
||||
|
||||
ParameterInfo parm = call.parms[call.index++];
|
||||
|
||||
Type argumentType = m_Stack.Peek();
|
||||
|
||||
if ( !parm.ParameterType.IsAssignableFrom( argumentType ) )
|
||||
throw new InvalidOperationException( "Parameter type mismatch." );
|
||||
|
||||
if ( argumentType.IsValueType && !parm.ParameterType.IsValueType )
|
||||
m_Generator.Emit( OpCodes.Box, argumentType );
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Scripts/Misc/Fastwalk.cs
Normal file
32
Scripts/Misc/Fastwalk.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
// This fastwalk detection is no longer required
|
||||
// As of B36 PlayerMobile implements movement packet throttling which more reliably controls movement speeds
|
||||
public class Fastwalk
|
||||
{
|
||||
private static int MaxSteps = 4; // Maximum number of queued steps until fastwalk is detected
|
||||
private static bool Enabled = false; // Is fastwalk detection enabled?
|
||||
private static bool UOTDOverride = false; // Should UO:TD clients not be checked for fastwalk?
|
||||
private static AccessLevel AccessOverride = AccessLevel.GameMaster; // Anyone with this or higher access level is not checked for fastwalk
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Mobile.FwdMaxSteps = MaxSteps;
|
||||
Mobile.FwdEnabled = Enabled;
|
||||
Mobile.FwdUOTDOverride = UOTDOverride;
|
||||
Mobile.FwdAccessOverride = AccessOverride;
|
||||
|
||||
if ( Enabled )
|
||||
EventSink.FastWalk += new FastWalkEventHandler( OnFastWalk );
|
||||
}
|
||||
|
||||
public static void OnFastWalk( FastWalkEventArgs e )
|
||||
{
|
||||
e.Blocked = true;//disallow this fastwalk
|
||||
Console.WriteLine( "Client: {0}: Fast movement detected (name={1})", e.NetState, e.NetState.Mobile.Name );
|
||||
}
|
||||
}
|
||||
}
|
||||
150
Scripts/Misc/FoodDecay.cs
Normal file
150
Scripts/Misc/FoodDecay.cs
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
using System;
|
||||
using Server.Network;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class FoodDecayTimer : Timer
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
new FoodDecayTimer().Start();
|
||||
}
|
||||
|
||||
public FoodDecayTimer() : base( TimeSpan.FromMinutes( 5 ), TimeSpan.FromMinutes( 5 ) )
|
||||
{
|
||||
Priority = TimerPriority.OneMinute;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
FoodDecay();
|
||||
}
|
||||
|
||||
public static void FoodDecay()
|
||||
{
|
||||
foreach ( NetState state in NetState.Instances )
|
||||
{
|
||||
HungerDecay( state.Mobile );
|
||||
}
|
||||
}
|
||||
|
||||
public static void HungerDecay( Mobile m )
|
||||
{
|
||||
if ( m != null && m is PlayerMobile && !(m.AccessLevel > AccessLevel.Player) && !(m.Region is InnRegion) )
|
||||
{
|
||||
if ( m.Hunger >= 1 )
|
||||
m.Hunger -= 1;
|
||||
if ( m.Thirst >= 1 )
|
||||
m.Thirst -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EatDecayTimer : Timer
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
new EatDecayTimer().Start();
|
||||
}
|
||||
|
||||
public EatDecayTimer() : base( TimeSpan.FromSeconds( 11.0 ), TimeSpan.FromSeconds( 11.0 ) )
|
||||
{
|
||||
Priority = TimerPriority.OneSecond;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
EatDecay();
|
||||
}
|
||||
|
||||
public static void EatDecay()
|
||||
{
|
||||
foreach ( NetState state in NetState.Instances )
|
||||
{
|
||||
EatDecaying( state.Mobile );
|
||||
}
|
||||
}
|
||||
|
||||
public static void EatDecaying( Mobile m )
|
||||
{
|
||||
if ( m is PlayerMobile && m.Alive && (m.Hunger < 5 || m.Thirst < 5) )
|
||||
{
|
||||
if ( m.Hunger < 5 )
|
||||
{
|
||||
int hits = 0;
|
||||
|
||||
switch (m.Hunger)
|
||||
{
|
||||
case 4: hits = 2; break;
|
||||
case 3: hits = 3; break;
|
||||
case 2: hits = 4; break;
|
||||
case 1: hits = 5; break;
|
||||
case 0:
|
||||
{
|
||||
hits = 6;
|
||||
m.SendMessage( "You are starving to death!" );
|
||||
m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am so hungry!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m.Hits < hits )
|
||||
hits = m.Hits-1;
|
||||
|
||||
if ( hits > 0 )
|
||||
m.Hits -= hits;
|
||||
|
||||
if ( m.Hunger < 3 && m.Hunger > 0 )
|
||||
{
|
||||
if ( Utility.RandomBool() ){ m.SendMessage( "You are getting very hungry!" ); }
|
||||
if ( Utility.RandomMinMax(1,5)==1 ){ m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am getting hungry!"); }
|
||||
}
|
||||
}
|
||||
if ( m.Thirst < 5 )
|
||||
{
|
||||
switch (m.Thirst)
|
||||
{
|
||||
case 4: m.Stam -= 2; break;
|
||||
case 3: m.Stam -= 3; break;
|
||||
case 2: m.Stam -= 4; break;
|
||||
case 1: m.Stam -= 5; break;
|
||||
case 0:
|
||||
{
|
||||
m.Stam -= 6;
|
||||
m.SendMessage( "You are exhausted from thirst!" );
|
||||
m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am so thirsty!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( m.Thirst < 3 && m.Thirst > 0 )
|
||||
{
|
||||
if ( Utility.RandomBool() ){ m.SendMessage( "You are getting exhausted from thirst!" ); }
|
||||
if ( Utility.RandomMinMax(1,5)==1 ){ m.LocalOverheadMessage(MessageType.Emote, 1150, true, "I am getting thirsty!"); }
|
||||
}
|
||||
if ( m.Stam < 0 )
|
||||
m.Stam = 0;
|
||||
}
|
||||
if ( m.Thirst < 5 || m.Hunger < 5 )
|
||||
{
|
||||
int test = m.Thirst;
|
||||
if ( m.Hunger < m.Thirst )
|
||||
test = m.Hunger;
|
||||
|
||||
switch (test)
|
||||
{
|
||||
case 4: m.Mana -= 2; break;
|
||||
case 3: m.Mana -= 3; break;
|
||||
case 2: m.Mana -= 4; break;
|
||||
case 1: m.Mana -= 5; break;
|
||||
case 0: m.Mana -= 6; break;
|
||||
}
|
||||
if ( m.Mana < 0 )
|
||||
m.Mana = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
224
Scripts/Misc/Geometry.cs
Normal file
224
Scripts/Misc/Geometry.cs
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public delegate void DoEffect_Callback( Point3D p, Map map );
|
||||
|
||||
public static class Geometry
|
||||
{
|
||||
public static void Swap<T>( ref T a, ref T b )
|
||||
{
|
||||
T temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
public static double RadiansToDegrees( double angle )
|
||||
{
|
||||
return angle * (180.0 / Math.PI);
|
||||
}
|
||||
|
||||
public static double DegreesToRadians( double angle )
|
||||
{
|
||||
return angle * ( Math.PI / 180.0 );
|
||||
}
|
||||
|
||||
public class CirclePoint
|
||||
{
|
||||
private Point2D point;
|
||||
private int angle;
|
||||
private int quadrant;
|
||||
|
||||
public Point2D Point{ get{ return point; } }
|
||||
public int Angle{ get{ return angle; } }
|
||||
public int Quadrant{ get{ return quadrant; } }
|
||||
|
||||
public CirclePoint( Point2D point, int angle, int quadrant )
|
||||
{
|
||||
this.point = point;
|
||||
this.angle = angle;
|
||||
this.quadrant = quadrant;
|
||||
}
|
||||
}
|
||||
|
||||
public static Point2D ArcPoint( Point3D loc, int radius, int angle )
|
||||
{
|
||||
int sideA, sideB;
|
||||
|
||||
if ( angle < 0 )
|
||||
angle = 0;
|
||||
|
||||
if ( angle > 90 )
|
||||
angle = 90;
|
||||
|
||||
sideA = (int) Math.Round( radius * Math.Sin( DegreesToRadians( angle ) ) );
|
||||
sideB = (int) Math.Round( radius * Math.Cos( DegreesToRadians( angle ) ) );
|
||||
|
||||
return new Point2D( loc.X - sideB, loc.Y - sideA );
|
||||
}
|
||||
|
||||
public static void Circle2D( Point3D loc, Map map, int radius, DoEffect_Callback effect )
|
||||
{
|
||||
Circle2D( loc, map, radius, effect, 0, 360 );
|
||||
}
|
||||
|
||||
public static void Circle2D( Point3D loc, Map map, int radius, DoEffect_Callback effect, int angleStart, int angleEnd )
|
||||
{
|
||||
if ( angleStart < 0 || angleStart > 360 )
|
||||
angleStart = 0;
|
||||
|
||||
if ( angleEnd > 360 || angleEnd < 0 )
|
||||
angleEnd = 360;
|
||||
|
||||
if ( angleStart == angleEnd )
|
||||
return;
|
||||
|
||||
bool opposite = angleStart > angleEnd;
|
||||
|
||||
int startQuadrant = angleStart / 90;
|
||||
int endQuadrant = angleEnd / 90;
|
||||
|
||||
Point2D start = ArcPoint( loc, radius, angleStart % 90 );
|
||||
Point2D end = ArcPoint( loc, radius, angleEnd % 90 );
|
||||
|
||||
if ( opposite )
|
||||
{
|
||||
Swap( ref start, ref end );
|
||||
Swap( ref startQuadrant, ref endQuadrant );
|
||||
}
|
||||
|
||||
CirclePoint startPoint = new CirclePoint( start, angleStart, startQuadrant );
|
||||
CirclePoint endPoint = new CirclePoint( end, angleEnd, endQuadrant );
|
||||
|
||||
int error = -radius;
|
||||
int x = radius;
|
||||
int y = 0;
|
||||
|
||||
while (x > y)
|
||||
{
|
||||
plot4points( loc, map, x, y, startPoint, endPoint, effect, opposite );
|
||||
plot4points( loc, map, y, x, startPoint, endPoint, effect, opposite );
|
||||
|
||||
error += ( y * 2 ) + 1;
|
||||
++y;
|
||||
|
||||
if (error >= 0)
|
||||
{
|
||||
--x;
|
||||
error -= x * 2;
|
||||
}
|
||||
}
|
||||
|
||||
plot4points( loc, map, x, y, startPoint, endPoint, effect, opposite );
|
||||
}
|
||||
|
||||
public static void plot4points( Point3D loc, Map map, int x, int y, CirclePoint start, CirclePoint end, DoEffect_Callback effect, bool opposite )
|
||||
{
|
||||
Point2D pointA = new Point2D( loc.X - x, loc.Y - y );
|
||||
Point2D pointB = new Point2D( loc.X - y, loc.Y - x );
|
||||
|
||||
int quadrant = 2;
|
||||
|
||||
if ( x == 0 && start.Quadrant == 3 )
|
||||
quadrant = 3;
|
||||
|
||||
if ( WithinCircleBounds( quadrant == 3 ? pointB : pointA, quadrant, loc, start, end, opposite ) )
|
||||
effect( new Point3D( loc.X + x, loc.Y + y, loc.Z ), map );
|
||||
|
||||
quadrant = 3;
|
||||
|
||||
if ( y == 0 && start.Quadrant == 0 )
|
||||
quadrant = 0;
|
||||
|
||||
if ( x != 0 && WithinCircleBounds( quadrant == 0 ? pointA : pointB, quadrant, loc, start, end, opposite ) )
|
||||
effect( new Point3D( loc.X - x, loc.Y + y, loc.Z ), map );
|
||||
if ( y != 0 && WithinCircleBounds( pointB, 1, loc, start, end, opposite ) )
|
||||
effect( new Point3D( loc.X + x, loc.Y - y, loc.Z ), map );
|
||||
if ( x != 0 && y != 0 && WithinCircleBounds( pointA, 0, loc, start, end, opposite ) )
|
||||
effect( new Point3D( loc.X - x, loc.Y - y, loc.Z ), map );
|
||||
}
|
||||
|
||||
public static bool WithinCircleBounds( Point2D pointLoc, int pointQuadrant, Point3D center, CirclePoint start, CirclePoint end, bool opposite )
|
||||
{
|
||||
if ( start.Angle == 0 && end.Angle == 360 )
|
||||
return true;
|
||||
|
||||
int startX = start.Point.X;
|
||||
int startY = start.Point.Y;
|
||||
int endX = end.Point.X;
|
||||
int endY = end.Point.Y;
|
||||
|
||||
int x = pointLoc.X;
|
||||
int y = pointLoc.Y;
|
||||
|
||||
if ( pointQuadrant < start.Quadrant || pointQuadrant > end.Quadrant )
|
||||
return opposite;
|
||||
|
||||
if ( pointQuadrant > start.Quadrant && pointQuadrant < end.Quadrant )
|
||||
return !opposite;
|
||||
|
||||
bool withinBounds = true;
|
||||
|
||||
if ( start.Quadrant == end.Quadrant )
|
||||
{
|
||||
if ( startX == endX && ( x > startX || y > startY || y < endY ) )
|
||||
withinBounds = false;
|
||||
else if ( startY == endY && ( y < startY || x < startX || x > endX ) )
|
||||
withinBounds = false;
|
||||
else if ( x < startX || x > endX || y > startY || y < endY )
|
||||
withinBounds = false;
|
||||
}
|
||||
else if ( pointQuadrant == start.Quadrant && ( x < startX || y > startY ) )
|
||||
withinBounds = false;
|
||||
else if ( pointQuadrant == end.Quadrant && ( x > endX || y < endY ) )
|
||||
withinBounds = false;
|
||||
|
||||
return opposite ? !withinBounds : withinBounds;
|
||||
}
|
||||
|
||||
public static void Line2D( Point3D start, Point3D end, Map map, DoEffect_Callback effect )
|
||||
{
|
||||
bool steep = Math.Abs( end.Y - start.Y ) > Math.Abs( end.X - start.X );
|
||||
|
||||
int x0 = start.X;
|
||||
int x1 = end.X;
|
||||
int y0 = start.Y;
|
||||
int y1 = end.Y;
|
||||
|
||||
if ( steep )
|
||||
{
|
||||
Swap( ref x0, ref y0 );
|
||||
Swap( ref x1, ref y1 );
|
||||
}
|
||||
|
||||
if ( x0 > x1 )
|
||||
{
|
||||
Swap( ref x0, ref x1 );
|
||||
Swap( ref y0, ref y1 );
|
||||
}
|
||||
|
||||
int deltax = x1 - x0;
|
||||
int deltay = Math.Abs( y1 - y0 );
|
||||
int error = deltax / 2;
|
||||
int ystep = y0 < y1 ? 1 : -1;
|
||||
int y = y0;
|
||||
|
||||
for ( int x = x0; x <= x1; x++ )
|
||||
{
|
||||
if ( steep )
|
||||
effect( new Point3D( y, x, start.Z ), map );
|
||||
else
|
||||
effect( new Point3D( x, y, start.Z ), map );
|
||||
|
||||
error -= deltay;
|
||||
|
||||
if ( error < 0 )
|
||||
{
|
||||
y += ystep;
|
||||
error += deltax;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
189
Scripts/Misc/HardwareInfo.cs
Normal file
189
Scripts/Misc/HardwareInfo.cs
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Commands;
|
||||
using Server.Accounting;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class HardwareInfo
|
||||
{
|
||||
private int m_InstanceID;
|
||||
private int m_OSMajor, m_OSMinor, m_OSRevision;
|
||||
private int m_CpuManufacturer, m_CpuFamily, m_CpuModel, m_CpuClockSpeed, m_CpuQuantity;
|
||||
private int m_PhysicalMemory;
|
||||
private int m_ScreenWidth, m_ScreenHeight, m_ScreenDepth;
|
||||
private int m_DXMajor, m_DXMinor;
|
||||
private int m_VCVendorID, m_VCDeviceID, m_VCMemory;
|
||||
private int m_Distribution, m_ClientsRunning, m_ClientsInstalled, m_PartialInstalled;
|
||||
private string m_VCDescription;
|
||||
private string m_Language;
|
||||
private string m_Unknown;
|
||||
private DateTime m_TimeReceived;
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int CpuModel{ get{ return m_CpuModel; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int CpuClockSpeed{ get{ return m_CpuClockSpeed; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int CpuQuantity{ get{ return m_CpuQuantity; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int OSMajor{ get{ return m_OSMajor; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int OSMinor{ get{ return m_OSMinor; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int OSRevision{ get{ return m_OSRevision; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int InstanceID{ get{ return m_InstanceID; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int ScreenWidth{ get{ return m_ScreenWidth; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int ScreenHeight{ get{ return m_ScreenHeight; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int ScreenDepth{ get{ return m_ScreenDepth; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int PhysicalMemory{ get{ return m_PhysicalMemory; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int CpuManufacturer{ get{ return m_CpuManufacturer; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int CpuFamily{ get{ return m_CpuFamily; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int VCVendorID{ get{ return m_VCVendorID; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int VCDeviceID{ get{ return m_VCDeviceID; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int VCMemory{ get{ return m_VCMemory; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int DXMajor{ get{ return m_DXMajor; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int DXMinor{ get{ return m_DXMinor; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public string VCDescription{ get{ return m_VCDescription; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public string Language{ get{ return m_Language; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int Distribution{ get{ return m_Distribution; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int ClientsRunning{ get{ return m_ClientsRunning; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int ClientsInstalled{ get{ return m_ClientsInstalled; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public int PartialInstalled{ get{ return m_PartialInstalled; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public string Unknown{ get{ return m_Unknown; } }
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster )]
|
||||
public DateTime TimeReceived { get { return m_TimeReceived; } }
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
PacketHandlers.Register( 0xD9, 0x10C, false, new OnPacketReceive( OnReceive ) );
|
||||
|
||||
CommandSystem.Register( "HWInfo", AccessLevel.GameMaster, new CommandEventHandler( HWInfo_OnCommand ) );
|
||||
}
|
||||
|
||||
[Usage( "HWInfo" )]
|
||||
[Description( "Displays information about a targeted player's hardware." )]
|
||||
public static void HWInfo_OnCommand( CommandEventArgs e )
|
||||
{
|
||||
e.Mobile.BeginTarget( -1, false, TargetFlags.None, new TargetCallback( HWInfo_OnTarget ) );
|
||||
e.Mobile.SendMessage( "Target a player to view their hardware information." );
|
||||
}
|
||||
|
||||
public static void HWInfo_OnTarget( Mobile from, object obj )
|
||||
{
|
||||
if ( obj is Mobile && ((Mobile)obj).Player )
|
||||
{
|
||||
Mobile m = (Mobile)obj;
|
||||
Account acct = m.Account as Account;
|
||||
|
||||
if ( acct != null )
|
||||
{
|
||||
HardwareInfo hwInfo = acct.HardwareInfo;
|
||||
|
||||
if ( hwInfo != null )
|
||||
CommandLogging.WriteLine( from, "{0} {1} viewing hardware info of {2}", from.AccessLevel, CommandLogging.Format( from ), CommandLogging.Format( m ) );
|
||||
|
||||
if ( hwInfo != null )
|
||||
from.SendGump( new Gumps.PropertiesGump( from, hwInfo ) );
|
||||
else
|
||||
from.SendMessage( "No hardware information for that account was found." );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage( "No account has been attached to that player." );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.BeginTarget( -1, false, TargetFlags.None, new TargetCallback( HWInfo_OnTarget ) );
|
||||
from.SendMessage( "That is not a player. Try again." );
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnReceive( NetState state, PacketReader pvSrc )
|
||||
{
|
||||
pvSrc.ReadByte(); // 1: <4.0.1a, 2>=4.0.1a
|
||||
|
||||
HardwareInfo info = new HardwareInfo();
|
||||
|
||||
info.m_InstanceID = pvSrc.ReadInt32();
|
||||
info.m_OSMajor = pvSrc.ReadInt32();
|
||||
info.m_OSMinor = pvSrc.ReadInt32();
|
||||
info.m_OSRevision = pvSrc.ReadInt32();
|
||||
info.m_CpuManufacturer = pvSrc.ReadByte();
|
||||
info.m_CpuFamily = pvSrc.ReadInt32();
|
||||
info.m_CpuModel = pvSrc.ReadInt32();
|
||||
info.m_CpuClockSpeed = pvSrc.ReadInt32();
|
||||
info.m_CpuQuantity = pvSrc.ReadByte();
|
||||
info.m_PhysicalMemory = pvSrc.ReadInt32();
|
||||
info.m_ScreenWidth = pvSrc.ReadInt32();
|
||||
info.m_ScreenHeight = pvSrc.ReadInt32();
|
||||
info.m_ScreenDepth = pvSrc.ReadInt32();
|
||||
info.m_DXMajor = pvSrc.ReadInt16();
|
||||
info.m_DXMinor = pvSrc.ReadInt16();
|
||||
info.m_VCDescription = pvSrc.ReadUnicodeStringLESafe( 64 );
|
||||
info.m_VCVendorID = pvSrc.ReadInt32();
|
||||
info.m_VCDeviceID = pvSrc.ReadInt32();
|
||||
info.m_VCMemory = pvSrc.ReadInt32();
|
||||
info.m_Distribution = pvSrc.ReadByte();
|
||||
info.m_ClientsRunning = pvSrc.ReadByte();
|
||||
info.m_ClientsInstalled = pvSrc.ReadByte();
|
||||
info.m_PartialInstalled = pvSrc.ReadByte();
|
||||
info.m_Language = pvSrc.ReadUnicodeStringLESafe( 4 );
|
||||
info.m_Unknown = pvSrc.ReadStringSafe( 64 );
|
||||
|
||||
info.m_TimeReceived = DateTime.Now;
|
||||
|
||||
Account acct = state.Account as Account;
|
||||
|
||||
if ( acct != null )
|
||||
acct.HardwareInfo = info;
|
||||
}
|
||||
}
|
||||
}
|
||||
595
Scripts/Misc/InhumanSpeech.cs
Normal file
595
Scripts/Misc/InhumanSpeech.cs
Normal file
|
|
@ -0,0 +1,595 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
[Flags]
|
||||
public enum IHSFlags
|
||||
{
|
||||
None = 0x00,
|
||||
OnDamaged = 0x01,
|
||||
OnDeath = 0x02,
|
||||
OnMovement = 0x04,
|
||||
OnSpeech = 0x08,
|
||||
All = OnDamaged | OnDeath | OnMovement
|
||||
} // NOTE: To enable monster conversations, add " | OnSpeech" to the "All" line
|
||||
|
||||
public class InhumanSpeech
|
||||
{
|
||||
private static InhumanSpeech m_RatmanSpeech;
|
||||
|
||||
public static InhumanSpeech Ratman
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_RatmanSpeech == null )
|
||||
{
|
||||
m_RatmanSpeech = new InhumanSpeech();
|
||||
|
||||
m_RatmanSpeech.Hue = 149;
|
||||
m_RatmanSpeech.Sound = 438;
|
||||
|
||||
m_RatmanSpeech.Flags = IHSFlags.All;
|
||||
|
||||
m_RatmanSpeech.Keywords = new string[]
|
||||
{
|
||||
"meat", "gold", "kill", "killing", "slay",
|
||||
"sword", "axe", "spell", "magic", "spells",
|
||||
"swords", "axes", "mace", "maces", "monster",
|
||||
"monsters", "food", "run", "escape", "away",
|
||||
"help", "dead", "die", "dying", "lose",
|
||||
"losing", "life", "lives", "death", "ghost",
|
||||
"ghosts", "british", "blackthorn", "guild",
|
||||
"guilds", "dragon", "dragons", "game", "games",
|
||||
"ultima", "silly", "stupid", "dumb", "idiot",
|
||||
"idiots", "cheesy", "cheezy", "crazy", "dork",
|
||||
"jerk", "fool", "foolish", "ugly", "insult", "scum"
|
||||
};
|
||||
|
||||
m_RatmanSpeech.Responses = new string[]
|
||||
{
|
||||
"meat", "kill", "pound", "crush", "yum yum",
|
||||
"crunch", "destroy", "murder", "eat", "munch",
|
||||
"massacre", "food", "monster", "evil", "run",
|
||||
"die", "lose", "dumb", "idiot", "fool", "crazy",
|
||||
"dinner", "lunch", "breakfast", "fight", "battle",
|
||||
"doomed", "rip apart", "tear apart", "smash",
|
||||
"edible?", "shred", "disembowel", "ugly", "smelly",
|
||||
"stupid", "hideous", "smell", "tasty", "invader",
|
||||
"attack", "raid", "plunder", "pillage", "treasure",
|
||||
"loser", "lose", "scum"
|
||||
};
|
||||
|
||||
m_RatmanSpeech.Syllables = new string[]
|
||||
{
|
||||
"skrit",
|
||||
|
||||
"ch", "ch",
|
||||
"it", "ti", "it", "ti",
|
||||
|
||||
"ak", "ek", "ik", "ok", "uk", "yk",
|
||||
"ka", "ke", "ki", "ko", "ku", "ky",
|
||||
"at", "et", "it", "ot", "ut", "yt",
|
||||
|
||||
"cha", "che", "chi", "cho", "chu", "chy",
|
||||
"ach", "ech", "ich", "och", "uch", "ych",
|
||||
"att", "ett", "itt", "ott", "utt", "ytt",
|
||||
"tat", "tet", "tit", "tot", "tut", "tyt",
|
||||
"tta", "tte", "tti", "tto", "ttu", "tty",
|
||||
"tak", "tek", "tik", "tok", "tuk", "tyk",
|
||||
"ack", "eck", "ick", "ock", "uck", "yck",
|
||||
"cka", "cke", "cki", "cko", "cku", "cky",
|
||||
"rak", "rek", "rik", "rok", "ruk", "ryk",
|
||||
|
||||
"tcha", "tche", "tchi", "tcho", "tchu", "tchy",
|
||||
"rach", "rech", "rich", "roch", "ruch", "rych",
|
||||
"rrap", "rrep", "rrip", "rrop", "rrup", "rryp",
|
||||
"ccka", "ccke", "ccki", "ccko", "ccku", "ccky"
|
||||
};
|
||||
}
|
||||
|
||||
return m_RatmanSpeech;
|
||||
}
|
||||
}
|
||||
|
||||
private static InhumanSpeech m_OrcSpeech;
|
||||
|
||||
public static InhumanSpeech Orc
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_OrcSpeech == null )
|
||||
{
|
||||
m_OrcSpeech = new InhumanSpeech();
|
||||
|
||||
m_OrcSpeech.Hue = 34;
|
||||
m_OrcSpeech.Sound = 432;
|
||||
|
||||
m_OrcSpeech.Flags = IHSFlags.All;
|
||||
|
||||
m_OrcSpeech.Keywords = new string[]
|
||||
{
|
||||
"meat", "gold", "kill", "killing", "slay",
|
||||
"sword", "axe", "spell", "magic", "spells",
|
||||
"swords", "axes", "mace", "maces", "monster",
|
||||
"monsters", "food", "run", "escape", "away",
|
||||
"help", "dead", "die", "dying", "lose",
|
||||
"losing", "life", "lives", "death", "ghost",
|
||||
"ghosts", "british", "blackthorn", "guild",
|
||||
"guilds", "dragon", "dragons", "game", "games",
|
||||
"ultima", "silly", "stupid", "dumb", "idiot",
|
||||
"idiots", "cheesy", "cheezy", "crazy", "dork",
|
||||
"jerk", "fool", "foolish", "ugly", "insult", "scum"
|
||||
};
|
||||
|
||||
m_OrcSpeech.Responses = new string[]
|
||||
{
|
||||
"meat", "kill", "pound", "crush", "yum yum",
|
||||
"crunch", "destroy", "murder", "eat", "munch",
|
||||
"massacre", "food", "monster", "evil", "run",
|
||||
"die", "lose", "dumb", "idiot", "fool", "crazy",
|
||||
"dinner", "lunch", "breakfast", "fight", "battle",
|
||||
"doomed", "rip apart", "tear apart", "smash",
|
||||
"edible?", "shred", "disembowel", "ugly", "smelly",
|
||||
"stupid", "hideous", "smell", "tasty", "invader",
|
||||
"attack", "raid", "plunder", "pillage", "treasure",
|
||||
"loser", "lose", "scum"
|
||||
};
|
||||
|
||||
m_OrcSpeech.Syllables = new string[]
|
||||
{
|
||||
"bu", "du", "fu", "ju", "gu",
|
||||
"ulg", "gug", "gub", "gur", "oog",
|
||||
"gub", "log", "ru", "stu", "glu",
|
||||
"ug", "ud", "og", "log", "ro", "flu",
|
||||
"bo", "duf", "fun", "nog", "dun", "bog",
|
||||
"dug", "gh", "ghu", "gho", "nug", "ig",
|
||||
"igh", "ihg", "luh", "duh", "bug", "dug",
|
||||
"dru", "urd", "gurt", "grut", "grunt",
|
||||
"snarf", "urgle", "igg", "glu", "glug",
|
||||
"foo", "bar", "baz", "ghat", "ab", "ad",
|
||||
"gugh", "guk", "ag", "alm", "thu", "log",
|
||||
"bilge", "augh", "gha", "gig", "goth",
|
||||
"zug", "pig", "auh", "gan", "azh", "bag",
|
||||
"hig", "oth", "dagh", "gulg", "ugh", "ba",
|
||||
"bid", "gug", "bug", "rug", "hat", "brui",
|
||||
"gagh", "buad", "buil", "buim", "bum",
|
||||
"hug", "hug", "buo", "ma", "buor", "ghed",
|
||||
"buu", "ca", "guk", "clog", "thurg", "car",
|
||||
"cro", "thu", "da", "cuk", "gil", "cur", "dak",
|
||||
"dar", "deak", "der", "dil", "dit", "at", "ag",
|
||||
"dor", "gar", "dre", "tk", "dri", "gka", "rim",
|
||||
"eag", "egg", "ha", "rod", "eg", "lat", "eichel",
|
||||
"ek", "ep", "ka", "it", "ut", "ewk", "ba", "dagh",
|
||||
"faugh", "foz", "fog", "fid", "fruk", "gag", "fub",
|
||||
"fud", "fur", "bog", "fup", "hagh", "gaa", "kt",
|
||||
"rekk", "lub", "lug", "tug", "gna", "urg", "l",
|
||||
"gno", "gnu", "gol", "gom", "kug", "ukk", "jak",
|
||||
"jek", "rukk", "jja", "akt", "nuk", "hok", "hrol",
|
||||
"olm", "natz", "i", "i", "o", "u", "ikk", "ign",
|
||||
"juk", "kh", "kgh", "ka", "hig", "ke", "ki", "klap",
|
||||
"klu", "knod", "kod", "knu", "thnu", "krug", "nug",
|
||||
"nar", "nag", "neg", "neh", "oag", "ob", "ogh", "oh",
|
||||
"om", "dud", "oo", "pa", "hrak", "qo", "quad", "quil",
|
||||
"ghig", "rur", "sag", "sah", "sg"
|
||||
};
|
||||
}
|
||||
|
||||
return m_OrcSpeech;
|
||||
}
|
||||
}
|
||||
|
||||
private static InhumanSpeech m_LizardmanSpeech;
|
||||
|
||||
public static InhumanSpeech Lizardman
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_LizardmanSpeech == null )
|
||||
{
|
||||
m_LizardmanSpeech = new InhumanSpeech();
|
||||
|
||||
m_LizardmanSpeech.Hue = 58;
|
||||
m_LizardmanSpeech.Sound = 418;
|
||||
|
||||
m_LizardmanSpeech.Flags = IHSFlags.All;
|
||||
|
||||
m_LizardmanSpeech.Keywords = new string[]
|
||||
{
|
||||
"meat", "gold", "kill", "killing", "slay",
|
||||
"sword", "axe", "spell", "magic", "spells",
|
||||
"swords", "axes", "mace", "maces", "monster",
|
||||
"monsters", "food", "run", "escape", "away",
|
||||
"help", "dead", "die", "dying", "lose",
|
||||
"losing", "life", "lives", "death", "ghost",
|
||||
"ghosts", "british", "blackthorn", "guild",
|
||||
"guilds", "dragon", "dragons", "game", "games",
|
||||
"ultima", "silly", "stupid", "dumb", "idiot",
|
||||
"idiots", "cheesy", "cheezy", "crazy", "dork",
|
||||
"jerk", "fool", "foolish", "ugly", "insult", "scum"
|
||||
};
|
||||
|
||||
m_LizardmanSpeech.Responses = new string[]
|
||||
{
|
||||
"meat", "kill", "pound", "crush", "yum yum",
|
||||
"crunch", "destroy", "murder", "eat", "munch",
|
||||
"massacre", "food", "monster", "evil", "run",
|
||||
"die", "lose", "dumb", "idiot", "fool", "crazy",
|
||||
"dinner", "lunch", "breakfast", "fight", "battle",
|
||||
"doomed", "rip apart", "tear apart", "smash",
|
||||
"edible?", "shred", "disembowel", "ugly", "smelly",
|
||||
"stupid", "hideous", "smell", "tasty", "invader",
|
||||
"attack", "raid", "plunder", "pillage", "treasure",
|
||||
"loser", "lose", "scum"
|
||||
};
|
||||
|
||||
m_LizardmanSpeech.Syllables = new string[]
|
||||
{
|
||||
"ss", "sth", "iss", "is", "ith", "kth",
|
||||
"sith", "this", "its", "sit", "tis", "tsi",
|
||||
"ssi", "sil", "lis", "sis", "lil", "thil",
|
||||
"lith", "sthi", "lish", "shi", "shash", "sal",
|
||||
"miss", "ra", "tha", "thes", "ses", "sas", "las",
|
||||
"les", "sath", "sia", "ais", "isa", "asi", "asth",
|
||||
"stha", "sthi", "isth", "asa", "ath", "tha", "als",
|
||||
"sla", "thth", "ci", "ce", "cy", "yss", "ys", "yth",
|
||||
"syth", "thys", "yts", "syt", "tys", "tsy", "ssy",
|
||||
"syl", "lys", "sys", "lyl", "thyl", "lyth", "sthy",
|
||||
"lysh", "shy", "myss", "ysa", "sthy", "ysth"
|
||||
};
|
||||
}
|
||||
|
||||
return m_LizardmanSpeech;
|
||||
}
|
||||
}
|
||||
|
||||
private static InhumanSpeech m_WispSpeech;
|
||||
|
||||
public static InhumanSpeech Wisp
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_WispSpeech == null )
|
||||
{
|
||||
m_WispSpeech = new InhumanSpeech();
|
||||
|
||||
m_WispSpeech.Hue = 89;
|
||||
m_WispSpeech.Sound = 466;
|
||||
|
||||
m_WispSpeech.Flags = IHSFlags.OnMovement;
|
||||
|
||||
m_WispSpeech.Syllables = new string[]
|
||||
{
|
||||
"b", "c", "d", "f", "g", "h", "i",
|
||||
"j", "k", "l", "m", "n", "p", "r",
|
||||
"s", "t", "v", "w", "x", "z", "c",
|
||||
"c", "x", "x", "x", "x", "x", "y",
|
||||
"y", "y", "y", "t", "t", "k", "k",
|
||||
"l", "l", "m", "m", "m", "m", "z"
|
||||
};
|
||||
}
|
||||
|
||||
return m_WispSpeech;
|
||||
}
|
||||
}
|
||||
|
||||
private string[] m_Syllables;
|
||||
private string[] m_Keywords;
|
||||
private string[] m_Responses;
|
||||
|
||||
private Dictionary<string, string> m_KeywordHash;
|
||||
|
||||
private int m_Hue;
|
||||
private int m_Sound;
|
||||
|
||||
private IHSFlags m_Flags;
|
||||
|
||||
public string[] Syllables
|
||||
{
|
||||
get{ return m_Syllables; }
|
||||
set{ m_Syllables = value; }
|
||||
}
|
||||
|
||||
public string[] Keywords
|
||||
{
|
||||
get{ return m_Keywords; }
|
||||
set
|
||||
{
|
||||
m_Keywords = value;
|
||||
m_KeywordHash = new Dictionary<string, string>( m_Keywords.Length, StringComparer.OrdinalIgnoreCase );
|
||||
for ( int i = 0; i < m_Keywords.Length; ++i )
|
||||
m_KeywordHash[m_Keywords[i]] = m_Keywords[i];
|
||||
}
|
||||
}
|
||||
|
||||
public string[] Responses
|
||||
{
|
||||
get{ return m_Responses; }
|
||||
set{ m_Responses = value; }
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get{ return m_Hue; }
|
||||
set{ m_Hue = value; }
|
||||
}
|
||||
|
||||
public int Sound
|
||||
{
|
||||
get{ return m_Sound; }
|
||||
set{ m_Sound = value; }
|
||||
}
|
||||
|
||||
public IHSFlags Flags
|
||||
{
|
||||
get{ return m_Flags; }
|
||||
set{ m_Flags = value; }
|
||||
}
|
||||
|
||||
public string GetRandomSyllable()
|
||||
{
|
||||
return m_Syllables[Utility.Random( m_Syllables.Length )];
|
||||
}
|
||||
|
||||
public string ConstructWord( int syllableCount )
|
||||
{
|
||||
string[] syllables = new string[syllableCount];
|
||||
|
||||
for ( int i = 0; i < syllableCount; ++i )
|
||||
syllables[i] = GetRandomSyllable();
|
||||
|
||||
return String.Concat( syllables );
|
||||
}
|
||||
|
||||
public string ConstructSentance( int wordCount )
|
||||
{
|
||||
StringBuilder sentance = new StringBuilder();
|
||||
|
||||
bool needUpperCase = true;
|
||||
|
||||
for ( int i = 0; i < wordCount; ++i )
|
||||
{
|
||||
if ( i > 0 ) // not first word )
|
||||
{
|
||||
int random = Utility.RandomMinMax( 1, 15 );
|
||||
|
||||
if ( random < 11 )
|
||||
{
|
||||
sentance.Append( ' ' );
|
||||
}
|
||||
else
|
||||
{
|
||||
needUpperCase = true;
|
||||
|
||||
if ( random > 13 )
|
||||
sentance.Append( "! " );
|
||||
else
|
||||
sentance.Append( ". " );
|
||||
}
|
||||
}
|
||||
|
||||
int syllableCount;
|
||||
|
||||
if ( 30 > Utility.Random( 100 ) )
|
||||
syllableCount = Utility.Random( 1, 5 );
|
||||
else
|
||||
syllableCount = Utility.Random( 1, 3 );
|
||||
|
||||
string word = ConstructWord( syllableCount );
|
||||
|
||||
sentance.Append( word );
|
||||
|
||||
if ( needUpperCase )
|
||||
sentance.Replace( word[0], Char.ToUpper( word[0] ), sentance.Length - word.Length, 1 );
|
||||
|
||||
needUpperCase = false;
|
||||
}
|
||||
|
||||
if ( Utility.RandomMinMax( 1, 5 ) == 1 )
|
||||
sentance.Append( '!' );
|
||||
else
|
||||
sentance.Append( '.' );
|
||||
|
||||
return sentance.ToString();
|
||||
}
|
||||
|
||||
public void SayRandomTranslate( Mobile mob, params string[] sentancesInEnglish )
|
||||
{
|
||||
SaySentance( mob, Utility.RandomMinMax( 2, 3 ) );
|
||||
mob.Say( sentancesInEnglish[Utility.Random( sentancesInEnglish.Length )] );
|
||||
}
|
||||
|
||||
private string GetRandomResponseWord( List<string> keywordsFound )
|
||||
{
|
||||
int random = Utility.Random( keywordsFound.Count + m_Responses.Length );
|
||||
|
||||
if ( random < keywordsFound.Count )
|
||||
return keywordsFound[random];
|
||||
|
||||
return m_Responses[random - keywordsFound.Count];
|
||||
}
|
||||
|
||||
public bool OnSpeech( Mobile mob, Mobile speaker, string text )
|
||||
{
|
||||
if ( (m_Flags & IHSFlags.OnSpeech) == 0 || m_Keywords == null || m_Responses == null || m_KeywordHash == null )
|
||||
return false; // not enabled
|
||||
|
||||
if ( !speaker.Alive )
|
||||
return false;
|
||||
|
||||
if ( !speaker.InRange( mob, 3 ) )
|
||||
return false;
|
||||
|
||||
if ( (speaker.Direction & Direction.Mask) != speaker.GetDirectionTo( mob ) )
|
||||
return false;
|
||||
|
||||
if ( (mob.Direction & Direction.Mask) != mob.GetDirectionTo( speaker ) )
|
||||
return false;
|
||||
|
||||
string[] split = text.Split( ' ' );
|
||||
List<string> keywordsFound = new List<string>();
|
||||
|
||||
for ( int i = 0; i < split.Length; ++i )
|
||||
{
|
||||
string keyword;
|
||||
m_KeywordHash.TryGetValue( split[i], out keyword );
|
||||
|
||||
if ( keyword != null )
|
||||
keywordsFound.Add( keyword );
|
||||
}
|
||||
|
||||
if ( keywordsFound.Count > 0 )
|
||||
{
|
||||
string responseWord;
|
||||
|
||||
if ( Utility.RandomBool() )
|
||||
responseWord = GetRandomResponseWord( keywordsFound );
|
||||
else
|
||||
responseWord = keywordsFound[Utility.Random( keywordsFound.Count )];
|
||||
|
||||
string secondResponseWord = GetRandomResponseWord( keywordsFound );
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
||||
switch ( Utility.Random( 6 ) )
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
{
|
||||
response.Append( "Me " ).Append( responseWord ).Append( '?' );
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
response.Append( responseWord ).Append( " thee!" );
|
||||
response.Replace( responseWord[0], Char.ToUpper( responseWord[0] ), 0, 1 );
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
response.Append( responseWord ).Append( '?' );
|
||||
response.Replace( responseWord[0], Char.ToUpper( responseWord[0] ), 0, 1 );
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
response.Append( responseWord ).Append( "! " ).Append( secondResponseWord ).Append( '.' );
|
||||
response.Replace( responseWord[0], Char.ToUpper( responseWord[0] ), 0, 1 );
|
||||
response.Replace( secondResponseWord[0], Char.ToUpper( secondResponseWord[0] ), responseWord.Length + 2, 1 );
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
response.Append( responseWord ).Append( '.' );
|
||||
response.Replace( responseWord[0], Char.ToUpper( responseWord[0] ), 0, 1 );
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
response.Append( responseWord ).Append( "? " ).Append( secondResponseWord ).Append( '.' );
|
||||
response.Replace( responseWord[0], Char.ToUpper( responseWord[0] ), 0, 1 );
|
||||
response.Replace( secondResponseWord[0], Char.ToUpper( secondResponseWord[0] ), responseWord.Length + 2, 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int maxWords = (split.Length / 2) + 1;
|
||||
|
||||
if ( maxWords < 2 )
|
||||
maxWords = 2;
|
||||
else if ( maxWords > 6 )
|
||||
maxWords = 6;
|
||||
|
||||
SaySentance( mob, Utility.RandomMinMax( 2, maxWords ) );
|
||||
mob.Say( response.ToString() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnDeath( Mobile mob )
|
||||
{
|
||||
if ( (m_Flags & IHSFlags.OnDeath) == 0 )
|
||||
return; // not enabled
|
||||
|
||||
if ( 90 > Utility.Random( 100 ) )
|
||||
return; // 90% chance to do nothing; 10% chance to talk
|
||||
|
||||
SayRandomTranslate( mob,
|
||||
"Revenge!",
|
||||
"NOOooo!",
|
||||
"I... I...",
|
||||
"Me no die!",
|
||||
"Me die!",
|
||||
"Must... not die...",
|
||||
"Oooh, me hurt...",
|
||||
"Me dying?" );
|
||||
}
|
||||
|
||||
public void OnMovement( Mobile mob, Mobile mover, Point3D oldLocation )
|
||||
{
|
||||
if ( (m_Flags & IHSFlags.OnMovement) == 0 )
|
||||
return; // not enabled
|
||||
|
||||
if ( !mover.Player || (mover.Hidden && mover.AccessLevel > AccessLevel.Player) )
|
||||
return;
|
||||
|
||||
if ( !mob.InRange( mover, 5 ) || mob.InRange( oldLocation, 5 ) )
|
||||
return; // only talk when they enter 5 tile range
|
||||
|
||||
if ( 90 > Utility.Random( 100 ) )
|
||||
return; // 90% chance to do nothing; 10% chance to talk
|
||||
|
||||
SaySentance( mob, 6 );
|
||||
}
|
||||
|
||||
public void OnDamage( Mobile mob, int amount )
|
||||
{
|
||||
if ( (m_Flags & IHSFlags.OnDamaged) == 0 )
|
||||
return; // not enabled
|
||||
|
||||
if ( 90 > Utility.Random( 100 ) )
|
||||
return; // 90% chance to do nothing; 10% chance to talk
|
||||
|
||||
if ( amount < 5 )
|
||||
{
|
||||
SayRandomTranslate( mob,
|
||||
"Ouch!",
|
||||
"Me not hurt bad!",
|
||||
"Thou fight bad.",
|
||||
"Thy blows soft!",
|
||||
"You bad with weapon!" );
|
||||
}
|
||||
else
|
||||
{
|
||||
SayRandomTranslate( mob,
|
||||
"Ouch! Me hurt!",
|
||||
"No, kill me not!",
|
||||
"Me hurt!",
|
||||
"Away with thee!",
|
||||
"Oof! That hurt!",
|
||||
"Aaah! That hurt...",
|
||||
"Good blow!" );
|
||||
}
|
||||
}
|
||||
|
||||
public void OnConstruct( Mobile mob )
|
||||
{
|
||||
mob.SpeechHue = m_Hue;
|
||||
}
|
||||
|
||||
public void SaySentance( Mobile mob, int wordCount )
|
||||
{
|
||||
mob.Say( ConstructSentance( wordCount ) );
|
||||
mob.PlaySound( m_Sound );
|
||||
}
|
||||
|
||||
public InhumanSpeech()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
44
Scripts/Misc/Keywords.cs
Normal file
44
Scripts/Misc/Keywords.cs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Guilds;
|
||||
using Server.Mobiles;
|
||||
using Server.Gumps;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Keywords
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
// Register our speech handler
|
||||
EventSink.Speech += new SpeechEventHandler( EventSink_Speech );
|
||||
}
|
||||
|
||||
public static void EventSink_Speech( SpeechEventArgs args )
|
||||
{
|
||||
Mobile from = args.Mobile;
|
||||
int[] keywords = args.Keywords;
|
||||
|
||||
for ( int i = 0; i < keywords.Length; ++i )
|
||||
{
|
||||
switch ( keywords[i] )
|
||||
{
|
||||
case 0x002A: // *i resign from my guild*
|
||||
{
|
||||
if ( from.Guild != null )
|
||||
((Guild)from.Guild).RemoveMember( from );
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x0032: // *i must consider my sins*
|
||||
{
|
||||
from.SendMessage( "Long Term Murders : {0}", from.Kills );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
375
Scripts/Misc/LanguageStatistics.cs
Normal file
375
Scripts/Misc/LanguageStatistics.cs
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Server;
|
||||
using Server.Accounting;
|
||||
using Server.Commands;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
/**
|
||||
* This file requires to be saved in a Unicode
|
||||
* compatible format.
|
||||
*
|
||||
* Warning: if you change String.Format methods,
|
||||
* please note that the following character
|
||||
* is suggested before any left-to-right text
|
||||
* in order to prevent undesired formatting
|
||||
* resulting from mixing LR and RL text:
|
||||
*
|
||||
* Use this one if you need to force RL:
|
||||
*
|
||||
* If you do not see the above chars, please
|
||||
* enable showing of unicode control chars
|
||||
**/
|
||||
|
||||
public class LanguageStatistics
|
||||
{
|
||||
struct InternationalCode
|
||||
{
|
||||
string m_Code;
|
||||
string m_Language;
|
||||
string m_Country;
|
||||
string m_Language_LocalName;
|
||||
string m_Country_LocalName;
|
||||
bool m_HasLocalInfo;
|
||||
|
||||
public string Code{ get{ return m_Code; } }
|
||||
public string Language{ get{ return m_Language; } }
|
||||
public string Country{ get{ return m_Country; } }
|
||||
public string Language_LocalName{ get{ return m_Language_LocalName; } }
|
||||
public string Country_LocalName{ get{ return m_Country_LocalName; } }
|
||||
|
||||
public InternationalCode( string code, string language, string country ) : this( code, language, country, null, null )
|
||||
{
|
||||
m_HasLocalInfo = false;
|
||||
}
|
||||
|
||||
public InternationalCode( string code, string language, string country, string language_localname, string country_localname )
|
||||
{
|
||||
m_Code = code;
|
||||
m_Language = language;
|
||||
m_Country = country;
|
||||
m_Language_LocalName = language_localname;
|
||||
m_Country_LocalName = country_localname;
|
||||
m_HasLocalInfo = true;
|
||||
}
|
||||
|
||||
public string GetName()
|
||||
{
|
||||
string s;
|
||||
|
||||
if ( m_HasLocalInfo )
|
||||
{
|
||||
s = String.Format( "{0} - {1}", DefaultLocalNames ? m_Language_LocalName : m_Language, DefaultLocalNames ? m_Country_LocalName : m_Country );
|
||||
|
||||
if ( ShowAlternatives )
|
||||
s += String.Format( " 【{0} - {1}】", DefaultLocalNames ? m_Language : m_Language_LocalName, DefaultLocalNames ? m_Country : m_Country_LocalName );
|
||||
}
|
||||
else
|
||||
{
|
||||
s = String.Format( "{0} - {1}", m_Language, m_Country );
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
private static InternationalCode[] InternationalCodes =
|
||||
{
|
||||
new InternationalCode( "ARA", "Arabic", "Saudi Arabia", "العربية", "السعودية" ),
|
||||
new InternationalCode( "ARI", "Arabic", "Iraq", "العربية", "العراق" ),
|
||||
new InternationalCode( "ARE", "Arabic", "Egypt", "العربية", "مصر" ),
|
||||
new InternationalCode( "ARL", "Arabic", "Libya", "العربية", "ليبيا" ),
|
||||
new InternationalCode( "ARG", "Arabic", "Algeria", "العربية", "الجزائر" ),
|
||||
new InternationalCode( "ARM", "Arabic", "Morocco", "العربية", "المغرب" ),
|
||||
new InternationalCode( "ART", "Arabic", "Tunisia", "العربية", "تونس" ),
|
||||
new InternationalCode( "ARO", "Arabic", "Oman", "العربية", "عمان" ),
|
||||
new InternationalCode( "ARY", "Arabic", "Yemen", "العربية", "اليمن" ),
|
||||
new InternationalCode( "ARS", "Arabic", "Syria", "العربية", "سورية" ),
|
||||
new InternationalCode( "ARJ", "Arabic", "Jordan", "العربية", "الأردن" ),
|
||||
new InternationalCode( "ARB", "Arabic", "Lebanon", "العربية", "لبنان" ),
|
||||
new InternationalCode( "ARK", "Arabic", "Kuwait", "العربية", "الكويت" ),
|
||||
new InternationalCode( "ARU", "Arabic", "U.A.E.", "العربية", "الامارات" ),
|
||||
new InternationalCode( "ARH", "Arabic", "Bahrain", "العربية", "البحرين" ),
|
||||
new InternationalCode( "ARQ", "Arabic", "Qatar", "العربية", "قطر" ),
|
||||
new InternationalCode( "BGR", "Bulgarian", "Bulgaria", "Български", "България" ),
|
||||
new InternationalCode( "CAT", "Catalan", "Spain", "Català", "Espanya" ),
|
||||
new InternationalCode( "CHT", "Chinese", "Taiwan", "台語", "臺灣" ),
|
||||
new InternationalCode( "CHS", "Chinese", "PRC", "中文", "中国" ),
|
||||
new InternationalCode( "ZHH", "Chinese", "Hong Kong", "中文", "香港" ),
|
||||
new InternationalCode( "ZHI", "Chinese", "Singapore", "中文", "新加坡" ),
|
||||
new InternationalCode( "ZHM", "Chinese", "Macau", "中文", "澳門" ),
|
||||
new InternationalCode( "CSY", "Czech", "Czech Republic", "Čeština", "Česká republika" ),
|
||||
new InternationalCode( "DAN", "Danish", "Denmark", "Dansk", "Danmark" ),
|
||||
new InternationalCode( "DEU", "German", "Germany", "Deutsch", "Deutschland" ),
|
||||
new InternationalCode( "DES", "German", "Switzerland", "Deutsch", "der Schweiz" ),
|
||||
new InternationalCode( "DEA", "German", "Austria", "Deutsch", "Österreich" ),
|
||||
new InternationalCode( "DEL", "German", "Luxembourg", "Deutsch", "Luxembourg" ),
|
||||
new InternationalCode( "DEC", "German", "Liechtenstein", "Deutsch", "Liechtenstein" ),
|
||||
new InternationalCode( "ELL", "Greek", "Greece", "Ελληνικά", "Ελλάδα" ),
|
||||
new InternationalCode( "ENU", "English", "United States" ),
|
||||
new InternationalCode( "ENG", "English", "United Kingdom" ),
|
||||
new InternationalCode( "ENA", "English", "Australia" ),
|
||||
new InternationalCode( "ENC", "English", "Canada" ),
|
||||
new InternationalCode( "ENZ", "English", "New Zealand" ),
|
||||
new InternationalCode( "ENI", "English", "Ireland" ),
|
||||
new InternationalCode( "ENS", "English", "South Africa" ),
|
||||
new InternationalCode( "ENJ", "English", "Jamaica" ),
|
||||
new InternationalCode( "ENB", "English", "Caribbean" ),
|
||||
new InternationalCode( "ENL", "English", "Belize" ),
|
||||
new InternationalCode( "ENT", "English", "Trinidad" ),
|
||||
new InternationalCode( "ENW", "English", "Zimbabwe" ),
|
||||
new InternationalCode( "ENP", "English", "Philippines" ),
|
||||
new InternationalCode( "ESP", "Spanish", "Spain (Traditional Sort)", "Español", "España (tipo tradicional)" ),
|
||||
new InternationalCode( "ESM", "Spanish", "Mexico", "Español", "México" ),
|
||||
new InternationalCode( "ESN", "Spanish", "Spain (International Sort)", "Español", "España (tipo internacional)" ),
|
||||
new InternationalCode( "ESG", "Spanish", "Guatemala", "Español", "Guatemala" ),
|
||||
new InternationalCode( "ESC", "Spanish", "Costa Rica", "Español", "Costa Rica" ),
|
||||
new InternationalCode( "ESA", "Spanish", "Panama", "Español", "Panama" ),
|
||||
new InternationalCode( "ESD", "Spanish", "Dominican Republic", "Español", "Republica Dominicana" ),
|
||||
new InternationalCode( "ESV", "Spanish", "Venezuela", "Español", "Venezuela" ),
|
||||
new InternationalCode( "ESO", "Spanish", "Colombia", "Español", "Colombia" ),
|
||||
new InternationalCode( "ESR", "Spanish", "Peru", "Español", "Peru" ),
|
||||
new InternationalCode( "ESS", "Spanish", "Argentina", "Español", "Argentina" ),
|
||||
new InternationalCode( "ESF", "Spanish", "Ecuador", "Español", "Ecuador" ),
|
||||
new InternationalCode( "ESL", "Spanish", "Chile", "Español", "Chile" ),
|
||||
new InternationalCode( "ESY", "Spanish", "Uruguay", "Español", "Uruguay" ),
|
||||
new InternationalCode( "ESZ", "Spanish", "Paraguay", "Español", "Paraguay" ),
|
||||
new InternationalCode( "ESB", "Spanish", "Bolivia", "Español", "Bolivia" ),
|
||||
new InternationalCode( "ESE", "Spanish", "El Salvador", "Español", "El Salvador" ),
|
||||
new InternationalCode( "ESH", "Spanish", "Honduras", "Español", "Honduras" ),
|
||||
new InternationalCode( "ESI", "Spanish", "Nicaragua", "Español", "Nicaragua" ),
|
||||
new InternationalCode( "ESU", "Spanish", "Puerto Rico", "Español", "Puerto Rico" ),
|
||||
new InternationalCode( "FIN", "Finnish", "Finland", "Suomi", "Suomi" ),
|
||||
new InternationalCode( "FRA", "French", "France", "Français", "France" ),
|
||||
new InternationalCode( "FRB", "French", "Belgium", "Français", "Belgique" ),
|
||||
new InternationalCode( "FRC", "French", "Canada", "Français", "Canada" ),
|
||||
new InternationalCode( "FRS", "French", "Switzerland", "Français", "Suisse" ),
|
||||
new InternationalCode( "FRL", "French", "Luxembourg", "Français", "Luxembourg" ),
|
||||
new InternationalCode( "FRM", "French", "Monaco", "Français", "Monaco" ),
|
||||
new InternationalCode( "HEB", "Hebrew", "Israel", "עִבְרִית", "ישׂראל" ),
|
||||
new InternationalCode( "HUN", "Hungarian", "Hungary", "Magyar", "Magyarország" ),
|
||||
new InternationalCode( "ISL", "Icelandic", "Iceland", "Íslenska", "Ísland" ),
|
||||
new InternationalCode( "ITA", "Italian", "Italy", "Italiano", "Italia" ),
|
||||
new InternationalCode( "ITS", "Italian", "Switzerland", "Italiano", "Svizzera" ),
|
||||
new InternationalCode( "JPN", "Japanese", "Japan", "日本語", "日本" ),
|
||||
new InternationalCode( "KOR", "Korean (Extended Wansung)", "Korea", "한국어", "한국" ),
|
||||
new InternationalCode( "NLD", "Dutch", "Netherlands", "Nederlands", "Nederland" ),
|
||||
new InternationalCode( "NLB", "Dutch", "Belgium", "Nederlands", "België" ),
|
||||
new InternationalCode( "NOR", "Norwegian", "Norway (Bokmål)", "Norsk", "Norge (Bokmål)" ),
|
||||
new InternationalCode( "NON", "Norwegian", "Norway (Nynorsk)", "Norsk", "Norge (Nynorsk)" ),
|
||||
new InternationalCode( "PLK", "Polish", "Poland", "Polski", "Polska" ),
|
||||
new InternationalCode( "PTB", "Portuguese", "Brazil", "Português", "Brasil" ),
|
||||
new InternationalCode( "PTG", "Portuguese", "Portugal", "Português", "Brasil" ),
|
||||
new InternationalCode( "ROM", "Romanian", "Romania", "Limba Română", "România" ),
|
||||
new InternationalCode( "RUS", "Russian", "Russia", "Русский", "Россия" ),
|
||||
new InternationalCode( "HRV", "Croatian", "Croatia", "Hrvatski", "Hrvatska" ),
|
||||
new InternationalCode( "SRL", "Serbian", "Serbia (Latin)", "Srpski", "Srbija i Crna Gora" ),
|
||||
new InternationalCode( "SRB", "Serbian", "Serbia (Cyrillic)", "Српски", "Србија и Црна Гора" ),
|
||||
new InternationalCode( "SKY", "Slovak", "Slovakia", "Slovenčina", "Slovensko" ),
|
||||
new InternationalCode( "SQI", "Albanian", "Albania", "Shqip", "Shqipëria" ),
|
||||
new InternationalCode( "SVE", "Swedish", "Sweden", "Svenska", "Sverige" ),
|
||||
new InternationalCode( "SVF", "Swedish", "Finland", "Svenska", "Finland" ),
|
||||
new InternationalCode( "THA", "Thai", "Thailand", "ภาษาไทย", "ประเทศไทย" ),
|
||||
new InternationalCode( "TRK", "Turkish", "Turkey", "Türkçe", "Türkiye" ),
|
||||
new InternationalCode( "URP", "Urdu", "Pakistan", "اردو", "پاکستان" ),
|
||||
new InternationalCode( "IND", "Indonesian", "Indonesia", "Bahasa Indonesia", "Indonesia" ),
|
||||
new InternationalCode( "UKR", "Ukrainian", "Ukraine", "Українська", "Украина" ),
|
||||
new InternationalCode( "BEL", "Belarusian", "Belarus", "Беларускі", "Беларусь" ),
|
||||
new InternationalCode( "SLV", "Slovene", "Slovenia", "Slovenščina", "Slovenija" ),
|
||||
new InternationalCode( "ETI", "Estonian", "Estonia", "Eesti", "Eesti" ),
|
||||
new InternationalCode( "LVI", "Latvian", "Latvia", "Latviešu", "Latvija" ),
|
||||
new InternationalCode( "LTH", "Lithuanian", "Lithuania", "Lietuvių", "Lietuva" ),
|
||||
new InternationalCode( "LTC", "Classic Lithuanian", "Lithuania", "Lietuviškai", "Lietuva" ),
|
||||
new InternationalCode( "FAR", "Farsi", "Iran", "فارسى", "ايران" ),
|
||||
new InternationalCode( "VIT", "Vietnamese", "Viet Nam", "tiếng Việt", "Việt Nam" ),
|
||||
new InternationalCode( "HYE", "Armenian", "Armenia", "Հայերէն", "Հայաստան" ),
|
||||
new InternationalCode( "AZE", "Azeri", "Azerbaijan (Latin)", "Azərbaycanca", "Azərbaycan" ),
|
||||
new InternationalCode( "AZE", "Azeri", "Azerbaijan (Cyrillic)", "Азәрбајҹанҹа", "Азәрбајҹан" ),
|
||||
new InternationalCode( "EUQ", "Basque", "Spain", "Euskera", "Espainia" ),
|
||||
new InternationalCode( "MKI", "Macedonian", "Macedonia", "Македонски", "Македонија" ),
|
||||
new InternationalCode( "AFK", "Afrikaans", "South Africa", "Afrikaans", "Republiek van Suid-Afrika" ),
|
||||
new InternationalCode( "KAT", "Georgian", "Georgia", "ქართული", "საკარტველო" ),
|
||||
new InternationalCode( "FOS", "Faeroese", "Faeroe Islands", "Føroyska", "Føroya" ),
|
||||
new InternationalCode( "HIN", "Hindi", "India", "हिन्दी", "भारत" ),
|
||||
new InternationalCode( "MSL", "Malay", "Malaysia", "Bahasa melayu", "Malaysia" ),
|
||||
new InternationalCode( "MSB", "Malay", "Brunei Darussalam", "Bahasa melayu", "Negara Brunei Darussalam" ),
|
||||
new InternationalCode( "KAZ", "Kazak", "Kazakstan", "Қазақ", "Қазақстан" ),
|
||||
new InternationalCode( "SWK", "Swahili", "Kenya", "Kiswahili", "Kenya" ),
|
||||
new InternationalCode( "UZB", "Uzbek", "Uzbekistan (Latin)", "O'zbek", "O'zbekiston" ),
|
||||
new InternationalCode( "UZB", "Uzbek", "Uzbekistan (Cyrillic)", "Ўзбек", "Ўзбекистон" ),
|
||||
new InternationalCode( "TAT", "Tatar", "Tatarstan", "Татарча", "Татарстан" ),
|
||||
new InternationalCode( "BEN", "Bengali", "India", "বাংলা", "ভারত" ),
|
||||
new InternationalCode( "PAN", "Punjabi", "India", "ਪੰਜਾਬੀ", "ਭਾਰਤ" ),
|
||||
new InternationalCode( "GUJ", "Gujarati", "India", "ગુજરાતી", "ભારત" ),
|
||||
new InternationalCode( "ORI", "Oriya", "India", "ଓଡ଼ିଆ", "ଭାରତ" ),
|
||||
new InternationalCode( "TAM", "Tamil", "India", "தமிழ்", "இந்தியா" ),
|
||||
new InternationalCode( "TEL", "Telugu", "India", "తెలుగు", "భారత" ),
|
||||
new InternationalCode( "KAN", "Kannada", "India", "ಕನ್ನಡ", "ಭಾರತ" ),
|
||||
new InternationalCode( "MAL", "Malayalam", "India", "മലയാളം", "ഭാരത" ),
|
||||
new InternationalCode( "ASM", "Assamese", "India", "অসমিয়া", "Bhārat" ), // missing correct country name
|
||||
new InternationalCode( "MAR", "Marathi", "India", "मराठी", "भारत" ),
|
||||
new InternationalCode( "SAN", "Sanskrit", "India", "संस्कृत", "भारतम्" ),
|
||||
new InternationalCode( "KOK", "Konkani", "India", "कोंकणी", "भारत" )
|
||||
};
|
||||
|
||||
private static string GetFormattedInfo( string code )
|
||||
{
|
||||
if ( code == null || code.Length != 3 )
|
||||
return String.Format( "Unknown code {0}", code );
|
||||
|
||||
for ( int i = 0; i < InternationalCodes.Length; i++ )
|
||||
{
|
||||
if ( code == InternationalCodes[i].Code )
|
||||
{
|
||||
return String.Format( "{0}", InternationalCodes[i].GetName() );
|
||||
}
|
||||
}
|
||||
|
||||
return String.Format( "Unknown code {0}", code );
|
||||
}
|
||||
|
||||
private static bool DefaultLocalNames = false;
|
||||
private static bool ShowAlternatives = true;
|
||||
private static bool CountAccounts = true; // will consider only first character's valid language
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register( "LanguageStatistics", AccessLevel.Administrator, new CommandEventHandler( LanguageStatistics_OnCommand ) );
|
||||
}
|
||||
|
||||
[Usage( "LanguageStatistics" )]
|
||||
[Description( "Generate a file containing the list of languages for each PlayerMobile." )]
|
||||
public static void LanguageStatistics_OnCommand( CommandEventArgs e )
|
||||
{
|
||||
Dictionary<string, InternationalCodeCounter> ht = new Dictionary<string, InternationalCodeCounter>();
|
||||
|
||||
using ( StreamWriter writer = new StreamWriter( "languages.txt" ) )
|
||||
{
|
||||
if ( CountAccounts )
|
||||
{
|
||||
// count accounts
|
||||
foreach ( Account acc in Accounts.GetAccounts() )
|
||||
{
|
||||
for ( int i = 0; i < acc.Length; i++ )
|
||||
{
|
||||
Mobile mob = acc[i];
|
||||
|
||||
if ( mob == null )
|
||||
continue;
|
||||
|
||||
string lang = mob.Language;
|
||||
|
||||
if ( lang != null )
|
||||
{
|
||||
lang = lang.ToUpper();
|
||||
|
||||
if ( !ht.ContainsKey( lang ) )
|
||||
ht[lang] = new InternationalCodeCounter( lang );
|
||||
else
|
||||
ht[lang].Increase();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// count playermobiles
|
||||
foreach( Mobile mob in World.Mobiles.Values )
|
||||
{
|
||||
if ( mob.Player )
|
||||
{
|
||||
string lang = mob.Language;
|
||||
|
||||
if ( lang != null )
|
||||
{
|
||||
lang = lang.ToUpper();
|
||||
|
||||
if ( !ht.ContainsKey( lang ) )
|
||||
ht[lang] = new InternationalCodeCounter( lang );
|
||||
else
|
||||
ht[lang].Increase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine( String.Format( "Language statistics. Numbers show how many {0} use the specified language.", CountAccounts ? "accounts" : "playermobile" ) );
|
||||
writer.WriteLine( "====================================================================================================" );
|
||||
writer.WriteLine();
|
||||
|
||||
// sort the list
|
||||
List<InternationalCodeCounter> list = new List<InternationalCodeCounter>( ht.Values );
|
||||
list.Sort( InternationalCodeComparer.Instance );
|
||||
|
||||
foreach ( InternationalCodeCounter c in list )
|
||||
writer.WriteLine( String.Format( "{0} : {1}", GetFormattedInfo( c.Code ), c.Count ) );
|
||||
|
||||
e.Mobile.SendMessage( "Languages list generated." );
|
||||
}
|
||||
}
|
||||
|
||||
private class InternationalCodeCounter
|
||||
{
|
||||
private string m_Code;
|
||||
private int m_Count;
|
||||
|
||||
public string Code{ get{ return m_Code; } }
|
||||
public int Count{ get{ return m_Count; } }
|
||||
|
||||
public InternationalCodeCounter( string code )
|
||||
{
|
||||
m_Code = code;
|
||||
m_Count = 1;
|
||||
}
|
||||
|
||||
public void Increase()
|
||||
{
|
||||
m_Count++;
|
||||
}
|
||||
}
|
||||
|
||||
private class InternationalCodeComparer : IComparer<InternationalCodeCounter>
|
||||
{
|
||||
public static readonly InternationalCodeComparer Instance = new InternationalCodeComparer();
|
||||
|
||||
public InternationalCodeComparer()
|
||||
{
|
||||
}
|
||||
|
||||
public int Compare( InternationalCodeCounter x, InternationalCodeCounter y )
|
||||
{
|
||||
string a = null, b = null;
|
||||
int ca = 0, cb = 0;
|
||||
|
||||
a = x.Code;
|
||||
ca = x.Count;
|
||||
b = y.Code;
|
||||
cb = y.Count;
|
||||
|
||||
|
||||
if ( ca > cb )
|
||||
return -1;
|
||||
|
||||
if ( ca < cb )
|
||||
return 1;
|
||||
|
||||
if ( a == null && b == null )
|
||||
return 0;
|
||||
|
||||
if ( a == null )
|
||||
return 1;
|
||||
|
||||
if ( b == null )
|
||||
return -1;
|
||||
|
||||
return a.CompareTo( b );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
140
Scripts/Misc/LightCycle.cs
Normal file
140
Scripts/Misc/LightCycle.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class LightCycle
|
||||
{
|
||||
public const int DayLevel = 0;
|
||||
public const int NightLevel = 12;
|
||||
public const int DungeonLevel = 26;
|
||||
public const int CaveLevel = 20;
|
||||
|
||||
private static int m_LevelOverride = int.MinValue;
|
||||
|
||||
public static int LevelOverride
|
||||
{
|
||||
get{ return m_LevelOverride; }
|
||||
set
|
||||
{
|
||||
m_LevelOverride = value;
|
||||
|
||||
for ( int i = 0; i < NetState.Instances.Count; ++i )
|
||||
{
|
||||
NetState ns = NetState.Instances[i];
|
||||
Mobile m = ns.Mobile;
|
||||
|
||||
if ( m != null )
|
||||
m.CheckLightLevels( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
new LightCycleTimer().Start();
|
||||
EventSink.Login += new LoginEventHandler( OnLogin );
|
||||
|
||||
CommandSystem.Register( "GlobalLight", AccessLevel.GameMaster, new CommandEventHandler( Light_OnCommand ) );
|
||||
}
|
||||
|
||||
[Usage( "GlobalLight <value>" )]
|
||||
[Description( "Sets the current global light level." )]
|
||||
private static void Light_OnCommand( CommandEventArgs e )
|
||||
{
|
||||
if ( e.Length >= 1 )
|
||||
{
|
||||
LevelOverride = e.GetInt32( 0 );
|
||||
e.Mobile.SendMessage( "Global light level override has been changed to {0}.", m_LevelOverride );
|
||||
}
|
||||
else
|
||||
{
|
||||
LevelOverride = int.MinValue;
|
||||
e.Mobile.SendMessage( "Global light level override has been cleared." );
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnLogin( LoginEventArgs args )
|
||||
{
|
||||
Mobile m = args.Mobile;
|
||||
|
||||
m.CheckLightLevels( true );
|
||||
}
|
||||
|
||||
public static int ComputeLevelFor( Mobile from )
|
||||
{
|
||||
if ( m_LevelOverride > int.MinValue )
|
||||
return m_LevelOverride;
|
||||
|
||||
int hours, minutes;
|
||||
|
||||
Server.Items.Clock.GetTime( from.Map, 3584, 2048, out hours, out minutes );
|
||||
|
||||
/* OSI times:
|
||||
*
|
||||
* Midnight -> 3:59 AM : Night
|
||||
* 4:00 AM -> 11:59 PM : Day
|
||||
*
|
||||
* RunUO times:
|
||||
*
|
||||
* 10:00 PM -> 11:59 PM : Scale to night
|
||||
* Midnight -> 3:59 AM : Night
|
||||
* 4:00 AM -> 5:59 AM : Scale to day
|
||||
* 6:00 AM -> 9:59 PM : Day
|
||||
*/
|
||||
|
||||
if ( hours < 4 )
|
||||
return NightLevel;
|
||||
|
||||
if ( hours < 6 )
|
||||
return NightLevel + (((((hours - 4) * 60) + minutes) * (DayLevel - NightLevel)) / 120);
|
||||
|
||||
if ( hours < 22 )
|
||||
return DayLevel;
|
||||
|
||||
if ( hours < 24 )
|
||||
return DayLevel + (((((hours - 22) * 60) + minutes) * (NightLevel - DayLevel)) / 120);
|
||||
|
||||
return NightLevel; // should never be
|
||||
}
|
||||
|
||||
private class LightCycleTimer : Timer
|
||||
{
|
||||
public LightCycleTimer() : base( TimeSpan.FromSeconds( 0 ), TimeSpan.FromSeconds( 5.0 ) )
|
||||
{
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
for ( int i = 0; i < NetState.Instances.Count; ++i )
|
||||
{
|
||||
NetState ns = NetState.Instances[i];
|
||||
Mobile m = ns.Mobile;
|
||||
|
||||
if ( m != null )
|
||||
m.CheckLightLevels( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class NightSightTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
|
||||
public NightSightTimer( Mobile owner ) : base( TimeSpan.FromMinutes( Utility.Random( 15, 25 ) ) )
|
||||
{
|
||||
m_Owner = owner;
|
||||
Priority = TimerPriority.OneMinute;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Owner.EndAction( typeof( LightCycle ) );
|
||||
m_Owner.LightLevel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Scripts/Misc/LoginStats.cs
Normal file
32
Scripts/Misc/LoginStats.cs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class LoginStats
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
// Register our event handler
|
||||
EventSink.Login += new LoginEventHandler( EventSink_Login );
|
||||
}
|
||||
|
||||
private static void EventSink_Login( LoginEventArgs args )
|
||||
{
|
||||
int userCount = NetState.Instances.Count;
|
||||
int itemCount = World.Items.Count;
|
||||
int mobileCount = World.Mobiles.Count;
|
||||
|
||||
Mobile m = args.Mobile;
|
||||
|
||||
/*
|
||||
m.SendMessage( "Welcome, {0}! There {1} currently {2} user{3} online, with {4} item{5} and {6} mobile{7} in the world.",
|
||||
args.Mobile.Name,
|
||||
userCount == 1 ? "is" : "are",
|
||||
userCount, userCount == 1 ? "" : "s",
|
||||
itemCount, itemCount == 1 ? "" : "s",
|
||||
mobileCount, mobileCount == 1 ? "" : "s" );
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
52
Scripts/Misc/MapDefinitions.cs
Normal file
52
Scripts/Misc/MapDefinitions.cs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class MapDefinitions
|
||||
{
|
||||
public static void Configure()
|
||||
{
|
||||
/* Here we configure all maps. Some notes:
|
||||
*
|
||||
* 1) The first 32 maps are reserved for core use.
|
||||
* 2) Map 0x7F is reserved for core use.
|
||||
* 3) Map 0xFF is reserved for core use.
|
||||
* 4) Changing or removing any predefined maps may cause server instability.
|
||||
*/
|
||||
|
||||
RegisterMap( 0, 0, 0, 7168, 4096, 1, "Britannia", MapRules.DangerRules );
|
||||
RegisterMap( 1, 1, 1, 7168, 4096, 1, "Underworld", MapRules.DangerRules );
|
||||
RegisterMap( 2, 2, 2, 2304, 1600, 1, "Darkness", MapRules.DangerRules );
|
||||
RegisterMap( 3, 3, 3, 2560, 2048, 1, "Ocean", MapRules.DangerRules );
|
||||
RegisterMap( 4, 4, 4, 1448, 1448, 1, "Grassland", MapRules.DangerRules );
|
||||
|
||||
RegisterMap( 0x7F, 0x7F, 0x7F, Map.SectorSize, Map.SectorSize, 1, "Internal", MapRules.Internal );
|
||||
|
||||
/* Example of registering a custom map:
|
||||
* RegisterMap( 32, 0, 0, 6144, 4096, 3, "Iceland", MapRules.DangerRules );
|
||||
*
|
||||
* Defined:
|
||||
* RegisterMap( <index>, <mapID>, <fileIndex>, <width>, <height>, <season>, <name>, <rules> );
|
||||
* - <index> : An unreserved unique index for this map
|
||||
* - <mapID> : An identification number used in client communications. For any visible maps, this value must be from 0-3
|
||||
* - <fileIndex> : A file identification number. For any visible maps, this value must be 0, 2, 3, or 4
|
||||
* - <width>, <height> : Size of the map (in tiles)
|
||||
* - <name> : Reference name for the map, used in props gump, get/set commands, region loading, etc
|
||||
* - <rules> : Rules and restrictions associated with the map. See documentation for details
|
||||
*/
|
||||
|
||||
TileMatrixPatch.Enabled = true; // OSI Client Patch 6.0.0.0
|
||||
|
||||
MultiComponentList.PostHSFormat = false; // OSI Client Patch 7.0.9.0
|
||||
}
|
||||
|
||||
public static void RegisterMap( int mapIndex, int mapID, int fileIndex, int width, int height, int season, string name, MapRules rules )
|
||||
{
|
||||
Map newMap = new Map( mapID, mapIndex, fileIndex, width, height, season, name, rules );
|
||||
|
||||
Map.Maps[mapIndex] = newMap;
|
||||
Map.AllMaps.Add( newMap );
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Scripts/Misc/NameList.cs
Normal file
109
Scripts/Misc/NameList.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using Server;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class NameList
|
||||
{
|
||||
private string m_Type;
|
||||
private string[] m_List;
|
||||
|
||||
public string Type{ get{ return m_Type; } }
|
||||
public string[] List{ get{ return m_List; } }
|
||||
|
||||
public bool ContainsName( string name )
|
||||
{
|
||||
for ( int i = 0; i < m_List.Length; i++ )
|
||||
if ( name == m_List[i] )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public NameList( string type, XmlElement xml )
|
||||
{
|
||||
m_Type = type;
|
||||
m_List = xml.InnerText.Split( ',' );
|
||||
|
||||
for ( int i = 0; i < m_List.Length; ++i )
|
||||
m_List[i] = Utility.Intern( m_List[i].Trim() );
|
||||
}
|
||||
|
||||
public string GetRandomName()
|
||||
{
|
||||
if ( m_List.Length > 0 )
|
||||
return m_List[Utility.Random( m_List.Length )];
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static NameList GetNameList( string type )
|
||||
{
|
||||
NameList n = null;
|
||||
m_Table.TryGetValue( type, out n );
|
||||
return n;
|
||||
}
|
||||
|
||||
public static string RandomName( string type )
|
||||
{
|
||||
NameList list = GetNameList( type );
|
||||
|
||||
if ( list != null )
|
||||
return list.GetRandomName();
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private static Dictionary<string, NameList> m_Table;
|
||||
|
||||
static NameList()
|
||||
{
|
||||
m_Table = new Dictionary<string, NameList>( StringComparer.OrdinalIgnoreCase );
|
||||
|
||||
string filePath = Path.Combine( Core.BaseDirectory, "Data/Config/names.xml" );
|
||||
|
||||
if ( !File.Exists( filePath ) )
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Load( filePath );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Console.WriteLine( "Warning: Exception caught loading name lists:" );
|
||||
Console.WriteLine( e );
|
||||
}
|
||||
}
|
||||
|
||||
private static void Load( string filePath )
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
doc.Load( filePath );
|
||||
|
||||
XmlElement root = doc["names"];
|
||||
|
||||
foreach ( XmlElement element in root.GetElementsByTagName( "namelist" ) )
|
||||
{
|
||||
string type = element.GetAttribute( "type" );
|
||||
|
||||
if ( String.IsNullOrEmpty( type ) )
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
NameList list = new NameList( type, element );
|
||||
|
||||
m_Table[type] = list;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
207
Scripts/Misc/NameVerification.cs
Normal file
207
Scripts/Misc/NameVerification.cs
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class NameVerification
|
||||
{
|
||||
public static readonly char[] SpaceDashPeriodQuote = new char[]
|
||||
{
|
||||
' ', '-', '.', '\''
|
||||
};
|
||||
|
||||
public static readonly char[] Empty = new char[0];
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register( "ValidateName", AccessLevel.Administrator, new CommandEventHandler( ValidateName_OnCommand ) );
|
||||
}
|
||||
|
||||
[Usage( "ValidateName" )]
|
||||
[Description( "Checks the result of NameValidation on the specified name." )]
|
||||
public static void ValidateName_OnCommand( CommandEventArgs e )
|
||||
{
|
||||
if ( Validate( e.ArgString, 2, 16, true, false, true, 1, SpaceDashPeriodQuote ) )
|
||||
e.Mobile.SendMessage( 0x59, "That name is considered valid." );
|
||||
else
|
||||
e.Mobile.SendMessage( 0x22, "That name is considered invalid." );
|
||||
}
|
||||
|
||||
public static bool Validate( string name, int minLength, int maxLength, bool allowLetters, bool allowDigits, bool noExceptionsAtStart, int maxExceptions, char[] exceptions )
|
||||
{
|
||||
return Validate( name, minLength, maxLength, allowLetters, allowDigits, noExceptionsAtStart, maxExceptions, exceptions, m_Disallowed, m_StartDisallowed );
|
||||
}
|
||||
|
||||
public static bool Validate( string name, int minLength, int maxLength, bool allowLetters, bool allowDigits, bool noExceptionsAtStart, int maxExceptions, char[] exceptions, string[] disallowed, string[] startDisallowed )
|
||||
{
|
||||
if ( name == null || name.Length < minLength || name.Length > maxLength )
|
||||
return false;
|
||||
|
||||
int exceptCount = 0;
|
||||
|
||||
name = name.ToLower();
|
||||
|
||||
if ( !allowLetters || !allowDigits || (exceptions.Length > 0 && (noExceptionsAtStart || maxExceptions < int.MaxValue)) )
|
||||
{
|
||||
for ( int i = 0; i < name.Length; ++i )
|
||||
{
|
||||
char c = name[i];
|
||||
|
||||
if ( c >= 'a' && c <= 'z' )
|
||||
{
|
||||
if ( !allowLetters )
|
||||
return false;
|
||||
|
||||
exceptCount = 0;
|
||||
}
|
||||
else if ( c >= '0' && c <= '9' )
|
||||
{
|
||||
if ( !allowDigits )
|
||||
return false;
|
||||
|
||||
exceptCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool except = false;
|
||||
|
||||
for ( int j = 0; !except && j < exceptions.Length; ++j )
|
||||
if ( c == exceptions[j] )
|
||||
except = true;
|
||||
|
||||
if ( !except || (i == 0 && noExceptionsAtStart) )
|
||||
return false;
|
||||
|
||||
if ( exceptCount++ == maxExceptions )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < disallowed.Length; ++i )
|
||||
{
|
||||
int indexOf = name.IndexOf( disallowed[i] );
|
||||
|
||||
if ( indexOf == -1 )
|
||||
continue;
|
||||
|
||||
bool badPrefix = ( indexOf == 0 );
|
||||
|
||||
for ( int j = 0; !badPrefix && j < exceptions.Length; ++j )
|
||||
badPrefix = ( name[indexOf - 1] == exceptions[j] );
|
||||
|
||||
if ( !badPrefix )
|
||||
continue;
|
||||
|
||||
bool badSuffix = ( (indexOf + disallowed[i].Length) >= name.Length );
|
||||
|
||||
for ( int j = 0; !badSuffix && j < exceptions.Length; ++j )
|
||||
badSuffix = ( name[indexOf + disallowed[i].Length] == exceptions[j] );
|
||||
|
||||
if ( badSuffix )
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < startDisallowed.Length; ++i )
|
||||
{
|
||||
if ( name.StartsWith( startDisallowed[i] ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string[] StartDisallowed { get { return m_StartDisallowed; } }
|
||||
public static string[] Disallowed { get { return m_Disallowed; } }
|
||||
|
||||
private static string[] m_StartDisallowed = new string[]
|
||||
{
|
||||
"seer",
|
||||
"counselor",
|
||||
"gm",
|
||||
"admin",
|
||||
"lady",
|
||||
"lord"
|
||||
};
|
||||
|
||||
private static string[] m_Disallowed = new string[]
|
||||
{
|
||||
"jigaboo",
|
||||
"chigaboo",
|
||||
"wop",
|
||||
"kyke",
|
||||
"kike",
|
||||
"tit",
|
||||
"spic",
|
||||
"prick",
|
||||
"piss",
|
||||
"lezbo",
|
||||
"lesbo",
|
||||
"felatio",
|
||||
"dyke",
|
||||
"dildo",
|
||||
"chinc",
|
||||
"chink",
|
||||
"cunnilingus",
|
||||
"cum",
|
||||
"cocksucker",
|
||||
"cock",
|
||||
"clitoris",
|
||||
"clit",
|
||||
"ass",
|
||||
"hitler",
|
||||
"penis",
|
||||
"nigga",
|
||||
"nigger",
|
||||
"klit",
|
||||
"kunt",
|
||||
"jiz",
|
||||
"jism",
|
||||
"jerkoff",
|
||||
"jackoff",
|
||||
"goddamn",
|
||||
"fag",
|
||||
"blowjob",
|
||||
"bitch",
|
||||
"asshole",
|
||||
"dick",
|
||||
"pussy",
|
||||
"snatch",
|
||||
"cunt",
|
||||
"twat",
|
||||
"shit",
|
||||
"fuck",
|
||||
"tailor",
|
||||
"smith",
|
||||
"scholar",
|
||||
"rogue",
|
||||
"novice",
|
||||
"neophyte",
|
||||
"merchant",
|
||||
"medium",
|
||||
"master",
|
||||
"mage",
|
||||
"lb",
|
||||
"journeyman",
|
||||
"grandmaster",
|
||||
"fisherman",
|
||||
"expert",
|
||||
"chef",
|
||||
"carpenter",
|
||||
"british",
|
||||
"blackthorne",
|
||||
"blackthorn",
|
||||
"beggar",
|
||||
"archer",
|
||||
"apprentice",
|
||||
"adept",
|
||||
"gamemaster",
|
||||
"frozen",
|
||||
"squelched",
|
||||
"invulnerable",
|
||||
"osi",
|
||||
"origin"
|
||||
};
|
||||
}
|
||||
}
|
||||
361
Scripts/Misc/Notoriety.cs
Normal file
361
Scripts/Misc/Notoriety.cs
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Guilds;
|
||||
using Server.Multis;
|
||||
using Server.Mobiles;
|
||||
using Server.Engines.PartySystem;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class NotorietyHandlers
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
Notoriety.Hues[Notoriety.Innocent] = 0x59;
|
||||
Notoriety.Hues[Notoriety.Ally] = 0x3F;
|
||||
Notoriety.Hues[Notoriety.CanBeAttacked] = 0x3B2;
|
||||
Notoriety.Hues[Notoriety.Criminal] = 0x3B2;
|
||||
Notoriety.Hues[Notoriety.Enemy] = 0x90;
|
||||
Notoriety.Hues[Notoriety.Murderer] = 0x22;
|
||||
Notoriety.Hues[Notoriety.Invulnerable] = 0x35;
|
||||
|
||||
Notoriety.Handler = new NotorietyHandler( MobileNotoriety );
|
||||
|
||||
Mobile.AllowBeneficialHandler = new AllowBeneficialHandler( Mobile_AllowBeneficial );
|
||||
Mobile.AllowHarmfulHandler = new AllowHarmfulHandler( Mobile_AllowHarmful );
|
||||
}
|
||||
|
||||
public static bool CriminalTolerated( Mobile m )
|
||||
{
|
||||
// Buc's Den
|
||||
if ( m.Map == Map.Britannia && m.X >= 2545 && m.Y >= 2100 && m.X <= 2702 && m.Y <= 2306 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private enum GuildStatus { None, Peaceful, Waring }
|
||||
|
||||
private static GuildStatus GetGuildStatus( Mobile m )
|
||||
{
|
||||
if( m.Guild == null )
|
||||
return GuildStatus.None;
|
||||
else if( ((Guild)m.Guild).Enemies.Count == 0 && m.Guild.Type == GuildType.Regular )
|
||||
return GuildStatus.Peaceful;
|
||||
|
||||
return GuildStatus.Waring;
|
||||
}
|
||||
|
||||
private static bool CheckBeneficialStatus( GuildStatus from, GuildStatus target )
|
||||
{
|
||||
if( from == GuildStatus.Waring || target == GuildStatus.Waring )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool Mobile_AllowBeneficial( Mobile from, Mobile target )
|
||||
{
|
||||
if( from == null || target == null || from.AccessLevel > AccessLevel.Player || target.AccessLevel > AccessLevel.Player )
|
||||
return true;
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if( map != null && (map.Rules & MapRules.BeneficialRestrictions) == 0 )
|
||||
return true;
|
||||
|
||||
if( !from.Player )
|
||||
return true; // NPCs have no restrictions
|
||||
|
||||
if( target is BaseCreature && !((BaseCreature)target).Controlled )
|
||||
return false; // Players cannot heal uncontrolled mobiles
|
||||
|
||||
Guild fromGuild = from.Guild as Guild;
|
||||
Guild targetGuild = target.Guild as Guild;
|
||||
|
||||
if( fromGuild != null && targetGuild != null && (targetGuild == fromGuild || fromGuild.IsAlly( targetGuild )) )
|
||||
return true; // Guild members can be beneficial
|
||||
|
||||
return CheckBeneficialStatus( GetGuildStatus( from ), GetGuildStatus( target ) );
|
||||
}
|
||||
|
||||
public static bool Mobile_AllowHarmful( Mobile from, Mobile target )
|
||||
{
|
||||
if( from == null || target == null || from.AccessLevel > AccessLevel.Player || target.AccessLevel > AccessLevel.Player )
|
||||
return true;
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if( map != null && (map.Rules & MapRules.HarmfulRestrictions) == 0 )
|
||||
return true;
|
||||
|
||||
BaseCreature bc = from as BaseCreature;
|
||||
|
||||
if( !from.Player && !(bc != null && bc.GetMaster() != null && bc.GetMaster().AccessLevel == AccessLevel.Player ) )
|
||||
{
|
||||
return true; // Uncontrolled NPCs are only restricted by the young system
|
||||
}
|
||||
|
||||
Guild fromGuild = GetGuildFor( from.Guild as Guild, from );
|
||||
Guild targetGuild = GetGuildFor( target.Guild as Guild, target );
|
||||
|
||||
if( fromGuild != null && targetGuild != null && (fromGuild == targetGuild || fromGuild.IsAlly( targetGuild ) || fromGuild.IsEnemy( targetGuild )) )
|
||||
return true; // Guild allies or enemies can be harmful
|
||||
|
||||
if( target is BaseCreature && (((BaseCreature)target).Controlled || (((BaseCreature)target).Summoned && from != ((BaseCreature)target).SummonMaster)) )
|
||||
return false; // Cannot harm other controlled mobiles
|
||||
|
||||
if( target.Player )
|
||||
return false; // Cannot harm other players
|
||||
|
||||
if( !(target is BaseCreature && ((BaseCreature)target).InitialInnocent) )
|
||||
{
|
||||
if( Notoriety.Compute( from, target ) == Notoriety.Innocent )
|
||||
return false; // Cannot harm innocent mobiles
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Guild GetGuildFor( Guild def, Mobile m )
|
||||
{
|
||||
Guild g = def;
|
||||
|
||||
BaseCreature c = m as BaseCreature;
|
||||
|
||||
if( c != null && c.Controlled && c.ControlMaster != null )
|
||||
{
|
||||
c.DisplayGuildTitle = false;
|
||||
|
||||
if( c.Map != Map.Internal && (Guild.NewGuildSystem || c.ControlOrder == OrderType.Attack || c.ControlOrder == OrderType.Guard) )
|
||||
g = (Guild)(c.Guild = c.ControlMaster.Guild);
|
||||
else if( c.Map == Map.Internal || c.ControlMaster.Guild == null )
|
||||
g = (Guild)(c.Guild = null);
|
||||
}
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
public static int CorpseNotoriety( Mobile source, Corpse target )
|
||||
{
|
||||
if( target.AccessLevel > AccessLevel.Player )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
Body body = (Body)target.Amount;
|
||||
|
||||
BaseCreature cretOwner = target.Owner as BaseCreature;
|
||||
|
||||
if( cretOwner != null )
|
||||
{
|
||||
Guild sourceGuild = GetGuildFor( source.Guild as Guild, source );
|
||||
Guild targetGuild = GetGuildFor( target.Guild as Guild, target.Owner );
|
||||
|
||||
if( sourceGuild != null && targetGuild != null )
|
||||
{
|
||||
if( sourceGuild == targetGuild || sourceGuild.IsAlly( targetGuild ) )
|
||||
return Notoriety.Ally;
|
||||
else if( sourceGuild.IsEnemy( targetGuild ) )
|
||||
return Notoriety.Enemy;
|
||||
}
|
||||
|
||||
if( CheckHouseFlag( source, target.Owner, target.Location, target.Map ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
int actual = Notoriety.CanBeAttacked;
|
||||
|
||||
if( target.Kills >= 5 || (body.IsMonster && IsSummoned( target.Owner as BaseCreature )) || (target.Owner is BaseCreature && ((BaseCreature)target.Owner).AlwaysMurderer) )
|
||||
actual = Notoriety.Murderer;
|
||||
|
||||
if( DateTime.Now >= (target.TimeOfDeath + Corpse.MonsterLootRightSacrifice) )
|
||||
return actual;
|
||||
|
||||
Party sourceParty = Party.Get( source );
|
||||
|
||||
List<Mobile> list = target.Aggressors;
|
||||
|
||||
for( int i = 0; i < list.Count; ++i )
|
||||
{
|
||||
if( list[i] == source || (sourceParty != null && Party.Get( list[i] ) == sourceParty) )
|
||||
return actual;
|
||||
}
|
||||
|
||||
return Notoriety.Innocent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( target.Kills >= 5 || (body.IsMonster && IsSummoned( target.Owner as BaseCreature )) || (target.Owner is BaseCreature && ((BaseCreature)target.Owner).AlwaysMurderer) )
|
||||
return Notoriety.Murderer;
|
||||
|
||||
if (target.Criminal && target.Map != null && ((target.Map.Rules & MapRules.HarmfulRestrictions) == 0))
|
||||
return Notoriety.Criminal;
|
||||
|
||||
Guild sourceGuild = GetGuildFor( source.Guild as Guild, source );
|
||||
Guild targetGuild = GetGuildFor( target.Guild as Guild, target.Owner );
|
||||
|
||||
if( sourceGuild != null && targetGuild != null )
|
||||
{
|
||||
if( sourceGuild == targetGuild || sourceGuild.IsAlly( targetGuild ) )
|
||||
return Notoriety.Ally;
|
||||
else if( sourceGuild.IsEnemy( targetGuild ) )
|
||||
return Notoriety.Enemy;
|
||||
}
|
||||
|
||||
if( target.Owner != null && target.Owner is BaseCreature && ((BaseCreature)target.Owner).AlwaysAttackable )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( CheckHouseFlag( source, target.Owner, target.Location, target.Map ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( !(target.Owner is PlayerMobile) && !IsPet( target.Owner as BaseCreature ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
List<Mobile> list = target.Aggressors;
|
||||
|
||||
for( int i = 0; i < list.Count; ++i )
|
||||
{
|
||||
if( list[i] == source )
|
||||
return Notoriety.CanBeAttacked;
|
||||
}
|
||||
|
||||
return Notoriety.Innocent;
|
||||
}
|
||||
}
|
||||
|
||||
public static int MobileNotoriety( Mobile source, Mobile target )
|
||||
{
|
||||
if( target is BaseCreature && target.Karma > 0 && target.Fame > 0 && !(target is Guard || target is BaseVendor) )
|
||||
return Notoriety.Innocent;
|
||||
|
||||
if( target is BaseCreature && ((BaseCreature)target).FightMode == FightMode.Evil && !(target is Guard || target is BaseVendor) )
|
||||
return Notoriety.Innocent;
|
||||
|
||||
if( target.AccessLevel > AccessLevel.Player )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( source.Player && !target.Player && source is PlayerMobile && target is BaseCreature )
|
||||
{
|
||||
BaseCreature bc = (BaseCreature)target;
|
||||
|
||||
Mobile master = bc.GetMaster();
|
||||
|
||||
if ( master != null && master.AccessLevel > AccessLevel.Player )
|
||||
return Notoriety.CanBeAttacked;
|
||||
}
|
||||
|
||||
if ( target.Kills >= 5 || ( target.Body.IsMonster && IsSummoned( target as BaseCreature ) && !( target is Golem ) ) || ( target is BaseCreature && ( ( (BaseCreature)target ).AlwaysMurderer ) ) )
|
||||
return Notoriety.Murderer;
|
||||
|
||||
if ( target is BaseCreature && ((BaseCreature)target).FightMode == FightMode.Closest && !(target is Guard) && ((BaseCreature)target).AI != AIType.AI_Animal )
|
||||
return Notoriety.Murderer;
|
||||
|
||||
if( target.Criminal )
|
||||
return Notoriety.Criminal;
|
||||
|
||||
Guild sourceGuild = GetGuildFor( source.Guild as Guild, source );
|
||||
Guild targetGuild = GetGuildFor( target.Guild as Guild, target );
|
||||
|
||||
if( sourceGuild != null && targetGuild != null )
|
||||
{
|
||||
if( sourceGuild == targetGuild || sourceGuild.IsAlly( targetGuild ) )
|
||||
return Notoriety.Ally;
|
||||
else if( sourceGuild.IsEnemy( targetGuild ) )
|
||||
return Notoriety.Enemy;
|
||||
}
|
||||
|
||||
if( SkillHandlers.Stealing.ClassicMode && target is PlayerMobile && ((PlayerMobile)target).PermaFlags.Contains( source ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( target is BaseCreature && ((BaseCreature)target).AlwaysAttackable )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( CheckHouseFlag( source, target, target.Location, target.Map ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( !(target is BaseCreature && ((BaseCreature)target).InitialInnocent) ) //If Target is NOT A baseCreature, OR it's a BC and the BC is initial innocent...
|
||||
{
|
||||
if( !target.Body.IsHuman && !target.Body.IsGhost && !IsPet( target as BaseCreature ) && !(target is PlayerMobile) || !target.CanBeginAction( typeof( Server.Spells.Seventh.PolymorphSpell ) ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
}
|
||||
|
||||
if( CheckAggressor( source.Aggressors, target ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( CheckAggressed( source.Aggressed, target ) )
|
||||
return Notoriety.CanBeAttacked;
|
||||
|
||||
if( target is BaseCreature )
|
||||
{
|
||||
BaseCreature bc = (BaseCreature)target;
|
||||
|
||||
if( bc.Controlled && bc.ControlOrder == OrderType.Guard && bc.ControlTarget == source )
|
||||
return Notoriety.CanBeAttacked;
|
||||
}
|
||||
|
||||
if( source is BaseCreature )
|
||||
{
|
||||
BaseCreature bc = (BaseCreature)source;
|
||||
|
||||
Mobile master = bc.GetMaster();
|
||||
if( master != null )
|
||||
if( CheckAggressor( master.Aggressors, target ) || MobileNotoriety( master, target ) == Notoriety.CanBeAttacked )
|
||||
return Notoriety.CanBeAttacked;
|
||||
}
|
||||
|
||||
return Notoriety.Innocent;
|
||||
}
|
||||
|
||||
public static bool CheckHouseFlag( Mobile from, Mobile m, Point3D p, Map map )
|
||||
{
|
||||
BaseHouse house = BaseHouse.FindHouseAt( p, map, 16 );
|
||||
|
||||
if( house == null || house.Public || !house.IsFriend( from ) )
|
||||
return false;
|
||||
|
||||
if( m != null && house.IsFriend( m ) )
|
||||
return false;
|
||||
|
||||
BaseCreature c = m as BaseCreature;
|
||||
|
||||
if( c != null && !c.Deleted && c.Controlled && c.ControlMaster != null )
|
||||
return !house.IsFriend( c.ControlMaster );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsPet( BaseCreature c )
|
||||
{
|
||||
return (c != null && c.Controlled);
|
||||
}
|
||||
|
||||
public static bool IsSummoned( BaseCreature c )
|
||||
{
|
||||
return (c != null && /*c.Controlled &&*/ c.Summoned);
|
||||
}
|
||||
|
||||
public static bool CheckAggressor( List<AggressorInfo> list, Mobile target )
|
||||
{
|
||||
for( int i = 0; i < list.Count; ++i )
|
||||
if( list[i].Attacker == target )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CheckAggressed( List<AggressorInfo> list, Mobile target )
|
||||
{
|
||||
for( int i = 0; i < list.Count; ++i )
|
||||
{
|
||||
AggressorInfo info = list[i];
|
||||
|
||||
if( !info.CriminalAggression && info.Defender == target )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Scripts/Misc/Paperdoll.cs
Normal file
36
Scripts/Misc/Paperdoll.cs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
using Server.Multis;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Paperdoll
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.PaperdollRequest += new PaperdollRequestEventHandler( EventSink_PaperdollRequest );
|
||||
}
|
||||
|
||||
public static void EventSink_PaperdollRequest( PaperdollRequestEventArgs e )
|
||||
{
|
||||
Mobile beholder = e.Beholder;
|
||||
Mobile beheld = e.Beheld;
|
||||
|
||||
beholder.Send( new DisplayPaperdoll( beheld, Titles.ComputeTitle( beholder, beheld ), beheld.AllowEquipFrom( beholder ) ) );
|
||||
|
||||
if ( ObjectPropertyList.Enabled )
|
||||
{
|
||||
List<Item> items = beheld.Items;
|
||||
|
||||
for ( int i = 0; i < items.Count; ++i )
|
||||
beholder.Send( items[i].OPLPacket );
|
||||
|
||||
// NOTE: OSI sends MobileUpdate when opening your own paperdoll.
|
||||
// It has a very bad rubber-banding affect. What positive affects does it have?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
113
Scripts/Misc/Poison.cs
Normal file
113
Scripts/Misc/Poison.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class PoisonImpl : Poison
|
||||
{
|
||||
[CallPriority( 10 )]
|
||||
public static void Configure()
|
||||
{
|
||||
Register( new PoisonImpl( "Lesser", 0, 4, 26, 2.500, 3.5, 3.0, 10, 2 ) );
|
||||
Register( new PoisonImpl( "Regular", 1, 5, 26, 3.125, 3.5, 3.0, 10, 2 ) );
|
||||
Register( new PoisonImpl( "Greater", 2, 6, 26, 6.250, 3.5, 3.0, 10, 2 ) );
|
||||
Register( new PoisonImpl( "Deadly", 3, 7, 26, 12.500, 3.5, 4.0, 10, 2 ) );
|
||||
Register( new PoisonImpl( "Lethal", 4, 9, 26, 25.000, 3.5, 5.0, 10, 2 ) );
|
||||
}
|
||||
|
||||
public static Poison IncreaseLevel( Poison oldPoison )
|
||||
{
|
||||
Poison newPoison = ( oldPoison == null ? null : GetPoison( oldPoison.Level + 1 ) );
|
||||
|
||||
return ( newPoison == null ? oldPoison : newPoison );
|
||||
}
|
||||
|
||||
// Info
|
||||
private string m_Name;
|
||||
private int m_Level;
|
||||
|
||||
// Damage
|
||||
private int m_Minimum, m_Maximum;
|
||||
private double m_Scalar;
|
||||
|
||||
// Timers
|
||||
private TimeSpan m_Delay;
|
||||
private TimeSpan m_Interval;
|
||||
private int m_Count, m_MessageInterval;
|
||||
|
||||
public PoisonImpl( string name, int level, int min, int max, double percent, double delay, double interval, int count, int messageInterval )
|
||||
{
|
||||
m_Name = name;
|
||||
m_Level = level;
|
||||
m_Minimum = min;
|
||||
m_Maximum = max;
|
||||
m_Scalar = percent * 0.01;
|
||||
m_Delay = TimeSpan.FromSeconds( delay );
|
||||
m_Interval = TimeSpan.FromSeconds( interval );
|
||||
m_Count = count;
|
||||
m_MessageInterval = messageInterval;
|
||||
}
|
||||
|
||||
public override string Name{ get{ return m_Name; } }
|
||||
public override int Level{ get{ return m_Level; } }
|
||||
|
||||
public class PoisonTimer : Timer
|
||||
{
|
||||
private PoisonImpl m_Poison;
|
||||
private Mobile m_Mobile;
|
||||
private Mobile m_From;
|
||||
private int m_LastDamage;
|
||||
private int m_Index;
|
||||
|
||||
public Mobile From{ get{ return m_From; } set{ m_From = value; } }
|
||||
|
||||
public PoisonTimer( Mobile m, PoisonImpl p ) : base( p.m_Delay, p.m_Interval )
|
||||
{
|
||||
m_From = m;
|
||||
m_Mobile = m;
|
||||
m_Poison = p;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( m_Index++ == m_Poison.m_Count )
|
||||
{
|
||||
m_Mobile.SendLocalizedMessage( 502136 ); // The poison seems to have worn off.
|
||||
m_Mobile.Poison = null;
|
||||
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
int damage = 1 + (int)(m_Mobile.Hits * m_Poison.m_Scalar);
|
||||
|
||||
if ( damage < m_Poison.m_Minimum )
|
||||
damage = m_Poison.m_Minimum;
|
||||
else if ( damage > m_Poison.m_Maximum )
|
||||
damage = m_Poison.m_Maximum;
|
||||
|
||||
m_LastDamage = damage;
|
||||
|
||||
if ( m_From != null )
|
||||
m_From.DoHarmful( m_Mobile, true );
|
||||
|
||||
Ultima.Damage( m_Mobile, m_From, damage );
|
||||
|
||||
if ( 0.60 <= Utility.RandomDouble() ) // OSI: randomly revealed between first and third damage tick, guessing 60% chance
|
||||
m_Mobile.RevealingAction();
|
||||
|
||||
if ( (m_Index % m_Poison.m_MessageInterval) == 0 )
|
||||
m_Mobile.OnPoisoned( m_From, m_Poison, m_Poison );
|
||||
}
|
||||
}
|
||||
|
||||
public override Timer ConstructTimer( Mobile m )
|
||||
{
|
||||
return new PoisonTimer( m, this );
|
||||
}
|
||||
}
|
||||
}
|
||||
124
Scripts/Misc/ProfanityProtection.cs
Normal file
124
Scripts/Misc/ProfanityProtection.cs
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public enum ProfanityAction
|
||||
{
|
||||
None, // no action taken
|
||||
Disallow, // speech is not displayed
|
||||
Criminal, // makes the player criminal, not killable by guards
|
||||
CriminalAction, // makes the player criminal, can be killed by guards
|
||||
Disconnect, // player is kicked
|
||||
Other // some other implementation
|
||||
}
|
||||
|
||||
public class ProfanityProtection
|
||||
{
|
||||
private static bool Enabled = false;
|
||||
private static ProfanityAction Action = ProfanityAction.Disallow; // change here what to do when profanity is detected
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if ( Enabled )
|
||||
EventSink.Speech += new SpeechEventHandler( EventSink_Speech );
|
||||
}
|
||||
|
||||
private static bool OnProfanityDetected( Mobile from, string speech )
|
||||
{
|
||||
switch ( Action )
|
||||
{
|
||||
case ProfanityAction.None: return true;
|
||||
case ProfanityAction.Disallow: return false;
|
||||
case ProfanityAction.Criminal: from.Criminal = true; return true;
|
||||
case ProfanityAction.CriminalAction: from.CriminalAction( false ); return true;
|
||||
case ProfanityAction.Disconnect:
|
||||
{
|
||||
NetState ns = from.NetState;
|
||||
|
||||
if ( ns != null )
|
||||
ns.Dispose();
|
||||
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
case ProfanityAction.Other: // TODO: Provide custom implementation if this is chosen
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void EventSink_Speech( SpeechEventArgs e )
|
||||
{
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
if ( from.AccessLevel > AccessLevel.Player )
|
||||
return;
|
||||
|
||||
if ( !NameVerification.Validate( e.Speech, 0, int.MaxValue, true, true, false, int.MaxValue, m_Exceptions, m_Disallowed, m_StartDisallowed ) )
|
||||
e.Blocked = !OnProfanityDetected( from, e.Speech );
|
||||
}
|
||||
|
||||
public static char[] Exceptions{ get{ return m_Exceptions; } }
|
||||
public static string[] StartDisallowed{ get{ return m_StartDisallowed; } }
|
||||
public static string[] Disallowed{ get{ return m_Disallowed; } }
|
||||
|
||||
private static char[] m_Exceptions = new char[]
|
||||
{
|
||||
' ', '-', '.', '\'', '"', ',', '_', '+', '=', '~', '`', '!', '^', '*', '\\', '/', ';', ':', '<', '>', '[', ']', '{', '}', '?', '|', '(', ')', '%', '$', '&', '#', '@'
|
||||
};
|
||||
|
||||
private static string[] m_StartDisallowed = new string[]{};
|
||||
|
||||
private static string[] m_Disallowed = new string[]
|
||||
{
|
||||
"jigaboo",
|
||||
"chigaboo",
|
||||
"wop",
|
||||
"kyke",
|
||||
"kike",
|
||||
"tit",
|
||||
"spic",
|
||||
"prick",
|
||||
"piss",
|
||||
"lezbo",
|
||||
"lesbo",
|
||||
"felatio",
|
||||
"dyke",
|
||||
"dildo",
|
||||
"chinc",
|
||||
"chink",
|
||||
"cunnilingus",
|
||||
"cum",
|
||||
"cocksucker",
|
||||
"cock",
|
||||
"clitoris",
|
||||
"clit",
|
||||
"ass",
|
||||
"hitler",
|
||||
"penis",
|
||||
"nigga",
|
||||
"nigger",
|
||||
"klit",
|
||||
"kunt",
|
||||
"jiz",
|
||||
"jism",
|
||||
"jerkoff",
|
||||
"jackoff",
|
||||
"goddamn",
|
||||
"fag",
|
||||
"blowjob",
|
||||
"bitch",
|
||||
"asshole",
|
||||
"dick",
|
||||
"pussy",
|
||||
"snatch",
|
||||
"cunt",
|
||||
"twat",
|
||||
"shit",
|
||||
"fuck"
|
||||
};
|
||||
}
|
||||
}
|
||||
98
Scripts/Misc/Profile.cs
Normal file
98
Scripts/Misc/Profile.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
using Server.Accounting;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Profile
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.ProfileRequest += new ProfileRequestEventHandler( EventSink_ProfileRequest );
|
||||
EventSink.ChangeProfileRequest += new ChangeProfileRequestEventHandler( EventSink_ChangeProfileRequest );
|
||||
}
|
||||
|
||||
public static void EventSink_ChangeProfileRequest( ChangeProfileRequestEventArgs e )
|
||||
{
|
||||
Mobile from = e.Beholder;
|
||||
|
||||
if ( from.ProfileLocked )
|
||||
from.SendMessage( "Your profile is locked. You may not change it." );
|
||||
else
|
||||
from.Profile = e.Text;
|
||||
}
|
||||
|
||||
public static void EventSink_ProfileRequest( ProfileRequestEventArgs e )
|
||||
{
|
||||
Mobile beholder = e.Beholder;
|
||||
Mobile beheld = e.Beheld;
|
||||
|
||||
if ( !beheld.Player )
|
||||
return;
|
||||
|
||||
if ( beholder.Map != beheld.Map || !beholder.InRange( beheld, 12 ) || !beholder.CanSee( beheld ) )
|
||||
return;
|
||||
|
||||
string header = Titles.ComputeTitle( beholder, beheld );
|
||||
|
||||
string footer = "";
|
||||
|
||||
if ( beheld.ProfileLocked )
|
||||
{
|
||||
if ( beholder == beheld )
|
||||
footer = "Your profile has been locked.";
|
||||
else if ( beholder.AccessLevel >= AccessLevel.Counselor )
|
||||
footer = "This profile has been locked.";
|
||||
}
|
||||
|
||||
if ( footer.Length == 0 && beholder == beheld )
|
||||
footer = GetAccountDuration( beheld );
|
||||
|
||||
string body = beheld.Profile;
|
||||
|
||||
if ( body == null || body.Length <= 0 )
|
||||
body = "";
|
||||
|
||||
beholder.Send( new DisplayProfile( beholder != beheld || !beheld.ProfileLocked, beheld, header, body, footer ) );
|
||||
}
|
||||
|
||||
private static string GetAccountDuration( Mobile m )
|
||||
{
|
||||
Account a = m.Account as Account;
|
||||
|
||||
if ( a == null )
|
||||
return "";
|
||||
|
||||
TimeSpan ts = DateTime.Now - a.Created;
|
||||
|
||||
string v;
|
||||
|
||||
if ( Format( ts.TotalDays, "This account is {0} day{1} old.", out v ) )
|
||||
return v;
|
||||
|
||||
if ( Format( ts.TotalHours, "This account is {0} hour{1} old.", out v ) )
|
||||
return v;
|
||||
|
||||
if ( Format( ts.TotalMinutes, "This account is {0} minute{1} old.", out v ) )
|
||||
return v;
|
||||
|
||||
if ( Format( ts.TotalSeconds, "This account is {0} second{1} old.", out v ) )
|
||||
return v;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static bool Format( double value, string format, out string op )
|
||||
{
|
||||
if ( value >= 1.0 )
|
||||
{
|
||||
op = String.Format( format, (int)value, (int)value != 1 ? "s" : "" );
|
||||
return true;
|
||||
}
|
||||
|
||||
op = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
107
Scripts/Misc/ProtocolExtensions.cs
Normal file
107
Scripts/Misc/ProtocolExtensions.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
using Server.Engines.PartySystem;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class ProtocolExtensions
|
||||
{
|
||||
private static PacketHandler[] m_Handlers = new PacketHandler[0x100];
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
PacketHandlers.Register( 0xF0, 0, false, new OnPacketReceive( DecodeBundledPacket ) );
|
||||
|
||||
Register( 0x00, true, new OnPacketReceive( QueryPartyLocations ) );
|
||||
}
|
||||
|
||||
public static void QueryPartyLocations( NetState state, PacketReader pvSrc )
|
||||
{
|
||||
Mobile from = state.Mobile;
|
||||
Party party = Party.Get( from );
|
||||
|
||||
if ( party != null )
|
||||
{
|
||||
AckPartyLocations ack = new AckPartyLocations( from, party );
|
||||
|
||||
if ( ack.UnderlyingStream.Length > 8 )
|
||||
state.Send( ack );
|
||||
}
|
||||
}
|
||||
|
||||
public static void Register( int packetID, bool ingame, OnPacketReceive onReceive )
|
||||
{
|
||||
m_Handlers[packetID] = new PacketHandler( packetID, 0, ingame, onReceive );
|
||||
}
|
||||
|
||||
public static PacketHandler GetHandler( int packetID )
|
||||
{
|
||||
if ( packetID >= 0 && packetID < m_Handlers.Length )
|
||||
return m_Handlers[packetID];
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void DecodeBundledPacket( NetState state, PacketReader pvSrc )
|
||||
{
|
||||
int packetID = pvSrc.ReadByte();
|
||||
|
||||
PacketHandler ph = GetHandler( packetID );
|
||||
|
||||
if ( ph != null )
|
||||
{
|
||||
if ( ph.Ingame && state.Mobile == null )
|
||||
{
|
||||
Console.WriteLine( "Client: {0}: Sent ingame packet (0xF0x{1:X2}) before having been attached to a mobile", state, packetID );
|
||||
state.Dispose();
|
||||
}
|
||||
else if ( ph.Ingame && state.Mobile.Deleted )
|
||||
{
|
||||
state.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
ph.OnReceive( state, pvSrc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class ProtocolExtension : Packet
|
||||
{
|
||||
public ProtocolExtension( int packetID, int capacity ) : base( 0xF0 )
|
||||
{
|
||||
EnsureCapacity( 4 + capacity );
|
||||
|
||||
m_Stream.Write( (byte) packetID );
|
||||
}
|
||||
}
|
||||
|
||||
public class AckPartyLocations : ProtocolExtension
|
||||
{
|
||||
public AckPartyLocations( Mobile from, Party party ) : base( 0x01, ((party.Members.Count - 1) * 9) + 4 )
|
||||
{
|
||||
for ( int i = 0; i < party.Members.Count; ++i )
|
||||
{
|
||||
PartyMemberInfo pmi = (PartyMemberInfo)party.Members[i];
|
||||
|
||||
if ( pmi == null || pmi.Mobile == from )
|
||||
continue;
|
||||
|
||||
Mobile mob = pmi.Mobile;
|
||||
|
||||
if ( Utility.InUpdateRange( from, mob ) && from.CanSee( mob ) )
|
||||
continue;
|
||||
|
||||
m_Stream.Write( (int) mob.Serial );
|
||||
m_Stream.Write( (short) mob.X );
|
||||
m_Stream.Write( (short) mob.Y );
|
||||
m_Stream.Write( (byte) (mob.Map == null ? 0 : mob.Map.MapID) );
|
||||
}
|
||||
|
||||
m_Stream.Write( (int) 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
223
Scripts/Misc/RaceDefinitions.cs
Normal file
223
Scripts/Misc/RaceDefinitions.cs
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class RaceDefinitions
|
||||
{
|
||||
public static void Configure()
|
||||
{
|
||||
/* Here we configure all races. Some notes:
|
||||
*
|
||||
* 1) The first 32 races are reserved for core use.
|
||||
* 2) Race 0x7F is reserved for core use.
|
||||
* 3) Race 0xFF is reserved for core use.
|
||||
* 4) Changing or removing any predefined races may cause server instability.
|
||||
*/
|
||||
|
||||
RegisterRace( new Human ( 0, 0 ) );
|
||||
RegisterRace( new Orc ( 1, 1 ) );
|
||||
}
|
||||
|
||||
public static void RegisterRace( Race race )
|
||||
{
|
||||
Race.Races[race.RaceIndex] = race;
|
||||
Race.AllRaces.Add( race );
|
||||
}
|
||||
|
||||
private class Human : Race
|
||||
{
|
||||
public Human( int raceID, int raceIndex )
|
||||
: base( raceID, raceIndex, "Human", "Humans", 400, 401, 402, 403, Expansion.None )
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ValidateHair( bool female, int itemID )
|
||||
{
|
||||
if( itemID == 0 )
|
||||
return true;
|
||||
|
||||
if( (female && itemID == 0x2048) || (!female && itemID == 0x2046 ) )
|
||||
return false; //Buns & Receeding Hair
|
||||
|
||||
if( itemID >= 0x203B && itemID <= 0x203D )
|
||||
return true;
|
||||
|
||||
if( itemID >= 0x2044 && itemID <= 0x204A )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int RandomHair( bool female ) //Random hair doesn't include baldness
|
||||
{
|
||||
switch( Utility.Random( 9 ) )
|
||||
{
|
||||
case 0: return 0x203B; //Short
|
||||
case 1: return 0x203C; //Long
|
||||
case 2: return 0x203D; //Pony Tail
|
||||
case 3: return 0x2044; //Mohawk
|
||||
case 4: return 0x2045; //Pageboy
|
||||
case 5: return 0x2047; //Afro
|
||||
case 6: return 0x2049; //Pig tails
|
||||
case 7: return 0x204A; //Krisna
|
||||
default: return (female ? 0x2046 : 0x2048); //Buns or Receeding Hair
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ValidateFacialHair( bool female, int itemID )
|
||||
{
|
||||
if( itemID == 0 )
|
||||
return true;
|
||||
|
||||
if( female )
|
||||
return false;
|
||||
|
||||
if( itemID >= 0x203E && itemID <= 0x2041 )
|
||||
return true;
|
||||
|
||||
if( itemID >= 0x204B && itemID <= 0x204D )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int RandomFacialHair( bool female )
|
||||
{
|
||||
if( female )
|
||||
return 0;
|
||||
|
||||
int rand = Utility.Random( 7 );
|
||||
|
||||
return ((rand < 4) ? 0x203E : 0x2047) + rand;
|
||||
}
|
||||
|
||||
public override int ClipSkinHue( int hue )
|
||||
{
|
||||
if( hue < 1002 )
|
||||
return 1002;
|
||||
else if( hue > 1058 )
|
||||
return 1058;
|
||||
else
|
||||
return hue;
|
||||
}
|
||||
|
||||
public override int RandomSkinHue()
|
||||
{
|
||||
return Utility.Random( 1002, 57 ) | 0x8000;
|
||||
}
|
||||
|
||||
public override int ClipHairHue( int hue )
|
||||
{
|
||||
if( hue < 1102 )
|
||||
return 1102;
|
||||
else if( hue > 1149 )
|
||||
return 1149;
|
||||
else
|
||||
return hue;
|
||||
}
|
||||
|
||||
public override int RandomHairHue()
|
||||
{
|
||||
return Utility.Random( 1102, 48 );
|
||||
}
|
||||
}
|
||||
|
||||
private class Orc : Race
|
||||
{
|
||||
private static int[] m_SkinHues = new int[]
|
||||
{
|
||||
0x0BF, 0x24D, 0x24E, 0x24F, 0x353, 0x361, 0x367, 0x374,
|
||||
0x375, 0x376, 0x381, 0x382, 0x383, 0x384, 0x385, 0x389,
|
||||
0x3DE, 0x3E5, 0x3E6, 0x3E8, 0x3E9, 0x430, 0x4A7, 0x4DE,
|
||||
0x51D, 0x53F, 0x579, 0x76B, 0x76C, 0x76D, 0x835, 0x903
|
||||
};
|
||||
|
||||
private static int[] m_HairHues = new int[]
|
||||
{
|
||||
0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x058, 0x08E,
|
||||
0x08F, 0x090, 0x091, 0x092, 0x101, 0x159, 0x15A, 0x15B,
|
||||
0x15C, 0x15D, 0x15E, 0x128, 0x12F, 0x1BD, 0x1E4, 0x1F3,
|
||||
0x207, 0x211, 0x239, 0x251, 0x26C, 0x2C3, 0x2C9, 0x31D,
|
||||
0x31E, 0x31F, 0x320, 0x321, 0x322, 0x323, 0x324, 0x325,
|
||||
0x326, 0x369, 0x386, 0x387, 0x388, 0x389, 0x38A, 0x59D,
|
||||
0x6B8, 0x725, 0x853
|
||||
};
|
||||
|
||||
public Orc( int raceID, int raceIndex )
|
||||
: base( raceID, raceIndex, "Orc", "Orcs", 605, 606, 607, 608, Expansion.ML )
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ValidateHair( bool female, int itemID )
|
||||
{
|
||||
if( itemID == 0 )
|
||||
return true;
|
||||
|
||||
if( (female && (itemID == 0x2FCD || itemID == 0x2FBF)) || (!female && (itemID == 0x2FCC || itemID == 0x2FD0)) )
|
||||
return false;
|
||||
|
||||
if( itemID >= 0x2FBF && itemID <= 0x2FC2 )
|
||||
return true;
|
||||
|
||||
if( itemID >= 0x2FCC && itemID <= 0x2FD1 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int RandomHair( bool female ) //Random hair doesn't include baldness
|
||||
{
|
||||
switch( Utility.Random( 8 ) )
|
||||
{
|
||||
case 0: return 0x2FC0; //Long Feather
|
||||
case 1: return 0x2FC1; //Short
|
||||
case 2: return 0x2FC2; //Mullet
|
||||
case 3: return 0x2FCE; //Knob
|
||||
case 4: return 0x2FCF; //Braided
|
||||
case 5: return 0x2FD1; //Spiked
|
||||
case 6: return (female ? 0x2FCC : 0x2FBF); //Flower or Mid-long
|
||||
default: return (female ? 0x2FD0 : 0x2FCD); //Bun or Long
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ValidateFacialHair( bool female, int itemID )
|
||||
{
|
||||
return (itemID == 0);
|
||||
}
|
||||
|
||||
public override int RandomFacialHair( bool female )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override int ClipSkinHue( int hue )
|
||||
{
|
||||
for( int i = 0; i < m_SkinHues.Length; i++ )
|
||||
if( m_SkinHues[i] == hue )
|
||||
return hue;
|
||||
|
||||
return m_SkinHues[0];
|
||||
}
|
||||
|
||||
public override int RandomSkinHue()
|
||||
{
|
||||
return m_SkinHues[Utility.Random( m_SkinHues.Length )] | 0x8000;
|
||||
}
|
||||
|
||||
public override int ClipHairHue( int hue )
|
||||
{
|
||||
for( int i = 0; i < m_HairHues.Length; i++ )
|
||||
if( m_HairHues[i] == hue )
|
||||
return hue;
|
||||
|
||||
return m_HairHues[0];
|
||||
}
|
||||
|
||||
public override int RandomHairHue()
|
||||
{
|
||||
return m_HairHues[Utility.Random( m_HairHues.Length )];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
130
Scripts/Misc/RegenRates.cs
Normal file
130
Scripts/Misc/RegenRates.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Spells;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class RegenRates
|
||||
{
|
||||
[CallPriority( 10 )]
|
||||
public static void Configure()
|
||||
{
|
||||
Mobile.DefaultHitsRate = TimeSpan.FromSeconds( 11.0 );
|
||||
Mobile.DefaultStamRate = TimeSpan.FromSeconds( 7.0 );
|
||||
Mobile.DefaultManaRate = TimeSpan.FromSeconds( 7.0 );
|
||||
|
||||
Mobile.ManaRegenRateHandler = new RegenRateHandler( Mobile_ManaRegenRate );
|
||||
}
|
||||
|
||||
private static void CheckBonusSkill( Mobile m, int cur, int max, SkillName skill )
|
||||
{
|
||||
if ( !m.Alive )
|
||||
return;
|
||||
|
||||
double n = (double)cur / max;
|
||||
double v = Math.Sqrt( m.Skills[skill].Value * 0.005 );
|
||||
|
||||
n *= (1.0 - v);
|
||||
n += v;
|
||||
|
||||
m.CheckSkill( skill, n );
|
||||
}
|
||||
|
||||
private static TimeSpan Mobile_HitsRegenRate( Mobile from )
|
||||
{
|
||||
int points = 0;
|
||||
|
||||
if ( from is BaseCreature )
|
||||
points += 4;
|
||||
|
||||
if ( from is BaseCreature && from is Leviathan )
|
||||
points += 40;
|
||||
|
||||
if ( points < 0 )
|
||||
points = 0;
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 / (0.1 * (1 + points)) );
|
||||
}
|
||||
|
||||
private static TimeSpan Mobile_StamRegenRate( Mobile from )
|
||||
{
|
||||
if ( from.Skills == null )
|
||||
return Mobile.DefaultStamRate;
|
||||
|
||||
int points = 0;
|
||||
|
||||
if( from is BaseCreature && from is Leviathan )
|
||||
points += 40;
|
||||
|
||||
if ( points < -1 )
|
||||
points = -1;
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 / (0.1 * (2 + points)) );
|
||||
}
|
||||
|
||||
private static TimeSpan Mobile_ManaRegenRate( Mobile from )
|
||||
{
|
||||
if ( from.Skills == null )
|
||||
return Mobile.DefaultManaRate;
|
||||
|
||||
if ( !from.Meditating )
|
||||
CheckBonusSkill( from, from.Mana, from.ManaMax, SkillName.Meditation );
|
||||
|
||||
double rate;
|
||||
double armorPenalty = GetArmorOffset( from );
|
||||
|
||||
double medPoints = (from.Int + from.Skills[SkillName.Meditation].Value) * 0.5;
|
||||
|
||||
if ( medPoints <= 0 )
|
||||
rate = 7.0;
|
||||
else if ( medPoints <= 100 )
|
||||
rate = 7.0 - (239*medPoints/2400) + (19*medPoints*medPoints/48000);
|
||||
else if ( medPoints < 120 )
|
||||
rate = 1.0;
|
||||
else
|
||||
rate = 0.75;
|
||||
|
||||
rate += armorPenalty;
|
||||
|
||||
if ( from.Meditating )
|
||||
rate *= 0.5;
|
||||
|
||||
if ( rate < 0.5 )
|
||||
rate = 0.5;
|
||||
else if ( rate > 7.0 )
|
||||
rate = 7.0;
|
||||
|
||||
return TimeSpan.FromSeconds( rate );
|
||||
}
|
||||
|
||||
public static double GetArmorOffset( Mobile from )
|
||||
{
|
||||
double rating = GetArmorMeditationValue( from.ShieldArmor as BaseArmor );
|
||||
|
||||
if ( from.NeckArmor is BaseArmor ){ rating += GetArmorMeditationValue( from.NeckArmor as BaseArmor ); }
|
||||
if ( from.HandArmor is BaseArmor ){ rating += GetArmorMeditationValue( from.HandArmor as BaseArmor ); }
|
||||
if ( from.HeadArmor is BaseArmor ){ rating += GetArmorMeditationValue( from.HeadArmor as BaseArmor ); }
|
||||
if ( from.ArmsArmor is BaseArmor ){ rating += GetArmorMeditationValue( from.ArmsArmor as BaseArmor ); }
|
||||
if ( from.LegsArmor is BaseArmor ){ rating += GetArmorMeditationValue( from.LegsArmor as BaseArmor ); }
|
||||
if ( from.ChestArmor is BaseArmor ){ rating += GetArmorMeditationValue( from.ChestArmor as BaseArmor ); }
|
||||
|
||||
return rating / 4;
|
||||
}
|
||||
|
||||
private static double GetArmorMeditationValue( BaseArmor ar )
|
||||
{
|
||||
if ( ar == null )
|
||||
return 0.0;
|
||||
|
||||
switch ( ar.MeditationAllowance )
|
||||
{
|
||||
default:
|
||||
case ArmorMeditationAllowance.None: return ar.BaseArmorRatingScaled;
|
||||
case ArmorMeditationAllowance.Half: return ar.BaseArmorRatingScaled / 2.0;
|
||||
case ArmorMeditationAllowance.All: return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Scripts/Misc/RenameRequests.cs
Normal file
34
Scripts/Misc/RenameRequests.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using Server;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class RenameRequests
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.RenameRequest += new RenameRequestEventHandler( EventSink_RenameRequest );
|
||||
}
|
||||
|
||||
private static void EventSink_RenameRequest( RenameRequestEventArgs e )
|
||||
{
|
||||
Mobile from = e.From;
|
||||
Mobile targ = e.Target;
|
||||
string name = e.Name;
|
||||
|
||||
if ( from.CanSee( targ ) && from.InRange( targ, 12 ) && targ.CanBeRenamedBy( from ) )
|
||||
{
|
||||
name = name.Trim();
|
||||
|
||||
if( NameVerification.Validate( name, 1, 16, true, false, true, 0, NameVerification.Empty, NameVerification.StartDisallowed, ( new string[]{} ) ) )
|
||||
{
|
||||
targ.Name = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendMessage( "That name is unacceptable." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
302
Scripts/Misc/ResourceInfo.cs
Normal file
302
Scripts/Misc/ResourceInfo.cs
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public enum CraftResource
|
||||
{
|
||||
None = 0,
|
||||
Iron = 1,
|
||||
Leathered = 2,
|
||||
Wooden = 3
|
||||
}
|
||||
|
||||
public enum CraftResourceType
|
||||
{
|
||||
None,
|
||||
Metal,
|
||||
Leather,
|
||||
Wood
|
||||
}
|
||||
|
||||
public class CraftAttributeInfo
|
||||
{
|
||||
private int m_WeaponDurability;
|
||||
private int m_WeaponLowerRequirements;
|
||||
|
||||
private int m_ArmorDurability;
|
||||
private int m_ArmorLowerRequirements;
|
||||
|
||||
public int WeaponDurability{ get{ return m_WeaponDurability; } set{ m_WeaponDurability = value; } }
|
||||
public int WeaponLowerRequirements{ get{ return m_WeaponLowerRequirements; } set{ m_WeaponLowerRequirements = value; } }
|
||||
|
||||
public int ArmorDurability{ get{ return m_ArmorDurability; } set{ m_ArmorDurability = value; } }
|
||||
public int ArmorLowerRequirements{ get{ return m_ArmorLowerRequirements; } set{ m_ArmorLowerRequirements = value; } }
|
||||
|
||||
public CraftAttributeInfo()
|
||||
{
|
||||
}
|
||||
|
||||
public static readonly CraftAttributeInfo Blank;
|
||||
|
||||
static CraftAttributeInfo()
|
||||
{
|
||||
Blank = new CraftAttributeInfo();
|
||||
}
|
||||
}
|
||||
|
||||
public class CraftResourceInfo
|
||||
{
|
||||
private int m_Hue;
|
||||
private int m_Number;
|
||||
private string m_Name;
|
||||
private CraftAttributeInfo m_AttributeInfo;
|
||||
private CraftResource m_Resource;
|
||||
private Type[] m_ResourceTypes;
|
||||
|
||||
public int Hue{ get{ return m_Hue; } }
|
||||
public int Number{ get{ return m_Number; } }
|
||||
public string Name{ get{ return m_Name; } }
|
||||
public CraftAttributeInfo AttributeInfo{ get{ return m_AttributeInfo; } }
|
||||
public CraftResource Resource{ get{ return m_Resource; } }
|
||||
public Type[] ResourceTypes{ get{ return m_ResourceTypes; } }
|
||||
|
||||
public CraftResourceInfo( int hue, int number, string name, CraftAttributeInfo attributeInfo, CraftResource resource, params Type[] resourceTypes )
|
||||
{
|
||||
m_Hue = hue;
|
||||
m_Number = number;
|
||||
m_Name = name;
|
||||
m_AttributeInfo = attributeInfo;
|
||||
m_Resource = resource;
|
||||
m_ResourceTypes = resourceTypes;
|
||||
|
||||
for ( int i = 0; i < resourceTypes.Length; ++i )
|
||||
CraftResources.RegisterType( resourceTypes[i], resource );
|
||||
}
|
||||
}
|
||||
|
||||
public class CraftResources
|
||||
{
|
||||
private static CraftResourceInfo[] m_MetalInfo = new CraftResourceInfo[]
|
||||
{
|
||||
new CraftResourceInfo( 0x000, 1053109, "Iron", CraftAttributeInfo.Blank, CraftResource.Iron, typeof( IronIngot ), typeof( IronOre ) )
|
||||
};
|
||||
|
||||
private static CraftResourceInfo[] m_LeatherInfo = new CraftResourceInfo[]
|
||||
{
|
||||
new CraftResourceInfo( 0x000, 1049353, "Leather", CraftAttributeInfo.Blank, CraftResource.Leathered, typeof( Leather ), typeof( Hides ) )
|
||||
};
|
||||
|
||||
private static CraftResourceInfo[] m_WoodInfo = new CraftResourceInfo[]
|
||||
{
|
||||
new CraftResourceInfo( 0x000, 1011542, "Wood", CraftAttributeInfo.Blank, CraftResource.Wooden, typeof( WoodBoard ), typeof( WoodBoard ) )
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if '<paramref name="resource"/>' is None, Iron, Leathered or Wooden. False if otherwise.
|
||||
/// </summary>
|
||||
public static bool IsStandard( CraftResource resource )
|
||||
{
|
||||
return ( resource == CraftResource.None || resource == CraftResource.Iron || resource == CraftResource.Leathered || resource == CraftResource.Wooden );
|
||||
}
|
||||
|
||||
private static Hashtable m_TypeTable;
|
||||
|
||||
/// <summary>
|
||||
/// Registers that '<paramref name="resourceType"/>' uses '<paramref name="resource"/>' so that it can later be queried by <see cref="CraftResources.GetFromType"/>
|
||||
/// </summary>
|
||||
public static void RegisterType( Type resourceType, CraftResource resource )
|
||||
{
|
||||
if ( m_TypeTable == null )
|
||||
m_TypeTable = new Hashtable();
|
||||
|
||||
m_TypeTable[resourceType] = resource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="CraftResource"/> value for which '<paramref name="resourceType"/>' uses -or- CraftResource.None if an unregistered type was specified.
|
||||
/// </summary>
|
||||
public static CraftResource GetFromType( Type resourceType )
|
||||
{
|
||||
if ( m_TypeTable == null )
|
||||
return CraftResource.None;
|
||||
|
||||
object obj = m_TypeTable[resourceType];
|
||||
|
||||
if ( !(obj is CraftResource) )
|
||||
return CraftResource.None;
|
||||
|
||||
return (CraftResource)obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CraftResourceInfo"/> instance describing '<paramref name="resource"/>' -or- null if an invalid resource was specified.
|
||||
/// </summary>
|
||||
public static CraftResourceInfo GetInfo( CraftResource resource )
|
||||
{
|
||||
CraftResourceInfo[] list = null;
|
||||
|
||||
switch ( GetType( resource ) )
|
||||
{
|
||||
case CraftResourceType.Metal: list = m_MetalInfo; break;
|
||||
case CraftResourceType.Leather: list = m_LeatherInfo; break;
|
||||
case CraftResourceType.Wood: list = m_WoodInfo; break;
|
||||
}
|
||||
|
||||
if ( list != null )
|
||||
{
|
||||
int index = GetIndex( resource );
|
||||
|
||||
if ( index >= 0 && index < list.Length )
|
||||
return list[index];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CraftResourceType"/> value indiciating the type of '<paramref name="resource"/>'.
|
||||
/// </summary>
|
||||
public static CraftResourceType GetType( CraftResource resource )
|
||||
{
|
||||
if ( resource == CraftResource.Iron )
|
||||
return CraftResourceType.Metal;
|
||||
|
||||
if ( resource == CraftResource.Leathered )
|
||||
return CraftResourceType.Leather;
|
||||
|
||||
if ( resource == CraftResource.Wooden )
|
||||
return CraftResourceType.Wood;
|
||||
|
||||
return CraftResourceType.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the first <see cref="CraftResource"/> in the series of resources for which '<paramref name="resource"/>' belongs.
|
||||
/// </summary>
|
||||
public static CraftResource GetStart( CraftResource resource )
|
||||
{
|
||||
switch ( GetType( resource ) )
|
||||
{
|
||||
case CraftResourceType.Metal: return CraftResource.Iron;
|
||||
case CraftResourceType.Leather: return CraftResource.Leathered;
|
||||
case CraftResourceType.Wood: return CraftResource.Wooden;
|
||||
}
|
||||
|
||||
return CraftResource.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of '<paramref name="resource"/>' in the seriest of resources for which it belongs.
|
||||
/// </summary>
|
||||
public static int GetIndex( CraftResource resource )
|
||||
{
|
||||
CraftResource start = GetStart( resource );
|
||||
|
||||
if ( start == CraftResource.None )
|
||||
return 0;
|
||||
|
||||
return (int)(resource - start);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="CraftResourceInfo.Number"/> property of '<paramref name="resource"/>' -or- 0 if an invalid resource was specified.
|
||||
/// </summary>
|
||||
public static int GetLocalizationNumber( CraftResource resource )
|
||||
{
|
||||
CraftResourceInfo info = GetInfo( resource );
|
||||
|
||||
return ( info == null ? 0 : info.Number );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="CraftResourceInfo.Hue"/> property of '<paramref name="resource"/>' -or- 0 if an invalid resource was specified.
|
||||
/// </summary>
|
||||
public static int GetHue( CraftResource resource )
|
||||
{
|
||||
CraftResourceInfo info = GetInfo( resource );
|
||||
|
||||
return ( info == null ? 0 : info.Hue );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="CraftResourceInfo.Name"/> property of '<paramref name="resource"/>' -or- an empty string if the resource specified was invalid.
|
||||
/// </summary>
|
||||
public static string GetName( CraftResource resource )
|
||||
{
|
||||
CraftResourceInfo info = GetInfo( resource );
|
||||
|
||||
return ( info == null ? String.Empty : info.Name );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="CraftResource"/> value which represents '<paramref name="info"/>' -or- CraftResource.None if unable to convert.
|
||||
/// </summary>
|
||||
public static CraftResource GetFromOreInfo( OreInfo info )
|
||||
{
|
||||
if ( info.Name.IndexOf( "Wood" ) >= 0 )
|
||||
return CraftResource.Wooden;
|
||||
else if ( info.Name.IndexOf( "Leather" ) >= 0 )
|
||||
return CraftResource.Leathered;
|
||||
else if ( info.Name.IndexOf( "Iron" ) >= 0 )
|
||||
return CraftResource.Iron;
|
||||
|
||||
return CraftResource.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="CraftResource"/> value which represents '<paramref name="info"/>', using '<paramref name="material"/>' to help resolve leather OreInfo instances.
|
||||
/// </summary>
|
||||
public static CraftResource GetFromOreInfo( OreInfo info, ArmorMaterialType material )
|
||||
{
|
||||
if ( material == ArmorMaterialType.Studded || material == ArmorMaterialType.Leather )
|
||||
{
|
||||
return CraftResource.Leathered;
|
||||
}
|
||||
|
||||
return GetFromOreInfo( info );
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This class is only for compatability with very old RunUO versions.
|
||||
// No changes to it should be required for custom resources.
|
||||
public class OreInfo
|
||||
{
|
||||
public static readonly OreInfo Iron = new OreInfo( 0, 0x000, "Iron" );
|
||||
|
||||
private int m_Level;
|
||||
private int m_Hue;
|
||||
private string m_Name;
|
||||
|
||||
public OreInfo( int level, int hue, string name )
|
||||
{
|
||||
m_Level = level;
|
||||
m_Hue = hue;
|
||||
m_Name = name;
|
||||
}
|
||||
|
||||
public int Level
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Level;
|
||||
}
|
||||
}
|
||||
|
||||
public int Hue
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Hue;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return m_Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
176
Scripts/Misc/ServerList.cs
Normal file
176
Scripts/Misc/ServerList.cs
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class ServerList
|
||||
{
|
||||
/*
|
||||
* The default setting for Address, a value of 'null', will use your local IP address. If all of your local IP addresses
|
||||
* are private network addresses and AutoDetect is 'true' then RunUO will attempt to discover your public IP address
|
||||
* for you automatically.
|
||||
*
|
||||
* If you do not plan on allowing clients outside of your LAN to connect, you can set AutoDetect to 'false' and leave
|
||||
* Address set to 'null'.
|
||||
*
|
||||
* If your public IP address cannot be determined, you must change the value of Address to your public IP address
|
||||
* manually to allow clients outside of your LAN to connect to your server. Address can be either an IP address or
|
||||
* a hostname that will be resolved when RunUO starts.
|
||||
*
|
||||
* If you want players outside your LAN to be able to connect to your server and you are behind a router, you must also
|
||||
* forward TCP port 2593 to your private IP address. The procedure for doing this varies by manufacturer but generally
|
||||
* involves configuration of the router through your web browser.
|
||||
*
|
||||
* ServerList will direct connecting clients depending on both the address they are connecting from and the address and
|
||||
* port they are connecting to. If it is determined that both ends of a connection are private IP addresses, ServerList
|
||||
* will direct the client to the local private IP address. If a client is connecting to a local public IP address, they
|
||||
* will be directed to whichever address and port they initially connected to. This allows multihomed servers to function
|
||||
* properly and fully supports listening on multiple ports. If a client with a public IP address is connecting to a
|
||||
* locally private address, the server will direct the client to either the AutoDetected IP address or the manually entered
|
||||
* IP address or hostname, whichever is applicable. Loopback clients will be directed to loopback.
|
||||
*
|
||||
* If you would like to listen on additional ports (i.e. 22, 23, 80, for clients behind highly restrictive egress
|
||||
* firewalls) or specific IP adddresses you can do so by modifying the file SocketOptions.cs found in this directory.
|
||||
*/
|
||||
|
||||
public static readonly string Address = null;
|
||||
public static readonly string ServerName = Server.Misc.Settings.ServerName();
|
||||
|
||||
public static readonly bool AutoDetect = true;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if ( Address == null ) {
|
||||
if ( AutoDetect )
|
||||
AutoDetection();
|
||||
}
|
||||
else {
|
||||
Resolve( Address, out m_PublicAddress );
|
||||
}
|
||||
|
||||
EventSink.ServerList += new ServerListEventHandler( EventSink_ServerList );
|
||||
}
|
||||
|
||||
private static IPAddress m_PublicAddress;
|
||||
|
||||
private static void EventSink_ServerList( ServerListEventArgs e )
|
||||
{
|
||||
try
|
||||
{
|
||||
NetState ns = e.State;
|
||||
Socket s = ns.Socket;
|
||||
|
||||
IPEndPoint ipep = (IPEndPoint)s.LocalEndPoint;
|
||||
|
||||
IPAddress localAddress = ipep.Address;
|
||||
int localPort = ipep.Port;
|
||||
|
||||
if ( IsPrivateNetwork( localAddress ) ) {
|
||||
ipep = (IPEndPoint)s.RemoteEndPoint;
|
||||
if ( !IsPrivateNetwork( ipep.Address ) && m_PublicAddress != null )
|
||||
localAddress = m_PublicAddress;
|
||||
}
|
||||
|
||||
e.AddServer( ServerName, new IPEndPoint( localAddress, localPort ) );
|
||||
}
|
||||
catch
|
||||
{
|
||||
e.Rejected = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AutoDetection()
|
||||
{
|
||||
if ( !HasPublicIPAddress() || Server.Misc.Settings.DetectPublicIP() ) {
|
||||
Console.Write( "ServerList: Auto-detecting public IP address..." );
|
||||
m_PublicAddress = FindPublicAddress();
|
||||
|
||||
if ( m_PublicAddress != null )
|
||||
Console.WriteLine( "done ({0})", m_PublicAddress.ToString() );
|
||||
else
|
||||
Console.WriteLine( "failed" );
|
||||
}
|
||||
}
|
||||
|
||||
private static void Resolve( string addr, out IPAddress outValue )
|
||||
{
|
||||
if ( IPAddress.TryParse( addr, out outValue ) )
|
||||
return;
|
||||
|
||||
try {
|
||||
IPHostEntry iphe = Dns.GetHostEntry( addr );
|
||||
|
||||
if ( iphe.AddressList.Length > 0 )
|
||||
outValue = iphe.AddressList[iphe.AddressList.Length - 1];
|
||||
}
|
||||
catch {
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasPublicIPAddress()
|
||||
{
|
||||
NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces();
|
||||
|
||||
foreach ( NetworkInterface adapter in adapters ) {
|
||||
IPInterfaceProperties properties = adapter.GetIPProperties();
|
||||
|
||||
foreach ( IPAddressInformation unicast in properties.UnicastAddresses ) {
|
||||
IPAddress ip = unicast.Address;
|
||||
|
||||
if ( !IPAddress.IsLoopback( ip ) && ip.AddressFamily != AddressFamily.InterNetworkV6 && !IsPrivateNetwork( ip ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool IsPrivateNetwork( IPAddress ip )
|
||||
{
|
||||
if ( ip.AddressFamily == AddressFamily.InterNetworkV6 )
|
||||
return false;
|
||||
|
||||
if ( Utility.IPMatch( "192.168.*", ip ) )
|
||||
return true;
|
||||
else if ( Utility.IPMatch( "10.*", ip ) )
|
||||
return true;
|
||||
else if ( Utility.IPMatch( "127.0.0.1", ip ) )
|
||||
return true;
|
||||
else if ( Utility.IPMatch( "169.254.*", ip ) )
|
||||
return true;
|
||||
else if ( Utility.IPMatch( "172.16-31.*", ip ) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private static IPAddress FindPublicAddress()
|
||||
{
|
||||
try {
|
||||
WebRequest req = HttpWebRequest.Create( Server.Misc.Settings.PublicIP() );
|
||||
req.Timeout = 15000;
|
||||
|
||||
WebResponse res = req.GetResponse();
|
||||
|
||||
Stream s = res.GetResponseStream();
|
||||
|
||||
StreamReader sr = new StreamReader( s );
|
||||
|
||||
IPAddress ip = IPAddress.Parse( sr.ReadLine() );
|
||||
|
||||
sr.Close();
|
||||
s.Close();
|
||||
res.Close();
|
||||
|
||||
return ip;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
643
Scripts/Misc/ShardPoller.cs
Normal file
643
Scripts/Misc/ShardPoller.cs
Normal file
|
|
@ -0,0 +1,643 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Server.Prompts;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class ShardPoller : Item
|
||||
{
|
||||
private string m_Title;
|
||||
|
||||
private ShardPollOption[] m_Options;
|
||||
private IPAddress[] m_Addresses;
|
||||
|
||||
private TimeSpan m_Duration;
|
||||
private DateTime m_StartTime;
|
||||
|
||||
private bool m_Active;
|
||||
|
||||
public ShardPollOption[] Options
|
||||
{
|
||||
get{ return m_Options; }
|
||||
set{ m_Options = value; }
|
||||
}
|
||||
|
||||
public IPAddress[] Addresses
|
||||
{
|
||||
get{ return m_Addresses; }
|
||||
set{ m_Addresses = value; }
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
|
||||
public string Title
|
||||
{
|
||||
get{ return m_Title; }
|
||||
set{ m_Title = ShardPollPrompt.UrlToHref( value ); }
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
|
||||
public TimeSpan Duration
|
||||
{
|
||||
get{ return m_Duration; }
|
||||
set{ m_Duration = value; }
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
|
||||
public DateTime StartTime
|
||||
{
|
||||
get{ return m_StartTime; }
|
||||
set{ m_StartTime = value; }
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
|
||||
public TimeSpan TimeRemaining
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( m_StartTime == DateTime.MinValue || !m_Active )
|
||||
return TimeSpan.Zero;
|
||||
|
||||
try
|
||||
{
|
||||
TimeSpan ts = (m_StartTime + m_Duration) - DateTime.Now;
|
||||
|
||||
if ( ts < TimeSpan.Zero )
|
||||
return TimeSpan.Zero;
|
||||
|
||||
return ts;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
|
||||
public bool Active
|
||||
{
|
||||
get{ return m_Active; }
|
||||
set
|
||||
{
|
||||
if ( m_Active == value )
|
||||
return;
|
||||
|
||||
m_Active = value;
|
||||
|
||||
if ( m_Active )
|
||||
{
|
||||
m_StartTime = DateTime.Now;
|
||||
m_ActivePollers.Add( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ActivePollers.Remove( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasAlreadyVoted( NetState ns )
|
||||
{
|
||||
for ( int i = 0; i < m_Options.Length; ++i )
|
||||
{
|
||||
if ( m_Options[i].HasAlreadyVoted( ns ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AddVote( NetState ns, ShardPollOption option )
|
||||
{
|
||||
option.AddVote( ns );
|
||||
}
|
||||
|
||||
public void RemoveOption( ShardPollOption option )
|
||||
{
|
||||
int index = Array.IndexOf( m_Options, option );
|
||||
|
||||
if ( index < 0 )
|
||||
return;
|
||||
|
||||
ShardPollOption[] old = m_Options;
|
||||
m_Options = new ShardPollOption[old.Length - 1];
|
||||
|
||||
for ( int i = 0; i < index; ++i )
|
||||
m_Options[i] = old[i];
|
||||
|
||||
for ( int i = index; i < m_Options.Length; ++i )
|
||||
m_Options[i] = old[i + 1];
|
||||
}
|
||||
|
||||
public void AddOption( ShardPollOption option )
|
||||
{
|
||||
ShardPollOption[] old = m_Options;
|
||||
m_Options = new ShardPollOption[old.Length + 1];
|
||||
|
||||
for ( int i = 0; i < old.Length; ++i )
|
||||
m_Options[i] = old[i];
|
||||
|
||||
m_Options[old.Length] = option;
|
||||
}
|
||||
|
||||
public override string DefaultName
|
||||
{
|
||||
get { return "shard poller"; }
|
||||
}
|
||||
|
||||
[Constructable( AccessLevel.Administrator )]
|
||||
public ShardPoller() : base( 0x1047 )
|
||||
{
|
||||
m_Duration = TimeSpan.FromHours( 24.0 );
|
||||
m_Options = new ShardPollOption[0];
|
||||
m_Addresses = new IPAddress[0];
|
||||
|
||||
Movable = false;
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Login += new LoginEventHandler( EventSink_Login );
|
||||
}
|
||||
|
||||
private static List<ShardPoller> m_ActivePollers = new List<ShardPoller>();
|
||||
|
||||
private static void EventSink_Login( LoginEventArgs e )
|
||||
{
|
||||
if ( m_ActivePollers.Count == 0 )
|
||||
return;
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerStateCallback( EventSink_Login_Callback ), e.Mobile );
|
||||
}
|
||||
|
||||
private static void EventSink_Login_Callback( object state )
|
||||
{
|
||||
Mobile from = (Mobile)state;
|
||||
NetState ns = from.NetState;
|
||||
|
||||
if ( ns == null )
|
||||
return;
|
||||
|
||||
ShardPollGump spg = null;
|
||||
|
||||
for ( int i = 0; i < m_ActivePollers.Count; ++i )
|
||||
{
|
||||
ShardPoller poller = m_ActivePollers[i];
|
||||
|
||||
if ( poller.Deleted || !poller.Active )
|
||||
continue;
|
||||
|
||||
if ( poller.TimeRemaining > TimeSpan.Zero )
|
||||
{
|
||||
if ( poller.HasAlreadyVoted( ns ) )
|
||||
continue;
|
||||
|
||||
if ( spg == null )
|
||||
{
|
||||
spg = new ShardPollGump( from, poller, false, null );
|
||||
from.SendGump( spg );
|
||||
}
|
||||
else
|
||||
{
|
||||
spg.QueuePoll( poller );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
poller.Active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SendQueuedPoll_Callback( object state )
|
||||
{
|
||||
object[] states = (object[])state;
|
||||
Mobile from = (Mobile)states[0];
|
||||
Queue<ShardPoller> queue = (Queue<ShardPoller>)states[1];
|
||||
|
||||
from.SendGump( new ShardPollGump( from, this, false, queue ) );
|
||||
}
|
||||
|
||||
public override void OnDoubleClick( Mobile from )
|
||||
{
|
||||
if ( from.AccessLevel >= AccessLevel.Administrator )
|
||||
from.SendGump( new ShardPollGump( from, this, true, null ) );
|
||||
}
|
||||
|
||||
public ShardPoller( Serial serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
|
||||
writer.Write( (int) 0 ); // version
|
||||
|
||||
writer.Write( m_Title );
|
||||
writer.Write( m_Duration );
|
||||
writer.Write( m_StartTime );
|
||||
writer.Write( m_Active );
|
||||
|
||||
writer.Write( m_Options.Length );
|
||||
|
||||
for ( int i = 0; i < m_Options.Length; ++i )
|
||||
m_Options[i].Serialize( writer );
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch ( version )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Title = reader.ReadString();
|
||||
m_Duration = reader.ReadTimeSpan();
|
||||
m_StartTime = reader.ReadDateTime();
|
||||
m_Active = reader.ReadBool();
|
||||
|
||||
m_Options = new ShardPollOption[reader.ReadInt()];
|
||||
|
||||
for ( int i = 0; i < m_Options.Length; ++i )
|
||||
m_Options[i] = new ShardPollOption( reader );
|
||||
|
||||
if ( m_Active )
|
||||
m_ActivePollers.Add( this );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
base.OnDelete();
|
||||
|
||||
Active = false;
|
||||
}
|
||||
}
|
||||
|
||||
public class ShardPollOption
|
||||
{
|
||||
private string m_Title;
|
||||
private int m_LineBreaks;
|
||||
private IPAddress[] m_Voters;
|
||||
|
||||
public string Title{ get{ return m_Title; } set{ m_Title = value; m_LineBreaks = GetBreaks( m_Title ); } }
|
||||
public int LineBreaks{ get{ return m_LineBreaks; } }
|
||||
|
||||
public int Votes{ get{ return m_Voters.Length; } }
|
||||
public IPAddress[] Voters{ get{ return m_Voters; } set{ m_Voters = value; } }
|
||||
|
||||
public ShardPollOption( string title )
|
||||
{
|
||||
m_Title = title;
|
||||
m_LineBreaks = GetBreaks( m_Title );
|
||||
m_Voters = new IPAddress[0];
|
||||
}
|
||||
|
||||
public bool HasAlreadyVoted( NetState ns )
|
||||
{
|
||||
if ( ns == null )
|
||||
return false;
|
||||
|
||||
IPAddress ipAddress = ns.Address;
|
||||
|
||||
for ( int i = 0; i < m_Voters.Length; ++i )
|
||||
{
|
||||
if ( Utility.IPMatchClassC( m_Voters[i], ipAddress ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void AddVote( NetState ns )
|
||||
{
|
||||
if ( ns == null )
|
||||
return;
|
||||
|
||||
IPAddress[] old = m_Voters;
|
||||
m_Voters = new IPAddress[old.Length + 1];
|
||||
|
||||
for ( int i = 0; i < old.Length; ++i )
|
||||
m_Voters[i] = old[i];
|
||||
|
||||
m_Voters[old.Length] = ns.Address;
|
||||
}
|
||||
|
||||
public int ComputeHeight()
|
||||
{
|
||||
int height = m_LineBreaks * 18;
|
||||
|
||||
if ( height > 30 )
|
||||
return height;
|
||||
|
||||
return 30;
|
||||
}
|
||||
|
||||
public int GetBreaks( string title )
|
||||
{
|
||||
if ( title == null )
|
||||
return 1;
|
||||
|
||||
int count = 0;
|
||||
int index = -1;
|
||||
|
||||
do
|
||||
{
|
||||
++count;
|
||||
index = title.IndexOf( "<br>", index + 1 );
|
||||
} while ( index >= 0 );
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public ShardPollOption( GenericReader reader )
|
||||
{
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch ( version )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Title = reader.ReadString();
|
||||
m_LineBreaks = GetBreaks( m_Title );
|
||||
|
||||
m_Voters = new IPAddress[reader.ReadInt()];
|
||||
|
||||
for ( int i = 0; i < m_Voters.Length; ++i )
|
||||
m_Voters[i] = Utility.Intern( reader.ReadIPAddress() );
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Serialize( GenericWriter writer )
|
||||
{
|
||||
writer.Write( (int) 0 ); // version
|
||||
|
||||
writer.Write( m_Title );
|
||||
|
||||
writer.Write( m_Voters.Length );
|
||||
|
||||
for ( int i = 0; i < m_Voters.Length; ++i )
|
||||
writer.Write( m_Voters[i] );
|
||||
}
|
||||
}
|
||||
|
||||
public class ShardPollGump : Gump
|
||||
{
|
||||
private Mobile m_From;
|
||||
private ShardPoller m_Poller;
|
||||
private bool m_Editing;
|
||||
private Queue<ShardPoller> m_Polls;
|
||||
|
||||
public bool Editing{ get{ return m_Editing; } }
|
||||
|
||||
public void QueuePoll( ShardPoller poller )
|
||||
{
|
||||
if ( m_Polls == null )
|
||||
m_Polls = new Queue<ShardPoller>( 4 );
|
||||
|
||||
m_Polls.Enqueue( poller );
|
||||
}
|
||||
|
||||
public string Center( string text )
|
||||
{
|
||||
return String.Format( "<CENTER>{0}</CENTER>", text );
|
||||
}
|
||||
|
||||
public string Color( string text, int color )
|
||||
{
|
||||
return String.Format( "<BASEFONT COLOR=#{0:X6}>{1}</BASEFONT>", color, text );
|
||||
}
|
||||
|
||||
private const int LabelColor32 = 0xFFFFFF;
|
||||
|
||||
public ShardPollGump( Mobile from, ShardPoller poller, bool editing, Queue<ShardPoller> polls ) : base( 50, 50 )
|
||||
{
|
||||
m_From = from;
|
||||
m_Poller = poller;
|
||||
m_Editing = editing;
|
||||
m_Polls = polls;
|
||||
|
||||
Closable = false;
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
int totalVotes = 0;
|
||||
int totalOptionHeight = 0;
|
||||
|
||||
for ( int i = 0; i < poller.Options.Length; ++i )
|
||||
{
|
||||
totalVotes += poller.Options[i].Votes;
|
||||
totalOptionHeight += poller.Options[i].ComputeHeight() + 5;
|
||||
}
|
||||
|
||||
bool isViewingResults = editing && poller.Active;
|
||||
bool isCompleted = totalVotes > 0 && !poller.Active;
|
||||
|
||||
if ( editing && !isViewingResults )
|
||||
totalOptionHeight += 35;
|
||||
|
||||
int height = 115 + totalOptionHeight;
|
||||
|
||||
AddBackground( 1, 1, 398, height - 2, 3600 );
|
||||
AddAlphaRegion( 16, 15, 369, height - 31 );
|
||||
|
||||
AddItem( 308, 30, 0x1E5E );
|
||||
|
||||
string title;
|
||||
|
||||
if ( editing )
|
||||
title = ( isCompleted ? "Poll Completed" : "Poll Editor" );
|
||||
else
|
||||
title = "Shard Poll";
|
||||
|
||||
AddHtml( 22, 22, 294, 20, Color( Center( title ), LabelColor32 ), false, false );
|
||||
|
||||
if ( editing )
|
||||
{
|
||||
AddHtml( 22, 22, 294, 20, Color( String.Format( "{0} total", totalVotes ), LabelColor32 ), false, false );
|
||||
AddButton( 287, 23, 0x2622, 0x2623, 2, GumpButtonType.Reply, 0 );
|
||||
}
|
||||
|
||||
AddHtml( 22, 50, 294, 40, Color( poller.Title, 0x99CC66 ), false, false );
|
||||
|
||||
AddImageTiled( 32, 88, 264, 1, 9107 );
|
||||
AddImageTiled( 42, 90, 264, 1, 9157 );
|
||||
|
||||
int y = 100;
|
||||
|
||||
for ( int i = 0; i < poller.Options.Length; ++i )
|
||||
{
|
||||
ShardPollOption option = poller.Options[i];
|
||||
string text = option.Title;
|
||||
|
||||
if ( editing && totalVotes > 0 )
|
||||
{
|
||||
double perc = option.Votes / (double)totalVotes;
|
||||
|
||||
text = String.Format( "[{1}: {2}%] {0}", text, option.Votes, (int)(perc*100) );
|
||||
}
|
||||
|
||||
int optHeight = option.ComputeHeight();
|
||||
|
||||
y += optHeight/2;
|
||||
|
||||
if ( isViewingResults )
|
||||
AddImage( 24, y - 15, 0x25FE );
|
||||
else
|
||||
AddRadio( 24, y - 15, 0x25F9, 0x25FC, false, 1 + i );
|
||||
|
||||
AddHtml( 60, y - (9 * option.LineBreaks), 250, 18 * option.LineBreaks, Color( text, LabelColor32 ), false, false );
|
||||
|
||||
y += optHeight/2;
|
||||
y += 5;
|
||||
}
|
||||
|
||||
if ( editing && !isViewingResults )
|
||||
{
|
||||
AddRadio( 24, y + 15 - 15, 0x25F9, 0x25FC, false, 1 + poller.Options.Length );
|
||||
AddHtml( 60, y + 15 - 9, 250, 18, Color( "Create new option.", 0x99CC66 ), false, false );
|
||||
}
|
||||
|
||||
AddButton( 314, height - 73, 247, 248, 1, GumpButtonType.Reply, 0 );
|
||||
AddButton( 314, height - 47, 242, 241, 0, GumpButtonType.Reply, 0 );
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState sender, RelayInfo info )
|
||||
{
|
||||
if ( m_Polls != null && m_Polls.Count > 0 )
|
||||
{
|
||||
ShardPoller poller = m_Polls.Dequeue();
|
||||
|
||||
if ( poller != null )
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerStateCallback( poller.SendQueuedPoll_Callback ), new object[]{ m_From, m_Polls } );
|
||||
}
|
||||
|
||||
if ( info.ButtonID == 1 )
|
||||
{
|
||||
int[] switches = info.Switches;
|
||||
|
||||
if ( switches.Length == 0 )
|
||||
return;
|
||||
|
||||
int switched = switches[0] - 1;
|
||||
ShardPollOption opt = null;
|
||||
|
||||
if ( switched >= 0 && switched < m_Poller.Options.Length )
|
||||
opt = m_Poller.Options[switched];
|
||||
|
||||
if ( opt == null && !m_Editing )
|
||||
return;
|
||||
|
||||
if ( m_Editing )
|
||||
{
|
||||
if ( !m_Poller.Active )
|
||||
{
|
||||
m_From.SendMessage( "Enter a title for the option. Escape to cancel.{0}", opt == null ? "" : " Use \"DEL\" to delete." );
|
||||
m_From.Prompt = new ShardPollPrompt( m_Poller, opt );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_From.SendMessage( "You may not edit an active poll. Deactivate it first." );
|
||||
m_From.SendGump( new ShardPollGump( m_From, m_Poller, m_Editing, m_Polls ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !m_Poller.Active )
|
||||
m_From.SendMessage( "The poll has been deactivated." );
|
||||
else if ( m_Poller.HasAlreadyVoted( sender ) )
|
||||
m_From.SendMessage( "You have already voted on this poll." );
|
||||
else
|
||||
m_Poller.AddVote( sender, opt );
|
||||
}
|
||||
}
|
||||
else if ( info.ButtonID == 2 && m_Editing )
|
||||
{
|
||||
m_From.SendGump( new ShardPollGump( m_From, m_Poller, m_Editing, m_Polls ) );
|
||||
m_From.SendGump( new PropertiesGump( m_From, m_Poller ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ShardPollPrompt : Prompt
|
||||
{
|
||||
private ShardPoller m_Poller;
|
||||
private ShardPollOption m_Option;
|
||||
|
||||
public ShardPollPrompt( ShardPoller poller, ShardPollOption opt )
|
||||
{
|
||||
m_Poller = poller;
|
||||
m_Option = opt;
|
||||
}
|
||||
|
||||
public override void OnCancel( Mobile from )
|
||||
{
|
||||
from.SendGump( new ShardPollGump( from, m_Poller, true, null ) );
|
||||
}
|
||||
|
||||
private static Regex m_UrlRegex = new Regex( @"\[url(?:=(.*?))?\](.*?)\[/url\]", RegexOptions.IgnoreCase | RegexOptions.Compiled );
|
||||
|
||||
private static string UrlRegex_Match( Match m )
|
||||
{
|
||||
if ( m.Groups[1].Success )
|
||||
{
|
||||
if ( m.Groups[2].Success )
|
||||
return String.Format( "<a href=\"{0}\">{1}</a>", m.Groups[1].Value, m.Groups[2].Value );
|
||||
}
|
||||
else if ( m.Groups[2].Success )
|
||||
{
|
||||
return String.Format( "<a href=\"{0}\">{0}</a>", m.Groups[2].Value );
|
||||
}
|
||||
|
||||
return m.Value;
|
||||
}
|
||||
|
||||
public static string UrlToHref( string text )
|
||||
{
|
||||
if ( text == null )
|
||||
return null;
|
||||
|
||||
return m_UrlRegex.Replace( text, new MatchEvaluator( UrlRegex_Match ) );
|
||||
}
|
||||
|
||||
public override void OnResponse( Mobile from, string text )
|
||||
{
|
||||
if ( m_Poller.Active )
|
||||
{
|
||||
from.SendMessage( "You may not edit an active poll. Deactivate it first." );
|
||||
}
|
||||
else if ( text == "DEL" )
|
||||
{
|
||||
if ( m_Option != null )
|
||||
m_Poller.RemoveOption( m_Option );
|
||||
}
|
||||
else
|
||||
{
|
||||
text = UrlToHref( text );
|
||||
|
||||
if ( m_Option == null )
|
||||
m_Poller.AddOption( new ShardPollOption( text ) );
|
||||
else
|
||||
m_Option.Title = text;
|
||||
}
|
||||
|
||||
from.SendGump( new ShardPollGump( from, m_Poller, true, null ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
86
Scripts/Misc/ShrinkTable.cs
Normal file
86
Scripts/Misc/ShrinkTable.cs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class ShrinkTable
|
||||
{
|
||||
public const int DefaultItemID = 0x1870; // Yellow virtue stone
|
||||
|
||||
private static int[] m_Table;
|
||||
|
||||
public static int Lookup( Mobile m )
|
||||
{
|
||||
return Lookup( m.Body.BodyID, DefaultItemID );
|
||||
}
|
||||
|
||||
public static int Lookup( int body )
|
||||
{
|
||||
return Lookup( body, DefaultItemID );
|
||||
}
|
||||
|
||||
public static int Lookup( Mobile m, int defaultValue )
|
||||
{
|
||||
return Lookup( m.Body.BodyID, defaultValue );
|
||||
}
|
||||
|
||||
public static int Lookup( int body, int defaultValue )
|
||||
{
|
||||
if ( m_Table == null )
|
||||
Load();
|
||||
|
||||
int val = 0;
|
||||
|
||||
if ( body >= 0 && body < m_Table.Length )
|
||||
val = m_Table[body];
|
||||
|
||||
if ( val == 0 )
|
||||
val = defaultValue;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
private static void Load()
|
||||
{
|
||||
string path = Path.Combine( Core.BaseDirectory, "Data/Config/shrink.cfg" );
|
||||
|
||||
if ( !File.Exists( path ) )
|
||||
{
|
||||
m_Table = new int[0];
|
||||
return;
|
||||
}
|
||||
|
||||
m_Table = new int[1000];
|
||||
|
||||
using ( StreamReader ip = new StreamReader( path ) )
|
||||
{
|
||||
string line;
|
||||
|
||||
while ( (line = ip.ReadLine()) != null )
|
||||
{
|
||||
line = line.Trim();
|
||||
|
||||
if ( line.Length == 0 || line.StartsWith( "#" ) )
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
string[] split = line.Split( '\t' );
|
||||
|
||||
if ( split.Length >= 2 )
|
||||
{
|
||||
int body = Utility.ToInt32( split[0] );
|
||||
int item = Utility.ToInt32( split[1] );
|
||||
|
||||
if ( body >= 0 && body < m_Table.Length )
|
||||
m_Table[body] = item;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Scripts/Misc/SocketOptions.cs
Normal file
42
Scripts/Misc/SocketOptions.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Server;
|
||||
using Server.Misc;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class SocketOptions
|
||||
{
|
||||
private const bool NagleEnabled = false; // Should the Nagle algorithm be enabled? This may reduce performance
|
||||
private const int CoalesceBufferSize = 512; // MSS that the core will use when buffering packets
|
||||
|
||||
private static IPEndPoint[] m_ListenerEndPoints = new IPEndPoint[] {
|
||||
new IPEndPoint( IPAddress.Any, 2593 ), // Default: Listen on port 2593 on all IP addresses
|
||||
|
||||
// Examples:
|
||||
// new IPEndPoint( IPAddress.Any, 80 ), // Listen on port 80 on all IP addresses
|
||||
// new IPEndPoint( IPAddress.Parse( "1.2.3.4" ), 2593 ), // Listen on port 2593 on IP address 1.2.3.4
|
||||
};
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
SendQueue.CoalesceBufferSize = CoalesceBufferSize;
|
||||
|
||||
EventSink.SocketConnect += new SocketConnectEventHandler( EventSink_SocketConnect );
|
||||
|
||||
Listener.EndPoints = m_ListenerEndPoints;
|
||||
}
|
||||
|
||||
private static void EventSink_SocketConnect( SocketConnectEventArgs e )
|
||||
{
|
||||
if ( !e.AllowConnection )
|
||||
return;
|
||||
|
||||
if ( !NagleEnabled )
|
||||
e.Socket.SetSocketOption( SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1 ); // RunUO uses its own algorithm
|
||||
}
|
||||
}
|
||||
}
|
||||
147
Scripts/Misc/Tasks.cs
Normal file
147
Scripts/Misc/Tasks.cs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
using Server.Accounting;
|
||||
using Server.Commands.Generic;
|
||||
using Server.Commands;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Regions;
|
||||
using Server.Spells;
|
||||
using Server.Targeting;
|
||||
using Server;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class TaskManager : Item
|
||||
{
|
||||
[Constructable]
|
||||
public TaskManager () : base( 0x0EDE )
|
||||
{
|
||||
Movable = false;
|
||||
Name = "Task Manager";
|
||||
Visible = false;
|
||||
TaskTimer thisTimer = new TaskTimer( this );
|
||||
thisTimer.Start();
|
||||
}
|
||||
|
||||
public TaskManager(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
writer.Write( (int) 0 ); // version
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
int version = reader.ReadInt();
|
||||
|
||||
FirstTimer thisTimer = new FirstTimer( this );
|
||||
thisTimer.Start();
|
||||
}
|
||||
|
||||
public class TaskTimer : Timer
|
||||
{
|
||||
private Item i_item;
|
||||
public TaskTimer( Item task ) : base( TimeSpan.FromMinutes( 60.0 ) )
|
||||
{
|
||||
Priority = TimerPriority.OneMinute;
|
||||
i_item = task;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
TaskTimer thisTimer = new TaskTimer( i_item );
|
||||
thisTimer.Start();
|
||||
RunThis( i_item );
|
||||
}
|
||||
}
|
||||
|
||||
public class FirstTimer : Timer
|
||||
{
|
||||
private Item i_item;
|
||||
public FirstTimer( Item task ) : base( TimeSpan.FromSeconds( 10.0 ) )
|
||||
{
|
||||
Priority = TimerPriority.OneSecond;
|
||||
i_item = task;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
TaskTimer thisTimer = new TaskTimer( i_item );
|
||||
thisTimer.Start();
|
||||
RunThis( i_item );
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunThis( Item item )
|
||||
{
|
||||
TaskTimer thisTimer = new TaskTimer( item );
|
||||
thisTimer.Start();
|
||||
|
||||
// ************************************************************************************
|
||||
|
||||
ArrayList citizens = new ArrayList();
|
||||
foreach ( Mobile citizen in World.Mobiles.Values )
|
||||
if ( citizen is Citizen )
|
||||
{
|
||||
if ( citizen != null )
|
||||
{
|
||||
citizens.Add( citizen );
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i < citizens.Count; ++i )
|
||||
{
|
||||
Mobile person = ( Mobile )citizens[ i ];
|
||||
person.Delete();
|
||||
}
|
||||
|
||||
// ************************************************************************************
|
||||
|
||||
ArrayList camps = new ArrayList();
|
||||
foreach ( Item camp in World.Items.Values )
|
||||
if ( camp is CampAAddon || camp is CampBAddon || camp is CampCAddon || camp is CampDAddon )
|
||||
{
|
||||
if ( camp != null )
|
||||
{
|
||||
camps.Add( camp );
|
||||
}
|
||||
}
|
||||
for ( int i = 0; i < camps.Count; ++i )
|
||||
{
|
||||
Item fire = ( Item )camps[ i ];
|
||||
fire.Delete();
|
||||
}
|
||||
|
||||
// ************************************************************************************
|
||||
|
||||
ArrayList traps = new ArrayList();
|
||||
foreach ( Item trap in World.Items.Values )
|
||||
{
|
||||
if ( trap is BaseTrap )
|
||||
{
|
||||
traps.Add( trap );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < traps.Count; ++i )
|
||||
{
|
||||
BaseTrap trapped = ( BaseTrap )traps[ i ];
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ************************************************************************************
|
||||
}
|
||||
}
|
||||
}
|
||||
125
Scripts/Misc/TextDefinition.cs
Normal file
125
Scripts/Misc/TextDefinition.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
using System;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class TextDefinition
|
||||
{
|
||||
private int m_Number;
|
||||
private string m_String;
|
||||
|
||||
public int Number{ get{ return m_Number; } }
|
||||
public string String{ get{ return m_String; } }
|
||||
|
||||
public TextDefinition( int number ) : this( number, null )
|
||||
{
|
||||
}
|
||||
|
||||
public TextDefinition( string text ) : this( 0, text )
|
||||
{
|
||||
}
|
||||
|
||||
public TextDefinition( int number, string text )
|
||||
{
|
||||
m_Number = number;
|
||||
m_String = text;
|
||||
}
|
||||
|
||||
public TextDefinition( GenericReader reader )
|
||||
{
|
||||
int type = reader.ReadEncodedInt();
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case 1: m_Number = reader.ReadEncodedInt(); m_String = null; break;
|
||||
case 2: m_Number = 0; m_String = reader.ReadString(); break;
|
||||
default: m_Number = 0; m_String = null; break;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if ( m_Number > 0 )
|
||||
return "#" + m_Number.ToString();
|
||||
else if ( m_String != null )
|
||||
return m_String;
|
||||
|
||||
return "(empty)";
|
||||
}
|
||||
|
||||
public virtual void Serialize( GenericWriter writer )
|
||||
{
|
||||
if ( m_Number > 0 )
|
||||
{
|
||||
writer.WriteEncodedInt( 1 );
|
||||
writer.WriteEncodedInt( m_Number );
|
||||
}
|
||||
else if ( m_String != null )
|
||||
{
|
||||
writer.WriteEncodedInt( 2 );
|
||||
writer.Write( m_String );
|
||||
}
|
||||
else
|
||||
writer.WriteEncodedInt( 0 );
|
||||
}
|
||||
|
||||
public static void AddTo( ObjectPropertyList list, TextDefinition def )
|
||||
{
|
||||
if ( def != null && def.m_Number > 0 )
|
||||
list.Add( def.m_Number );
|
||||
else if ( def != null && def.m_String != null )
|
||||
list.Add( def.m_String );
|
||||
}
|
||||
|
||||
public static implicit operator TextDefinition ( int v )
|
||||
{
|
||||
return new TextDefinition( v );
|
||||
}
|
||||
|
||||
public static implicit operator TextDefinition ( string s )
|
||||
{
|
||||
return new TextDefinition( s );
|
||||
}
|
||||
|
||||
public static implicit operator int ( TextDefinition m )
|
||||
{
|
||||
if ( m == null )
|
||||
return 0;
|
||||
|
||||
return m.m_Number;
|
||||
}
|
||||
|
||||
public static implicit operator string ( TextDefinition m )
|
||||
{
|
||||
if ( m == null )
|
||||
return null;
|
||||
|
||||
return m.m_String;
|
||||
}
|
||||
|
||||
public static void AddHtmlText( Server.Gumps.Gump g, int x, int y, int width, int height, TextDefinition text, bool back, bool scroll, int numberColor, int stringColor )
|
||||
{
|
||||
if( text != null && text.Number > 0 )
|
||||
if( numberColor >= 0 )
|
||||
g.AddHtmlLocalized( x, y, width, height, text.Number, numberColor, back, scroll );
|
||||
else
|
||||
g.AddHtmlLocalized( x, y, width, height, text.Number, back, scroll );
|
||||
else if( text != null && text.String != null )
|
||||
if( stringColor >= 0 )
|
||||
g.AddHtml( x, y, width, height, String.Format( "<BASEFONT COLOR=#{0:X6}>{1}</BASEFONT>", stringColor, text.String ), back, scroll );
|
||||
else
|
||||
g.AddHtml( x, y, width, height, text.String, back, scroll );
|
||||
}
|
||||
public static void AddHtmlText( Server.Gumps.Gump g, int x, int y, int width, int height, TextDefinition text, bool back, bool scroll )
|
||||
{
|
||||
AddHtmlText( g, x, y, width, height, text, back, scroll, -1, -1 );
|
||||
}
|
||||
|
||||
public static void SendMessageTo( Mobile m, TextDefinition def )
|
||||
{
|
||||
if( def.Number > 0 )
|
||||
m.SendLocalizedMessage( def.Number );
|
||||
else if( def.String != null )
|
||||
m.SendMessage( def.String );
|
||||
}
|
||||
}
|
||||
}
|
||||
343
Scripts/Misc/Titles.cs
Normal file
343
Scripts/Misc/Titles.cs
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class Titles
|
||||
{
|
||||
public const int MinFame = 0;
|
||||
public const int MaxFame = 15000;
|
||||
|
||||
public static void AwardFame( Mobile m, int offset, bool message )
|
||||
{
|
||||
if ( offset > 0 )
|
||||
{
|
||||
if ( m.Fame >= MaxFame )
|
||||
return;
|
||||
|
||||
offset -= m.Fame / 100;
|
||||
|
||||
if ( offset < 0 )
|
||||
offset = 0;
|
||||
}
|
||||
else if ( offset < 0 )
|
||||
{
|
||||
if ( m.Fame <= MinFame )
|
||||
return;
|
||||
|
||||
offset -= m.Fame / 100;
|
||||
|
||||
if ( offset > 0 )
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if ( (m.Fame + offset) > MaxFame )
|
||||
offset = MaxFame - m.Fame;
|
||||
else if ( (m.Fame + offset) < MinFame )
|
||||
offset = MinFame - m.Fame;
|
||||
|
||||
m.Fame += offset;
|
||||
|
||||
if ( message )
|
||||
{
|
||||
if ( offset > 40 )
|
||||
m.SendLocalizedMessage( 1019054 ); // You have gained a lot of fame.
|
||||
else if ( offset > 20 )
|
||||
m.SendLocalizedMessage( 1019053 ); // You have gained a good amount of fame.
|
||||
else if ( offset > 10 )
|
||||
m.SendLocalizedMessage( 1019052 ); // You have gained some fame.
|
||||
else if ( offset > 0 )
|
||||
m.SendLocalizedMessage( 1019051 ); // You have gained a little fame.
|
||||
else if ( offset < -40 )
|
||||
m.SendLocalizedMessage( 1019058 ); // You have lost a lot of fame.
|
||||
else if ( offset < -20 )
|
||||
m.SendLocalizedMessage( 1019057 ); // You have lost a good amount of fame.
|
||||
else if ( offset < -10 )
|
||||
m.SendLocalizedMessage( 1019056 ); // You have lost some fame.
|
||||
else if ( offset < 0 )
|
||||
m.SendLocalizedMessage( 1019055 ); // You have lost a little fame.
|
||||
}
|
||||
}
|
||||
|
||||
public const int MinKarma = -15000;
|
||||
public const int MaxKarma = 15000;
|
||||
|
||||
public static void AwardKarma( Mobile m, int offset, bool message )
|
||||
{
|
||||
if ( offset > 0 )
|
||||
{
|
||||
if ( m is PlayerMobile && ((PlayerMobile)m).KarmaLocked )
|
||||
return;
|
||||
|
||||
if ( m.Karma >= MaxKarma )
|
||||
return;
|
||||
|
||||
offset -= m.Karma / 100;
|
||||
|
||||
if ( offset < 0 )
|
||||
offset = 0;
|
||||
}
|
||||
else if ( offset < 0 )
|
||||
{
|
||||
if ( m.Karma <= MinKarma )
|
||||
return;
|
||||
|
||||
offset -= m.Karma / 100;
|
||||
|
||||
if ( offset > 0 )
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
if ( (m.Karma + offset) > MaxKarma )
|
||||
offset = MaxKarma - m.Karma;
|
||||
else if ( (m.Karma + offset) < MinKarma )
|
||||
offset = MinKarma - m.Karma;
|
||||
|
||||
bool wasPositiveKarma = ( m.Karma >= 0 );
|
||||
|
||||
m.Karma += offset;
|
||||
|
||||
if ( message )
|
||||
{
|
||||
if ( offset > 40 )
|
||||
m.SendLocalizedMessage( 1019062 ); // You have gained a lot of karma.
|
||||
else if ( offset > 20 )
|
||||
m.SendLocalizedMessage( 1019061 ); // You have gained a good amount of karma.
|
||||
else if ( offset > 10 )
|
||||
m.SendLocalizedMessage( 1019060 ); // You have gained some karma.
|
||||
else if ( offset > 0 )
|
||||
m.SendLocalizedMessage( 1019059 ); // You have gained a little karma.
|
||||
else if ( offset < -40 )
|
||||
m.SendLocalizedMessage( 1019066 ); // You have lost a lot of karma.
|
||||
else if ( offset < -20 )
|
||||
m.SendLocalizedMessage( 1019065 ); // You have lost a good amount of karma.
|
||||
else if ( offset < -10 )
|
||||
m.SendLocalizedMessage( 1019064 ); // You have lost some karma.
|
||||
else if ( offset < 0 )
|
||||
m.SendLocalizedMessage( 1019063 ); // You have lost a little karma.
|
||||
}
|
||||
|
||||
if ( wasPositiveKarma && m.Karma < 0 && m is PlayerMobile && !((PlayerMobile)m).KarmaLocked )
|
||||
{
|
||||
((PlayerMobile)m).KarmaLocked = true;
|
||||
m.SendLocalizedMessage( 1042511, "", 0x22 ); // Karma is locked. A mantra spoken at a shrine will unlock it again.
|
||||
}
|
||||
}
|
||||
|
||||
public static string ComputeTitle( Mobile beholder, Mobile beheld )
|
||||
{
|
||||
StringBuilder title = new StringBuilder();
|
||||
|
||||
int fame = beheld.Fame;
|
||||
int karma = beheld.Karma;
|
||||
|
||||
bool showSkillTitle = beheld.ShowFameTitle && ( (beholder == beheld) || (fame >= 5000) );
|
||||
|
||||
if ( beheld.Kills >= 5 )
|
||||
{
|
||||
title.AppendFormat( beheld.Fame >= 10000 ? "The Murderer {1} {0}" : "The Murderer {0}", beheld.Name, beheld.Female ? "Lady" : "Lord" );
|
||||
}
|
||||
else if ( beheld.ShowFameTitle || (beholder == beheld) )
|
||||
{
|
||||
for ( int i = 0; i < m_FameEntries.Length; ++i )
|
||||
{
|
||||
FameEntry fe = m_FameEntries[i];
|
||||
|
||||
if ( fame <= fe.m_Fame || i == (m_FameEntries.Length - 1) )
|
||||
{
|
||||
KarmaEntry[] karmaEntries = fe.m_Karma;
|
||||
|
||||
for ( int j = 0; j < karmaEntries.Length; ++j )
|
||||
{
|
||||
KarmaEntry ke = karmaEntries[j];
|
||||
|
||||
if ( karma <= ke.m_Karma || j == (karmaEntries.Length - 1) )
|
||||
{
|
||||
title.AppendFormat( ke.m_Title, beheld.Name, beheld.Female ? "Lady" : "Lord" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
title.Append( beheld.Name );
|
||||
}
|
||||
|
||||
string customTitle = beheld.Title;
|
||||
|
||||
if ( customTitle != null && (customTitle = customTitle.Trim()).Length > 0 )
|
||||
{
|
||||
title.AppendFormat( " {0}", customTitle );
|
||||
}
|
||||
else if ( showSkillTitle && beheld.Player )
|
||||
{
|
||||
string skillTitle = GetSkillTitle( beheld );
|
||||
|
||||
if ( skillTitle != null ) {
|
||||
title.Append( ", " ).Append( skillTitle );
|
||||
}
|
||||
}
|
||||
|
||||
return title.ToString();
|
||||
}
|
||||
|
||||
public static string GetSkillTitle( Mobile mob ) {
|
||||
Skill highest = GetHighestSkill( mob );// beheld.Skills.Highest;
|
||||
|
||||
if ( highest != null && highest.BaseFixedPoint >= 300 )
|
||||
{
|
||||
string skillLevel = GetSkillLevel( highest );
|
||||
string skillTitle = highest.Info.Title;
|
||||
|
||||
if ( mob.Female && skillTitle.EndsWith( "man" ) )
|
||||
skillTitle = skillTitle.Substring( 0, skillTitle.Length - 3 ) + "woman";
|
||||
|
||||
return String.Concat( skillLevel, " ", skillTitle );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Skill GetHighestSkill( Mobile m )
|
||||
{
|
||||
Skills skills = m.Skills;
|
||||
|
||||
return skills.Highest;
|
||||
}
|
||||
|
||||
private static string[,] m_Levels = new string[,]
|
||||
{
|
||||
{ "Neophyte", "Neophyte", "Neophyte" },
|
||||
{ "Novice", "Novice", "Novice" },
|
||||
{ "Apprentice", "Apprentice", "Apprentice" },
|
||||
{ "Journeyman", "Journeyman", "Journeyman" },
|
||||
{ "Expert", "Expert", "Expert" },
|
||||
{ "Adept", "Adept", "Adept" },
|
||||
{ "Master", "Master", "Master" },
|
||||
{ "Grandmaster", "Grandmaster", "Grandmaster" },
|
||||
{ "Elder", "Tatsujin", "Shinobi" },
|
||||
{ "Legendary", "Kengo", "Ka-ge" }
|
||||
};
|
||||
|
||||
private static string GetSkillLevel( Skill skill )
|
||||
{
|
||||
return m_Levels[GetTableIndex( skill ), GetTableType( skill )];
|
||||
}
|
||||
|
||||
private static int GetTableType( Skill skill )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int GetTableIndex( Skill skill )
|
||||
{
|
||||
int fp = Math.Min( skill.BaseFixedPoint, 1200 );
|
||||
|
||||
return (fp - 300) / 100;
|
||||
}
|
||||
|
||||
private static FameEntry[] m_FameEntries = new FameEntry[]
|
||||
{
|
||||
new FameEntry( 1249, new KarmaEntry[]
|
||||
{
|
||||
new KarmaEntry( -10000, "The Outcast {0}" ),
|
||||
new KarmaEntry( -5000, "The Despicable {0}" ),
|
||||
new KarmaEntry( -2500, "The Scoundrel {0}" ),
|
||||
new KarmaEntry( -1250, "The Unsavory {0}" ),
|
||||
new KarmaEntry( -625, "The Rude {0}" ),
|
||||
new KarmaEntry( 624, "{0}" ),
|
||||
new KarmaEntry( 1249, "The Fair {0}" ),
|
||||
new KarmaEntry( 2499, "The Kind {0}" ),
|
||||
new KarmaEntry( 4999, "The Good {0}" ),
|
||||
new KarmaEntry( 9999, "The Honest {0}" ),
|
||||
new KarmaEntry( 10000, "The Trustworthy {0}" )
|
||||
} ),
|
||||
new FameEntry( 2499, new KarmaEntry[]
|
||||
{
|
||||
new KarmaEntry( -10000, "The Wretched {0}" ),
|
||||
new KarmaEntry( -5000, "The Dastardly {0}" ),
|
||||
new KarmaEntry( -2500, "The Malicious {0}" ),
|
||||
new KarmaEntry( -1250, "The Dishonorable {0}" ),
|
||||
new KarmaEntry( -625, "The Disreputable {0}" ),
|
||||
new KarmaEntry( 624, "The Notable {0}" ),
|
||||
new KarmaEntry( 1249, "The Upstanding {0}" ),
|
||||
new KarmaEntry( 2499, "The Respectable {0}" ),
|
||||
new KarmaEntry( 4999, "The Honorable {0}" ),
|
||||
new KarmaEntry( 9999, "The Commendable {0}" ),
|
||||
new KarmaEntry( 10000, "The Estimable {0}" )
|
||||
} ),
|
||||
new FameEntry( 4999, new KarmaEntry[]
|
||||
{
|
||||
new KarmaEntry( -10000, "The Nefarious {0}" ),
|
||||
new KarmaEntry( -5000, "The Wicked {0}" ),
|
||||
new KarmaEntry( -2500, "The Vile {0}" ),
|
||||
new KarmaEntry( -1250, "The Ignoble {0}" ),
|
||||
new KarmaEntry( -625, "The Notorious {0}" ),
|
||||
new KarmaEntry( 624, "The Prominent {0}" ),
|
||||
new KarmaEntry( 1249, "The Reputable {0}" ),
|
||||
new KarmaEntry( 2499, "The Proper {0}" ),
|
||||
new KarmaEntry( 4999, "The Admirable {0}" ),
|
||||
new KarmaEntry( 9999, "The Famed {0}" ),
|
||||
new KarmaEntry( 10000, "The Great {0}" )
|
||||
} ),
|
||||
new FameEntry( 9999, new KarmaEntry[]
|
||||
{
|
||||
new KarmaEntry( -10000, "The Dread {0}" ),
|
||||
new KarmaEntry( -5000, "The Evil {0}" ),
|
||||
new KarmaEntry( -2500, "The Villainous {0}" ),
|
||||
new KarmaEntry( -1250, "The Sinister {0}" ),
|
||||
new KarmaEntry( -625, "The Infamous {0}" ),
|
||||
new KarmaEntry( 624, "The Renowned {0}" ),
|
||||
new KarmaEntry( 1249, "The Distinguished {0}" ),
|
||||
new KarmaEntry( 2499, "The Eminent {0}" ),
|
||||
new KarmaEntry( 4999, "The Noble {0}" ),
|
||||
new KarmaEntry( 9999, "The Illustrious {0}" ),
|
||||
new KarmaEntry( 10000, "The Glorious {0}" )
|
||||
} ),
|
||||
new FameEntry( 10000, new KarmaEntry[]
|
||||
{
|
||||
new KarmaEntry( -10000, "The Dread {1} {0}" ),
|
||||
new KarmaEntry( -5000, "The Evil {1} {0}" ),
|
||||
new KarmaEntry( -2500, "The Dark {1} {0}" ),
|
||||
new KarmaEntry( -1250, "The Sinister {1} {0}" ),
|
||||
new KarmaEntry( -625, "The Dishonored {1} {0}" ),
|
||||
new KarmaEntry( 624, "{1} {0}" ),
|
||||
new KarmaEntry( 1249, "The Distinguished {1} {0}" ),
|
||||
new KarmaEntry( 2499, "The Eminent {1} {0}" ),
|
||||
new KarmaEntry( 4999, "The Noble {1} {0}" ),
|
||||
new KarmaEntry( 9999, "The Illustrious {1} {0}" ),
|
||||
new KarmaEntry( 10000, "The Glorious {1} {0}" )
|
||||
} )
|
||||
};
|
||||
}
|
||||
|
||||
public class FameEntry
|
||||
{
|
||||
public int m_Fame;
|
||||
public KarmaEntry[] m_Karma;
|
||||
|
||||
public FameEntry( int fame, KarmaEntry[] karma )
|
||||
{
|
||||
m_Fame = fame;
|
||||
m_Karma = karma;
|
||||
}
|
||||
}
|
||||
|
||||
public class KarmaEntry
|
||||
{
|
||||
public int m_Karma;
|
||||
public string m_Title;
|
||||
|
||||
public KarmaEntry( int karma, string title )
|
||||
{
|
||||
m_Karma = karma;
|
||||
m_Title = title;
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Scripts/Misc/TreasureMapProtection.cs
Normal file
77
Scripts/Misc/TreasureMapProtection.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class TreasureRegion : BaseRegion
|
||||
{
|
||||
private const int Range = 5; // No house may be placed within 5 tiles of the treasure
|
||||
|
||||
public TreasureRegion( int x, int y, Map map ): base( null, map, Region.DefaultPriority, new Rectangle2D( x - Range, y - Range, 1 + (Range * 2), 1 + (Range * 2) ) )
|
||||
{
|
||||
GoLocation = new Point3D( x, y, map.GetAverageZ( x, y ) );
|
||||
|
||||
Register();
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
string filePath = Path.Combine( Core.BaseDirectory, "Data/Config/treasure.cfg" );
|
||||
int i = 0, x = 0, y = 0;
|
||||
|
||||
if ( File.Exists( filePath ) )
|
||||
{
|
||||
using ( StreamReader ip = new StreamReader( filePath ) )
|
||||
{
|
||||
string line;
|
||||
|
||||
while ( (line = ip.ReadLine()) != null )
|
||||
{
|
||||
i++;
|
||||
|
||||
try
|
||||
{
|
||||
string[] split = line.Split( ' ' );
|
||||
|
||||
x = Convert.ToInt32( split[0] );
|
||||
y = Convert.ToInt32( split[1] );
|
||||
|
||||
try
|
||||
{
|
||||
new TreasureRegion( x, y, Map.Britannia );
|
||||
}
|
||||
catch ( Exception e )
|
||||
{
|
||||
Console.WriteLine( "{0} {1} {2} {3}", i, x, y, e );
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine( "Warning: Error in Line '{0}' of Data/Config/treasure.cfg", line );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool AllowHousing( Mobile from, Point3D p )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnEnter( Mobile m )
|
||||
{
|
||||
if ( m.AccessLevel > AccessLevel.Player )
|
||||
m.SendMessage( "You have entered a protected treasure map area." );
|
||||
}
|
||||
|
||||
public override void OnExit( Mobile m )
|
||||
{
|
||||
if ( m.AccessLevel > AccessLevel.Player )
|
||||
m.SendMessage( "You have left a protected treasure map area." );
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Scripts/Misc/Ultima.cs
Normal file
57
Scripts/Misc/Ultima.cs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Spells;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public class CurrentExpansion
|
||||
{
|
||||
private static readonly Expansion Expansion = Expansion.AOS;
|
||||
|
||||
public static void Configure()
|
||||
{
|
||||
Core.Expansion = Expansion;
|
||||
|
||||
bool Enabled = Core.AOS;
|
||||
|
||||
ObjectPropertyList.Enabled = Enabled;
|
||||
Mobile.VisibleDamageType = Enabled ? VisibleDamageType.Related : VisibleDamageType.None;
|
||||
Mobile.GuildClickMessage = !Enabled;
|
||||
Mobile.AsciiClickMessage = !Enabled;
|
||||
|
||||
if ( Enabled )
|
||||
{
|
||||
if ( ObjectPropertyList.Enabled )
|
||||
PacketHandlers.SingleClickProps = true; // single click for everything is overriden to check object property list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Ultima
|
||||
{
|
||||
public static int Damage( Mobile m, int damage )
|
||||
{
|
||||
return Damage( m, null, damage );
|
||||
}
|
||||
|
||||
public static int Damage( Mobile m, Mobile from, int damage )
|
||||
{
|
||||
if( m == null || m.Deleted || !m.Alive || damage <= 0 )
|
||||
return 0;
|
||||
|
||||
m.Damage( damage, from );
|
||||
return damage;
|
||||
}
|
||||
|
||||
public static int Scale( int input, int percent )
|
||||
{
|
||||
return (input * percent) / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
387
Scripts/Misc/Weather.cs
Normal file
387
Scripts/Misc/Weather.cs
Normal file
|
|
@ -0,0 +1,387 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
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[]{ Map.Britannia };
|
||||
|
||||
/* Static weather:
|
||||
*
|
||||
* Format:
|
||||
* AddWeather( temperature, chanceOfPercipitation, chanceOfExtremeTemperature, <area ...> );
|
||||
*/
|
||||
|
||||
// artic areas
|
||||
AddWeather( -15, 100, 5, new Rectangle2D( 2564, 334, 543, 358 ), new Rectangle2D( 5049, 2747, 1750, 975 ) );
|
||||
|
||||
/* 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, 7168, 4096 ) );
|
||||
}
|
||||
|
||||
public static List<Weather> GetWeatherList( Map facet )
|
||||
{
|
||||
if ( facet == null )
|
||||
return null;
|
||||
|
||||
List<Weather> list = null;
|
||||
m_WeatherByFacet.TryGetValue( facet, out list );
|
||||
|
||||
if ( list == null )
|
||||
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;
|
||||
|
||||
Weather w = new Weather( m_Facets[i], new Rectangle2D[]{ area }, temperature, chanceOfPercipitation, chanceOfExtremeTemperature, TimeSpan.FromSeconds( 30.0 ) );
|
||||
|
||||
w.m_Bounds = bounds;
|
||||
w.m_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;
|
||||
}
|
||||
|
||||
private Map m_Facet;
|
||||
private Rectangle2D[] m_Area;
|
||||
private int m_Temperature;
|
||||
private int m_ChanceOfPercipitation;
|
||||
private int m_ChanceOfExtremeTemperature;
|
||||
|
||||
public Map Facet{ get{ return m_Facet; } }
|
||||
public Rectangle2D[] Area{ get{ return m_Area; } set{ m_Area = value; } }
|
||||
public int Temperature{ get{ return m_Temperature; } set{ m_Temperature = value; } }
|
||||
public int ChanceOfPercipitation{ get{ return m_ChanceOfPercipitation; } set{ m_ChanceOfPercipitation = value; } }
|
||||
public int ChanceOfExtremeTemperature{ get{ return m_ChanceOfExtremeTemperature; } set{ m_ChanceOfExtremeTemperature = value; } }
|
||||
|
||||
// For dynamic weather:
|
||||
private Rectangle2D m_Bounds;
|
||||
private int m_MoveSpeed;
|
||||
private int m_MoveAngleX, m_MoveAngleY;
|
||||
|
||||
public Rectangle2D Bounds{ get{ return m_Bounds; } set{ m_Bounds = value; } }
|
||||
public int MoveSpeed{ get{ return m_MoveSpeed; } set{ m_MoveSpeed = value; } }
|
||||
public int MoveAngleX{ get{ return m_MoveAngleX; } set{ m_MoveAngleX = value; } }
|
||||
public int MoveAngleY{ get{ return m_MoveAngleY; } set{ m_MoveAngleY = value; } }
|
||||
|
||||
public static bool CheckIntersection( Rectangle2D r1, Rectangle2D r2 )
|
||||
{
|
||||
if ( r1.X >= (r2.X + r2.Width) )
|
||||
return false;
|
||||
|
||||
if ( r2.X >= (r1.X + r1.Width) )
|
||||
return false;
|
||||
|
||||
if ( r1.Y >= (r2.Y + r2.Height) )
|
||||
return false;
|
||||
|
||||
if ( r2.Y >= (r1.Y + r1.Height) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CheckContains( Rectangle2D big, Rectangle2D small )
|
||||
{
|
||||
if ( small.X < big.X )
|
||||
return false;
|
||||
|
||||
if ( small.Y < big.Y )
|
||||
return false;
|
||||
|
||||
if ( (small.X + small.Width) > (big.X + big.Width) )
|
||||
return false;
|
||||
|
||||
if ( (small.Y + small.Height) > (big.Y + big.Height) )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool IntersectsWith( Rectangle2D area )
|
||||
{
|
||||
for ( int i = 0; i < m_Area.Length; ++i )
|
||||
{
|
||||
if ( CheckIntersection( area, m_Area[i] ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Weather( Map facet, Rectangle2D[] area, int temperature, int chanceOfPercipitation, int chanceOfExtremeTemperature, TimeSpan interval )
|
||||
{
|
||||
m_Facet = facet;
|
||||
m_Area = area;
|
||||
m_Temperature = temperature;
|
||||
m_ChanceOfPercipitation = chanceOfPercipitation;
|
||||
m_ChanceOfExtremeTemperature = chanceOfExtremeTemperature;
|
||||
|
||||
List<Weather> list = GetWeatherList( facet );
|
||||
|
||||
if ( list != null )
|
||||
list.Add( this );
|
||||
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( (0.2+(Utility.RandomDouble()*0.8)) * interval.TotalSeconds ), interval, new TimerCallback( OnTick ) );
|
||||
}
|
||||
|
||||
public virtual void Reposition()
|
||||
{
|
||||
if ( m_Area.Length == 0 )
|
||||
return;
|
||||
|
||||
int width = m_Area[0].Width;
|
||||
int height = m_Area[0].Height;
|
||||
|
||||
Rectangle2D area = new Rectangle2D();
|
||||
bool isValid = false;
|
||||
|
||||
for ( int j = 0; j < 10; ++j )
|
||||
{
|
||||
area = new Rectangle2D( m_Bounds.X + Utility.Random( m_Bounds.Width - width ), m_Bounds.Y + Utility.Random( m_Bounds.Height - height ), width, height );
|
||||
|
||||
if ( !CheckWeatherConflict( m_Facet, this, area ) )
|
||||
isValid = true;
|
||||
|
||||
if ( isValid )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !isValid )
|
||||
return;
|
||||
|
||||
m_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 );
|
||||
|
||||
m_MoveAngleX = (int)(100 * cos);
|
||||
m_MoveAngleY = (int)(100 * sin);
|
||||
}
|
||||
|
||||
public virtual void MoveForward()
|
||||
{
|
||||
if ( m_Area.Length == 0 )
|
||||
return;
|
||||
|
||||
for ( int i = 0; i < 5; ++i ) // try 5 times to find a valid spot
|
||||
{
|
||||
int xOffset = (m_MoveSpeed * m_MoveAngleX) / 100;
|
||||
int yOffset = (m_MoveSpeed * m_MoveAngleY) / 100;
|
||||
|
||||
Rectangle2D oldArea = m_Area[0];
|
||||
Rectangle2D newArea = new Rectangle2D( oldArea.X + xOffset, oldArea.Y + yOffset, oldArea.Width, oldArea.Height );
|
||||
|
||||
if ( !CheckWeatherConflict( m_Facet, this, newArea ) && CheckContains( m_Bounds, newArea ) )
|
||||
{
|
||||
m_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 = ( m_ChanceOfPercipitation > Utility.Random( 100 ) );
|
||||
m_ExtremeTemperature = ( m_ChanceOfExtremeTemperature > Utility.Random( 100 ) );
|
||||
|
||||
if ( m_MoveSpeed > 0 )
|
||||
{
|
||||
Reposition();
|
||||
RecalculateMovementAngle();
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_Active )
|
||||
{
|
||||
if ( m_Stage > 0 && m_MoveSpeed > 0 )
|
||||
MoveForward();
|
||||
|
||||
int type, density, temperature;
|
||||
|
||||
temperature = m_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 != m_Facet )
|
||||
continue;
|
||||
|
||||
bool contains = ( m_Area.Length == 0 );
|
||||
|
||||
for ( int j = 0; !contains && j < m_Area.Length; ++j )
|
||||
contains = m_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
|
||||
{
|
||||
get { return "weather map"; }
|
||||
}
|
||||
|
||||
[Constructable]
|
||||
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( (int) 0 );
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
119
Scripts/Misc/WebStatus.cs
Normal file
119
Scripts/Misc/WebStatus.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Server;
|
||||
using Server.Network;
|
||||
using Server.Guilds;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public class StatusPage : Timer
|
||||
{
|
||||
public static bool Enabled = false;
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
if ( Enabled )
|
||||
new StatusPage().Start();
|
||||
}
|
||||
|
||||
public StatusPage() : base( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 60.0 ) )
|
||||
{
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
private static string Encode( string input )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder( input );
|
||||
|
||||
sb.Replace( "&", "&" );
|
||||
sb.Replace( "<", "<" );
|
||||
sb.Replace( ">", ">" );
|
||||
sb.Replace( "\"", """ );
|
||||
sb.Replace( "'", "'" );
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( !Directory.Exists( "web" ) )
|
||||
Directory.CreateDirectory( "web" );
|
||||
|
||||
using ( StreamWriter op = new StreamWriter( "web/status.html" ) )
|
||||
{
|
||||
op.WriteLine( "<html>" );
|
||||
op.WriteLine( " <head>" );
|
||||
op.WriteLine( " <title>RunUO Server Status</title>");
|
||||
op.WriteLine( " </head>" );
|
||||
op.WriteLine( " <body bgcolor=\"white\">" );
|
||||
op.WriteLine( " <h1>RunUO Server Status</h1>" );
|
||||
op.WriteLine( " Online clients:<br>" );
|
||||
op.WriteLine( " <table width=\"100%\">" );
|
||||
op.WriteLine( " <tr>" );
|
||||
op.WriteLine( " <td bgcolor=\"black\"><font color=\"white\">Name</font></td><td bgcolor=\"black\"><font color=\"white\">Location</font></td><td bgcolor=\"black\"><font color=\"white\">Kills</font></td><td bgcolor=\"black\"><font color=\"white\">Karma / Fame</font></td>" );
|
||||
op.WriteLine( " </tr>" );
|
||||
|
||||
foreach ( NetState state in NetState.Instances )
|
||||
{
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
if ( m != null )
|
||||
{
|
||||
Guild g = m.Guild as Guild;
|
||||
|
||||
op.Write( " <tr><td>" );
|
||||
|
||||
if ( g != null )
|
||||
{
|
||||
op.Write( Encode( m.Name ) );
|
||||
op.Write( " [" );
|
||||
|
||||
string title = m.GuildTitle;
|
||||
|
||||
if ( title != null )
|
||||
title = title.Trim();
|
||||
else
|
||||
title = "";
|
||||
|
||||
if ( title.Length > 0 )
|
||||
{
|
||||
op.Write( Encode( title ) );
|
||||
op.Write( ", " );
|
||||
}
|
||||
|
||||
op.Write( Encode( g.Abbreviation ) );
|
||||
|
||||
op.Write( ']' );
|
||||
}
|
||||
else
|
||||
{
|
||||
op.Write( Encode( m.Name ) );
|
||||
}
|
||||
|
||||
op.Write( "</td><td>" );
|
||||
op.Write( m.X );
|
||||
op.Write( ", " );
|
||||
op.Write( m.Y );
|
||||
op.Write( ", " );
|
||||
op.Write( m.Z );
|
||||
op.Write( " (" );
|
||||
op.Write( m.Map );
|
||||
op.Write( ")</td><td>" );
|
||||
op.Write( m.Kills );
|
||||
op.Write( "</td><td>" );
|
||||
op.Write( m.Karma );
|
||||
op.Write( " / " );
|
||||
op.Write( m.Fame );
|
||||
op.WriteLine( "</td></tr>" );
|
||||
}
|
||||
}
|
||||
|
||||
op.WriteLine( " <tr>" );
|
||||
op.WriteLine( " </table>" );
|
||||
op.WriteLine( " </body>" );
|
||||
op.WriteLine( "</html>" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
Scripts/Misc/WeightOverloading.cs
Normal file
126
Scripts/Misc/WeightOverloading.cs
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public enum DFAlgorithm
|
||||
{
|
||||
Standard,
|
||||
PainSpike
|
||||
}
|
||||
|
||||
public class WeightOverloading
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
EventSink.Movement += new MovementEventHandler( EventSink_Movement );
|
||||
}
|
||||
|
||||
private static DFAlgorithm m_DFA;
|
||||
|
||||
public static DFAlgorithm DFA
|
||||
{
|
||||
get{ return m_DFA; }
|
||||
set{ m_DFA = value; }
|
||||
}
|
||||
|
||||
public static void FatigueOnDamage( Mobile m, int damage )
|
||||
{
|
||||
double fatigue = 0.0;
|
||||
|
||||
switch ( m_DFA )
|
||||
{
|
||||
case DFAlgorithm.Standard:
|
||||
{
|
||||
fatigue = (damage * (100.0 / m.Hits) * ((double)m.Stam / 100)) - 5.0;
|
||||
break;
|
||||
}
|
||||
case DFAlgorithm.PainSpike:
|
||||
{
|
||||
fatigue = (damage * ((100.0 / m.Hits) + ((50.0 + m.Stam) / 100) - 1.0)) - 5.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( fatigue > 0 )
|
||||
m.Stam -= (int)fatigue;
|
||||
}
|
||||
|
||||
public const int OverloadAllowance = 4; // We can be four stones overweight without getting fatigued
|
||||
|
||||
public static int GetMaxWeight( Mobile m )
|
||||
{
|
||||
return m.MaxWeight;
|
||||
}
|
||||
|
||||
public static void EventSink_Movement( MovementEventArgs e )
|
||||
{
|
||||
Mobile from = e.Mobile;
|
||||
|
||||
if ( !from.Alive || from.AccessLevel > AccessLevel.Player )
|
||||
return;
|
||||
|
||||
if ( !from.Player )
|
||||
{
|
||||
// Else it won't work on monsters.
|
||||
return;
|
||||
}
|
||||
|
||||
int maxWeight = GetMaxWeight( from ) + OverloadAllowance;
|
||||
int overWeight = (Mobile.BodyWeight + from.TotalWeight) - maxWeight;
|
||||
|
||||
if ( overWeight > 0 )
|
||||
{
|
||||
from.Stam -= GetStamLoss( from, overWeight, (e.Direction & Direction.Running) != 0 );
|
||||
|
||||
if ( from.Stam == 0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 500109 ); // You are too fatigued to move, because you are carrying too much weight!
|
||||
e.Blocked = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ((from.Stam * 100) / Math.Max( from.StamMax, 1 )) < 10 )
|
||||
--from.Stam;
|
||||
|
||||
if ( from.Stam == 0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 500110 ); // You are too fatigued to move.
|
||||
e.Blocked = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( from is PlayerMobile )
|
||||
{
|
||||
int amt = ( from.Mounted ? 48 : 16 );
|
||||
PlayerMobile pm = (PlayerMobile)from;
|
||||
|
||||
if ( (++pm.StepsTaken % amt) == 0 )
|
||||
--from.Stam;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetStamLoss( Mobile from, int overWeight, bool running )
|
||||
{
|
||||
int loss = 5 + (overWeight / 25);
|
||||
|
||||
if ( from.Mounted )
|
||||
loss /= 3;
|
||||
|
||||
if ( running )
|
||||
loss *= 2;
|
||||
|
||||
return loss;
|
||||
}
|
||||
|
||||
public static bool IsOverloaded( Mobile m )
|
||||
{
|
||||
if ( !m.Player || !m.Alive || m.AccessLevel > AccessLevel.Player )
|
||||
return false;
|
||||
|
||||
return ( (Mobile.BodyWeight + m.TotalWeight) > (GetMaxWeight( m ) + OverloadAllowance) );
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Scripts/Misc/WelcomeTimer.cs
Normal file
38
Scripts/Misc/WelcomeTimer.cs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
/// <summary>
|
||||
/// This timer spouts some welcome messages to a user at a set interval. It is used on character creation and login.
|
||||
/// </summary>
|
||||
public class WelcomeTimer : Timer
|
||||
{
|
||||
private Mobile m_Mobile;
|
||||
private int m_State, m_Count;
|
||||
|
||||
private static string[] m_Messages = new string[]
|
||||
{
|
||||
"Welcome to Britannia!"
|
||||
};
|
||||
|
||||
public WelcomeTimer( Mobile m ) : this( m, m_Messages.Length )
|
||||
{
|
||||
}
|
||||
|
||||
public WelcomeTimer( Mobile m, int count ) : base( TimeSpan.FromSeconds( 5.0 ), TimeSpan.FromSeconds( 10.0 ) )
|
||||
{
|
||||
m_Mobile = m;
|
||||
m_Count = count;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( m_State < m_Count )
|
||||
m_Mobile.SendMessage( 0x35, m_Messages[m_State++] );
|
||||
|
||||
if ( m_State == m_Count )
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue