ModernUO/Scripts/Engines/Factions/Mobiles/Guards/BaseFactionGuard.cs
2018-09-14 13:22:16 -07:00

494 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Factions.AI;
namespace Server.Factions
{
public abstract class BaseFactionGuard : BaseCreature
{
private Faction m_Faction;
private Town m_Town;
private Orders m_Orders;
public override bool BardImmune => true;
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
public Faction Faction
{
get => m_Faction;
set{ Unregister(); m_Faction = value; Register(); }
}
public Orders Orders => m_Orders;
[CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator )]
public Town Town
{
get => m_Town;
set{ Unregister(); m_Town = value; Register(); }
}
public void Register()
{
if ( m_Town != null && m_Faction != null )
m_Town.RegisterGuard( this );
}
public void Unregister()
{
if ( m_Town != null )
m_Town.UnregisterGuard( this );
}
public abstract GuardAI GuardAI{ get; }
protected override BaseAI ForcedAI => new FactionGuardAI( this );
public override TimeSpan ReacquireDelay => TimeSpan.FromSeconds( 2.0 );
public override bool IsEnemy( Mobile m )
{
Faction ourFaction = m_Faction;
Faction theirFaction = Faction.Find( m );
if ( theirFaction == null && m is BaseFactionGuard guard )
theirFaction = guard.Faction;
if ( ourFaction != null && theirFaction != null && ourFaction != theirFaction )
{
ReactionType reactionType = Orders.GetReaction( theirFaction ).Type;
if ( reactionType == ReactionType.Attack )
return true;
List<AggressorInfo> list = m.Aggressed;
for ( int i = 0; i < list.Count; ++i )
{
AggressorInfo ai = list[i];
if ( ai.Defender is BaseFactionGuard bf && bf.Faction == ourFaction )
return true;
}
}
return false;
}
public override void OnMovement( Mobile m, Point3D oldLocation )
{
if ( m.Player && m.Alive && InRange( m, 10 ) && !InRange( oldLocation, 10 ) && InLOS( m ) && m_Orders.GetReaction( Faction.Find( m ) ).Type == ReactionType.Warn )
{
Direction = GetDirectionTo( m );
string warning = null;
switch ( Utility.Random( 6 ) )
{
case 0: warning = "I warn you, {0}, you would do well to leave this area before someone shows you the world of gray."; break;
case 1: warning = "It would be wise to leave this area, {0}, lest your head become my commanders' trophy."; break;
case 2: warning = "You are bold, {0}, for one of the meager {1}. Leave now, lest you be taught the taste of dirt."; break;
case 3: warning = "Your presence here is an insult, {0}. Be gone now, knave."; break;
case 4: warning = "Dost thou wish to be hung by your toes, {0}? Nay? Then come no closer."; break;
case 5: warning = "Hey, {0}. Yeah, you. Get out of here before I beat you with a stick."; break;
}
Faction faction = Faction.Find( m );
Say( warning, m.Name, faction == null ? "civilians" : faction.Definition.FriendlyName );
}
}
private const int ListenRange = 12;
public override bool HandlesOnSpeech( Mobile from )
{
if ( InRange( from, ListenRange ) )
return true;
return base.HandlesOnSpeech( from );
}
private DateTime m_OrdersEnd;
private void ChangeReaction( Faction faction, ReactionType type )
{
if ( faction == null )
{
switch ( type )
{
case ReactionType.Ignore: Say( 1005179 ); break; // Civilians will now be ignored.
case ReactionType.Warn: Say( 1005180 ); break; // Civilians will now be warned of their impending deaths.
case ReactionType.Attack: return;
}
}
else
{
TextDefinition def = null;
switch ( type )
{
case ReactionType.Ignore: def = faction.Definition.GuardIgnore; break;
case ReactionType.Warn: def = faction.Definition.GuardWarn; break;
case ReactionType.Attack: def = faction.Definition.GuardAttack; break;
}
if ( def != null && def.Number > 0 )
Say( def.Number );
else if ( def?.String != null )
Say( def.String );
}
m_Orders.SetReaction( faction, type );
}
private bool WasNamed( string speech )
{
string name = Name;
return ( name != null && Insensitive.StartsWith( speech, name ) );
}
public override void OnSpeech( SpeechEventArgs e )
{
base.OnSpeech( e );
Mobile from = e.Mobile;
if ( !e.Handled && InRange( from, ListenRange ) && from.Alive )
{
if ( e.HasKeyword( 0xE6 ) && (Insensitive.Equals( e.Speech, "orders" ) || WasNamed( e.Speech )) ) // *orders*
{
if ( m_Town == null || !m_Town.IsSheriff( from ) )
{
Say( 1042189 ); // I don't work for you!
}
else if ( Town.FromRegion( Region ) == m_Town )
{
Say( 1042180 ); // Your orders, sire?
m_OrdersEnd = DateTime.UtcNow + TimeSpan.FromSeconds( 10.0 );
}
}
else if ( DateTime.UtcNow < m_OrdersEnd )
{
if ( m_Town != null && m_Town.IsSheriff( from ) && Town.FromRegion( Region ) == m_Town )
{
m_OrdersEnd = DateTime.UtcNow + TimeSpan.FromSeconds( 10.0 );
bool understood = true;
ReactionType newType = 0;
if ( Insensitive.Contains( e.Speech, "attack" ) )
newType = ReactionType.Attack;
else if ( Insensitive.Contains( e.Speech, "warn" ) )
newType = ReactionType.Warn;
else if ( Insensitive.Contains( e.Speech, "ignore" ) )
newType = ReactionType.Ignore;
else
understood = false;
if ( understood )
{
understood = false;
if ( Insensitive.Contains( e.Speech, "civil" ) )
{
ChangeReaction( null, newType );
understood = true;
}
List<Faction> factions = Faction.Factions;
for ( int i = 0; i < factions.Count; ++i )
{
Faction faction = factions[i];
if ( faction != m_Faction && Insensitive.Contains( e.Speech, faction.Definition.Keyword ) )
{
ChangeReaction( faction, newType );
understood = true;
}
}
}
else if ( Insensitive.Contains( e.Speech, "patrol" ) )
{
Home = Location;
RangeHome = 6;
Combatant = null;
m_Orders.Movement = MovementType.Patrol;
Say( 1005146 ); // This spot looks like it needs protection! I shall guard it with my life.
understood = true;
}
else if ( Insensitive.Contains( e.Speech, "follow" ) )
{
Home = Location;
RangeHome = 6;
Combatant = null;
m_Orders.Follow = from;
m_Orders.Movement = MovementType.Follow;
Say( 1005144 ); // Yes, Sire.
understood = true;
}
if ( !understood )
Say( 1042183 ); // I'm sorry, I don't understand your orders...
}
}
}
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
if ( m_Faction != null && Map == Faction.Facet )
list.Add( 1060846, m_Faction.Definition.PropName ); // Guard: ~1_val~
}
public override void OnSingleClick( Mobile from )
{
if ( m_Faction != null && Map == Faction.Facet )
{
string text = string.Concat( "(Guard, ", m_Faction.Definition.FriendlyName, ")" );
int hue = ( Faction.Find( from ) == m_Faction ? 98 : 38 );
PrivateOverheadMessage( MessageType.Label, hue, true, text, from.NetState );
}
base.OnSingleClick( from );
}
public virtual void GenerateRandomHair()
{
Utility.AssignRandomHair( this );
Utility.AssignRandomFacialHair( this, HairHue );
}
private static Type[] m_StrongPotions = {
typeof( GreaterHealPotion ), typeof( GreaterHealPotion ), typeof( GreaterHealPotion ),
typeof( GreaterCurePotion ), typeof( GreaterCurePotion ), typeof( GreaterCurePotion ),
typeof( GreaterStrengthPotion ), typeof( GreaterStrengthPotion ),
typeof( GreaterAgilityPotion ), typeof( GreaterAgilityPotion ),
typeof( TotalRefreshPotion ), typeof( TotalRefreshPotion ),
typeof( GreaterExplosionPotion )
};
private static Type[] m_WeakPotions = {
typeof( HealPotion ), typeof( HealPotion ), typeof( HealPotion ),
typeof( CurePotion ), typeof( CurePotion ), typeof( CurePotion ),
typeof( StrengthPotion ), typeof( StrengthPotion ),
typeof( AgilityPotion ), typeof( AgilityPotion ),
typeof( RefreshPotion ), typeof( RefreshPotion ),
typeof( ExplosionPotion )
};
public void PackStrongPotions( int min, int max )
{
PackStrongPotions( Utility.RandomMinMax( min, max ) );
}
public void PackStrongPotions( int count )
{
for ( int i = 0; i < count; ++i )
PackStrongPotion();
}
public void PackStrongPotion()
{
PackItem( Loot.Construct( m_StrongPotions ) );
}
public void PackWeakPotions( int min, int max )
{
PackWeakPotions( Utility.RandomMinMax( min, max ) );
}
public void PackWeakPotions( int count )
{
for ( int i = 0; i < count; ++i )
PackWeakPotion();
}
public void PackWeakPotion()
{
PackItem( Loot.Construct( m_WeakPotions ) );
}
public Item Immovable( Item item )
{
item.Movable = false;
return item;
}
public Item Newbied( Item item )
{
item.LootType = LootType.Newbied;
return item;
}
public Item Rehued( Item item, int hue )
{
item.Hue = hue;
return item;
}
public Item Layered( Item item, Layer layer )
{
item.Layer = layer;
return item;
}
public Item Resourced( BaseWeapon weapon, CraftResource resource )
{
weapon.Resource = resource;
return weapon;
}
public Item Resourced( BaseArmor armor, CraftResource resource )
{
armor.Resource = resource;
return armor;
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
Unregister();
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.Delete();
}
public virtual void GenerateBody( bool isFemale, bool randomHair )
{
Hue = Utility.RandomSkinHue();
if ( isFemale )
{
Female = true;
Body = 401;
Name = NameList.RandomName( "female" );
}
else
{
Female = false;
Body = 400;
Name = NameList.RandomName( "male" );
}
if ( randomHair )
GenerateRandomHair();
}
public override bool ClickTitle => false;
public BaseFactionGuard( string title ) : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
m_Orders = new Orders( this );
Title = title;
RangeHome = 6;
}
public BaseFactionGuard( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
Faction.WriteReference( writer, m_Faction );
Town.WriteReference( writer, m_Town );
m_Orders.Serialize( writer );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_Faction = Faction.ReadReference( reader );
m_Town = Town.ReadReference( reader );
m_Orders = new Orders( this, reader );
Timer.DelayCall( TimeSpan.Zero, new TimerCallback( Register ) );
}
}
public class VirtualMount : IMount
{
private VirtualMountItem m_Item;
public Mobile Rider
{
get => m_Item.Rider;
set{}
}
public VirtualMount( VirtualMountItem item )
{
m_Item = item;
}
public virtual void OnRiderDamaged( int amount, Mobile from, bool willKill )
{
}
}
public class VirtualMountItem : Item, IMountItem
{
private Mobile m_Rider;
private VirtualMount m_Mount;
public Mobile Rider => m_Rider;
public VirtualMountItem( Mobile mob ) : base( 0x3EA0 )
{
Layer = Layer.Mount;
m_Rider = mob;
m_Mount = new VirtualMount( this );
}
public IMount Mount => m_Mount;
public VirtualMountItem( Serial serial ) : base( serial )
{
m_Mount = new VirtualMount( this );
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( (Mobile) m_Rider );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_Rider = reader.ReadMobile();
if ( m_Rider == null )
Delete();
}
}
}