ML quest system; first SVN release.

Secondary changes:
- Region fixes, mainly for New Haven.
- Recipe system changes.
- Enabled ML craftables.
- Dyeing/cutting restrictions for quest items.
- Moved IsInvulnerable from BaseVendor to BaseCreature.
- Moved RandomBrightHue to Utility.
- Items no longer decay when attached to a spawner.
- Quest item hue is now faked through packets, instead of overriding Hue.
- Re-enabled item drag effects for SA clients.
- Fixed AssignRandomFacialHair bug in Utility.
- Added random hue comments to Utility.
This commit is contained in:
eos 2013-02-03 01:05:17 +00:00
parent 5c7af18dfb
commit 35fbffdb51
167 changed files with 23218 additions and 234 deletions

View file

@ -71,6 +71,12 @@ namespace Server.Mobiles
public override int Hides{ get{ return 15; } }
public override FoodType FavoriteFood{ get{ return FoodType.GrainsAndHay; } }
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new GamanHorns( Utility.RandomBool() ? 1 : 2 ) );
}
public Gaman( Serial serial ) : base( serial )
{
}

View file

@ -9,6 +9,7 @@ using Server.Misc;
using Server.Items;
using Server.ContextMenus;
using Server.Engines.Quests;
using Server.Engines.MLQuests;
using Server.Engines.PartySystem;
using Server.Factions;
using Server.SkillHandlers;
@ -312,6 +313,86 @@ namespace Server.Mobiles
public virtual Faction FactionAllegiance{ get{ return null; } }
public virtual int FactionSilverWorth{ get{ return 30; } }
#region ML Quest System
private List<MLQuest> m_MLQuests;
public List<MLQuest> MLQuests
{
get
{
if ( m_MLQuests == null )
{
if ( StaticMLQuester )
m_MLQuests = MLQuestSystem.FindQuestList( GetType() );
else
m_MLQuests = ConstructQuestList();
if ( m_MLQuests == null )
return MLQuestSystem.EmptyList; // return EmptyList, but don't cache it (run construction again next time)
}
return m_MLQuests;
}
}
public virtual bool StaticMLQuester { get { return true; } }
protected virtual List<MLQuest> ConstructQuestList()
{
return null;
}
public virtual bool CanGiveMLQuest { get { return ( MLQuests.Count != 0 ); } }
public virtual bool CanShout { get { return false; } }
public const int ShoutRange = 8;
public static readonly TimeSpan ShoutDelay = TimeSpan.FromMinutes( 1 );
private DateTime m_MLNextShout;
private void CheckShout( PlayerMobile pm, Point3D oldLocation )
{
if ( m_MLNextShout > DateTime.Now || pm.Hidden || !pm.Alive )
return;
int shoutRange = ShoutRange;
if ( !InRange( pm.Location, shoutRange ) || InRange( oldLocation, shoutRange ) || !CanSee( pm ) || !InLOS( pm ) )
return;
MLQuestContext context = MLQuestSystem.GetContext( pm );
if ( context != null && context.IsFull )
return;
MLQuest quest = MLQuestSystem.RandomStarterQuest( this, pm );
if ( quest == null || !quest.Activated || ( context != null && context.IsDoingQuest( quest ) ) )
return;
Shout( pm );
m_MLNextShout = DateTime.Now + ShoutDelay;
}
public virtual void Shout( PlayerMobile pm )
{
}
private void RegisterQuests()
{
foreach ( MLQuest quest in MLQuests )
quest.Register( this );
}
private void UnregisterQuests()
{
foreach ( MLQuest quest in MLQuests )
quest.Unregister( this );
}
#endregion
#region Bonding
public const bool BondingEnabled = true;
@ -784,6 +865,8 @@ namespace Server.Mobiles
#endregion
public virtual bool IsInvulnerable { get { return false; } }
public BaseAI AIObject{ get{ return m_AI; } }
public const int MaxOwners = 5;
@ -1647,7 +1730,13 @@ namespace Server.Mobiles
if ( speechType != null )
speechType.OnConstruct( this );
if ( IsInvulnerable && !Core.AOS )
NameHue = 0x35;
GenerateLoot( true );
if ( MLQuestSystem.Enabled && StaticMLQuester )
RegisterQuests();
}
public BaseCreature( Serial serial ) : base( serial )
@ -2010,6 +2099,9 @@ namespace Server.Mobiles
Hue = Paragon.Hue; //Paragon hue fixed, should now be 0x501.
}
if ( Core.AOS && NameHue == 0x35 )
NameHue = -1;
CheckStatTimers();
ChangeAIType(m_CurrentAI);
@ -2018,6 +2110,9 @@ namespace Server.Mobiles
if ( IsAnimatedDead )
Spells.Necromancy.AnimateDeadSpell.Register( m_SummonMaster, this );
if ( MLQuestSystem.Enabled && StaticMLQuester )
RegisterQuests();
}
public virtual bool IsHumanInTown()
@ -2283,6 +2378,14 @@ namespace Server.Mobiles
else if ( CheckGold( from, dropped ) )
return true;
// Note: Yes, this happens for all questers (regardless of type, e.g. escorts),
// even if they can't offer you anything at the moment
if ( MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile )
{
MLQuestSystem.Tell( this, (PlayerMobile)from, 1074893 ); // You need to mark your quest items so I don't take the wrong object. Then speak to me.
return false;
}
return base.OnDragDrop( from, dropped );
}
@ -2886,6 +2989,9 @@ namespace Server.Mobiles
if ( IsAnimatedDead )
Spells.Necromancy.AnimateDeadSpell.Unregister( m_SummonMaster, this );
if ( MLQuestSystem.Enabled )
UnregisterQuests();
base.OnAfterDelete();
}
@ -3549,6 +3655,9 @@ namespace Server.Mobiles
}
/* End notice sound */
if ( MLQuestSystem.Enabled && CanShout && m is PlayerMobile )
CheckShout( (PlayerMobile)m, oldLocation );
if ( m_NoDupeGuards == m )
return;
@ -4323,6 +4432,9 @@ namespace Server.Mobiles
}
}
if ( MLQuestSystem.Enabled && CanGiveMLQuest && from is PlayerMobile )
MLQuestSystem.OnDoubleClick( this, (PlayerMobile)from );
base.OnDoubleClick( from );
}
@ -4362,6 +4474,9 @@ namespace Server.Mobiles
{
base.AddNameProperties( list );
if ( MLQuestSystem.Enabled && CanGiveMLQuest )
list.Add( 1072269 ); // Quest Giver
if ( Core.ML )
{
if ( DisplayWeight )
@ -4720,6 +4835,7 @@ namespace Server.Mobiles
{
int totalFame = Fame / 100;
int totalKarma = -Karma / 100;
if (Map == Map.Felucca)
{
totalFame += ((totalFame/10)*3);
@ -4794,13 +4910,21 @@ namespace Server.Mobiles
TreasuresOfTokuno.HandleKill( this, ds.m_Mobile );
}
if ( givenQuestKill )
continue;
PlayerMobile pm = ds.m_Mobile as PlayerMobile;
if ( pm != null )
{
if ( MLQuestSystem.Enabled )
{
MLQuestSystem.HandleKill( pm, this );
// Kills are given to *everyone* with looting right in the ML quest system
//givenQuestKill = true;
}
if ( givenQuestKill )
continue;
QuestSystem qs = pm.Quest;
if ( qs != null )
@ -4810,6 +4934,7 @@ namespace Server.Mobiles
}
}
}
for ( int i = 0; i < titles.Count; ++i )
{
Titles.AwardFame( titles[ i ], fame[ i ], true );
@ -4862,12 +4987,12 @@ namespace Server.Mobiles
if ( target is BaseFactionGuard )
return false;
if ( (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
if ( ( target is BaseCreature && ( (BaseCreature)target ).IsInvulnerable ) || target is PlayerVendor || target is TownCrier )
{
if ( message )
{
if ( target.Title == null )
SendMessage( "{0} the vendor cannot be harmed.", target.Name );
SendMessage( "{0} cannot be harmed.", target.Name );
else
SendMessage( "{0} {1} cannot be harmed.", target.Name, target.Title );
}
@ -5501,7 +5626,7 @@ namespace Server.Mobiles
public override bool CanBeDamaged()
{
if ( IsDeadPet )
if ( IsDeadPet || IsInvulnerable )
return false;
return base.CanBeDamaged();

View file

@ -47,6 +47,14 @@ namespace Server.Mobiles
return true;
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
if ( Utility.RandomDouble() < 0.5 )
c.DropItem( new FragmentOfAMap() );
}
public EvilWanderingHealer( Serial serial ) : base( serial )
{
}

View file

@ -42,7 +42,7 @@ namespace Server.Mobiles
public override int GetRobeColor()
{
return RandomBrightHue();
return Utility.RandomBrightHue();
}
public override void InitOutfit()
@ -51,9 +51,9 @@ namespace Server.Mobiles
switch ( Utility.Random( 3 ) )
{
case 0: AddItem( new SkullCap( RandomBrightHue() ) ); break;
case 1: AddItem( new WizardsHat( RandomBrightHue() ) ); break;
case 2: AddItem( new Bandana( RandomBrightHue() ) ); break;
case 0: AddItem( new SkullCap( Utility.RandomBrightHue() ) ); break;
case 1: AddItem( new WizardsHat( Utility.RandomBrightHue() ) ); break;
case 2: AddItem( new Bandana( Utility.RandomBrightHue() ) ); break;
}
AddItem( new Spellbook() );

View file

@ -65,6 +65,14 @@ namespace Server.Mobiles
Utility.AssignRandomHair( this );
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
if ( Utility.RandomDouble() < 0.9 )
c.DropItem( new SeveredHumanEars() );
}
public override void GenerateLoot()
{
AddLoot( LootPack.Average );

View file

@ -59,6 +59,15 @@ namespace Server.Mobiles
PackItem( Loot.RandomNecromancyReagent() );
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
// TODO: Check drop rate
if ( Utility.RandomDouble() < 0.05 )
c.DropItem( new StoutWhip() );
}
public override void GenerateLoot()
{
AddLoot( LootPack.Meager, 2 );

View file

@ -0,0 +1,79 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "an Abscess corpse" )]
public class Abscess : Hydra
{
[Constructable]
public Abscess()
{
IsParagon = true;
Name = "Abscess";
Hue = 0x8FD;
SetStr( 845, 871 );
SetDex( 121, 134 );
SetInt( 124, 142 );
SetHits( 7470, 7540 );
SetDamage( 26, 31 );
SetDamageType( ResistanceType.Physical, 60 );
SetDamageType( ResistanceType.Fire, 10 );
SetDamageType( ResistanceType.Cold, 10 );
SetDamageType( ResistanceType.Poison, 10 );
SetDamageType( ResistanceType.Energy, 10 );
SetResistance( ResistanceType.Physical, 65, 75 );
SetResistance( ResistanceType.Fire, 70, 80 );
SetResistance( ResistanceType.Cold, 25, 35 );
SetResistance( ResistanceType.Poison, 35, 45 );
SetResistance( ResistanceType.Energy, 35, 45 );
SetSkill( SkillName.Wrestling, 132.3, 143.8 );
SetSkill( SkillName.Tactics, 121.0, 130.5 );
SetSkill( SkillName.MagicResist, 102.9, 119.0 );
SetSkill( SkillName.Anatomy, 91.8, 94.3 );
// TODO: Fame/Karma
}
public override void GenerateLoot()
{
AddLoot( LootPack.UltraRich, 4 );
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new AbscessTail() );
}
public override bool GivesMLMinorArtifact { get { return true; } }
public Abscess( 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();
}
}
}

View file

@ -0,0 +1,106 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "a Coil corpse" )]
public class Coil : SilverSerpent
{
// TODO: Check faction allegiance
[Constructable]
public Coil()
{
IsParagon = true;
Name = "Coil";
Hue = 0x3F;
SetStr( 205, 343 );
SetDex( 202, 283 );
SetInt( 88, 142 );
SetHits( 628, 1291 );
SetDamage( 19, 28 );
SetDamageType( ResistanceType.Physical, 50 );
SetDamageType( ResistanceType.Poison, 50 );
SetResistance( ResistanceType.Physical, 56, 62 );
SetResistance( ResistanceType.Fire, 25, 30 );
SetResistance( ResistanceType.Cold, 25, 30 );
SetResistance( ResistanceType.Poison, 100 );
SetResistance( ResistanceType.Energy, 25, 30 );
SetSkill( SkillName.Wrestling, 124.5, 141.3 );
SetSkill( SkillName.Tactics, 130.2, 142.0 );
SetSkill( SkillName.MagicResist, 102.3, 113.0 );
SetSkill( SkillName.Anatomy, 120.8, 138.1 );
SetSkill( SkillName.Poisoning, 110.1, 133.4 );
// TODO: Fame/Karma
PackGem( 2 );
PackItem( new Bone() );
}
public override void GenerateLoot()
{
AddLoot( LootPack.UltraRich, 3 );
}
public override WeaponAbility GetWeaponAbility()
{
return WeaponAbility.MortalStrike;
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new CoilsFang() );
/*
// TODO: uncomment once added
if ( Utility.RandomDouble() < 0.025 )
{
switch ( Utility.Random( 5 ) )
{
case 0: c.DropItem( new AssassinChest() ); break;
case 1: c.DropItem( new DeathGloves() ); break;
case 2: c.DropItem( new LeafweaveLegs() ); break;
case 3: c.DropItem( new HunterLegs() ); break;
case 4: c.DropItem( new MyrmidonLegs() ); break;
}
}
*/
}
public override Poison HitPoison { get { return Poison.Lethal; } }
public override Poison PoisonImmune { get { return Poison.Lethal; } }
public override bool GivesMLMinorArtifact { get { return true; } }
public override int Hides { get { return 48; } }
public override int Meat { get { return 1; } }
public Coil( 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();
}
}
}

View file

@ -0,0 +1,46 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "an enslaved satyr corpse" )]
public class EnslavedSatyr : Satyr
{
[Constructable]
public EnslavedSatyr()
{
Name = "an enslaved satyr";
}
/*
// TODO: uncomment once added
public override void OnDeath( Container c )
{
base.OnDeath( c );
if ( Utility.RandomDouble() < 0.1 )
c.DropItem( new ParrotItem() );
}
*/
public EnslavedSatyr( 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();
}
}
}

View file

@ -0,0 +1,91 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "a hydra corpse" )]
public class Hydra : BaseCreature
{
[Constructable]
public Hydra()
: base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
Name = "a hydra";
Body = 0x109;
BaseSoundID = 0x16A;
SetStr( 801, 828 );
SetDex( 102, 118 );
SetInt( 102, 120 );
SetHits( 1480, 1500 );
SetDamage( 21, 26 );
SetDamageType( ResistanceType.Physical, 60 );
SetDamageType( ResistanceType.Fire, 10 );
SetDamageType( ResistanceType.Cold, 10 );
SetDamageType( ResistanceType.Poison, 10 );
SetDamageType( ResistanceType.Energy, 10 );
SetResistance( ResistanceType.Physical, 65, 75 );
SetResistance( ResistanceType.Fire, 70, 85 );
SetResistance( ResistanceType.Cold, 25, 35 );
SetResistance( ResistanceType.Poison, 35, 43 );
SetResistance( ResistanceType.Energy, 36, 45 );
SetSkill( SkillName.Wrestling, 103.5, 117.4 );
SetSkill( SkillName.Tactics, 100.1, 109.8 );
SetSkill( SkillName.MagicResist, 85.5, 98.5 );
SetSkill( SkillName.Anatomy, 75.4, 79.8 );
// TODO: Fame/Karma
}
public override void GenerateLoot()
{
AddLoot( LootPack.UltraRich, 3 );
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new HydraScale() );
/*
// TODO: uncomment once added
if ( Utility.RandomDouble() < 0.2 )
c.DropItem( new ParrotItem() );
if ( Utility.RandomDouble() < 0.05 )
c.DropItem( new ThorvaldsMedallion() );
*/
}
public override bool HasBreath { get { return true; } }
public override int Hides { get { return 40; } }
public override int Meat { get { return 19; } }
public override int TreasureMapLevel { get { return 5; } }
public Hydra( 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();
}
}
}

View file

@ -0,0 +1,50 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "an insane dryad corpse" )]
public class InsaneDryad : MLDryad
{
public override bool InitialInnocent { get { return false; } }
[Constructable]
public InsaneDryad()
{
Name = "an insane dryad";
// TODO: Perhaps these should have negative karma?
}
/*
// TODO: uncomment once added
public override void OnDeath( Container c )
{
base.OnDeath( c );
if ( Utility.RandomDouble() < 0.1 )
c.DropItem( new ParrotItem() );
}
*/
public InsaneDryad( 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();
}
}
}

View file

@ -0,0 +1,77 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "a Saliva corpse" )]
public class Saliva : Harpy
{
[Constructable]
public Saliva()
{
// TODO: Not a paragon? No ML arties?
// It moves like a paragon on OSI...
Name = "Saliva";
Hue = 0x11E;
SetStr( 110, 206 );
SetDex( 123, 222 );
SetInt( 80, 127 );
SetHits( 409, 842 );
SetDamage( 20, 22 );
SetDamageType( ResistanceType.Physical, 100 );
SetResistance( ResistanceType.Physical, 46, 48 );
SetResistance( ResistanceType.Fire, 32, 40 );
SetResistance( ResistanceType.Cold, 34, 49 );
SetResistance( ResistanceType.Poison, 40, 48 );
SetResistance( ResistanceType.Energy, 35, 39 );
SetSkill( SkillName.Wrestling, 106.4, 128.8 );
SetSkill( SkillName.Tactics, 129.9, 141.0 );
SetSkill( SkillName.MagicResist, 84.3, 105.0 );
// TODO: Fame/Karma?
}
public override void GenerateLoot()
{
AddLoot( LootPack.UltraRich, 2 );
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new SalivasFeather() );
// TODO: uncomment once added
//if ( Utility.RandomDouble() < 0.1 )
// c.DropItem( new ParrotItem() );
}
public Saliva( 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();
}
}
}

View file

@ -0,0 +1,78 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "a Tangle corpse" )]
public class Tangle : BogThing
{
[Constructable]
public Tangle()
{
// TODO: Not a paragon? No ML arties?
// It moves like a paragon on OSI...
Name = "Tangle";
Hue = 0x21;
SetStr( 870, 940 );
SetDex( 58, 74 );
SetInt( 46, 58 );
SetHits( 2468, 2733 );
SetMana( 8, 12 );
SetDamage( 15, 28 );
SetDamageType( ResistanceType.Physical, 60 );
SetDamageType( ResistanceType.Poison, 40 );
SetResistance( ResistanceType.Physical, 50, 57 );
SetResistance( ResistanceType.Fire, 40, 43 );
SetResistance( ResistanceType.Cold, 30, 35 );
SetResistance( ResistanceType.Poison, 61, 69 );
SetResistance( ResistanceType.Energy, 41, 45 );
SetSkill( SkillName.Wrestling, 77.8, 94.6 );
SetSkill( SkillName.Tactics, 90.6, 100.4 );
SetSkill( SkillName.MagicResist, 108.4, 114.0 );
// TODO: Fame/Karma?
}
public override void GenerateLoot()
{
AddLoot( LootPack.UltraRich, 3 );
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
if ( Utility.RandomDouble() < 0.3 )
c.DropItem( new TaintedSeeds() );
}
public override Poison PoisonImmune { get { return Poison.Lethal; } }
public Tangle( 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();
}
}
}

View file

@ -0,0 +1,81 @@
using System;
using Server;
using Server.Items;
namespace Server.Mobiles
{
[CorpseName( "a Thrasher corpse" )]
public class Thrasher : Alligator
{
[Constructable]
public Thrasher()
{
IsParagon = true;
Name = "Thrasher";
Hue = 0x497;
SetStr( 93, 327 );
SetDex( 7, 201 );
SetInt( 15, 67 );
SetHits( 260, 984 );
SetStam( 56, 75 );
SetMana( 25, 30 );
SetDamage( 20, 30 );
SetDamageType( ResistanceType.Physical, 100 );
SetResistance( ResistanceType.Physical, 50, 55 );
SetResistance( ResistanceType.Fire, 25, 29 );
SetResistance( ResistanceType.Poison, 25, 28 );
SetSkill( SkillName.Wrestling, 101.2, 118.3 );
SetSkill( SkillName.Tactics, 96.3, 117.3 );
SetSkill( SkillName.MagicResist, 102.4, 118.6 );
// TODO: Fame/Karma
}
public override void GenerateLoot()
{
AddLoot( LootPack.FilthyRich, 4 );
}
public override WeaponAbility GetWeaponAbility()
{
return WeaponAbility.ArmorIgnore;
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
c.DropItem( new ThrashersTail() );
}
public override bool GivesMLMinorArtifact { get { return true; } }
public override int Hides { get { return 48; } }
public override int Meat { get { return 1; } }
public Thrasher( 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();
}
}
}

View file

@ -54,6 +54,14 @@ namespace Server.Mobiles
AddLoot( LootPack.Rich ); // Need to verify
}
public override void OnDeath( Container c )
{
base.OnDeath( c );
if ( Utility.RandomDouble() < 0.1 )
c.DropItem( new PrimitiveFetish() );
}
public Troglodyte( Serial serial ) : base( serial )
{
}

View file

@ -24,6 +24,7 @@ using Server.Engines.CannedEvil;
using Server.Engines.Craft;
using Server.Spells.Spellweaving;
using Server.Engines.PartySystem;
using Server.Engines.MLQuests;
namespace Server.Mobiles
{
@ -112,7 +113,7 @@ namespace Server.Mobiles
private int m_Profession;
private bool m_IsStealthing; // IsStealthing should be moved to Server.Mobiles
private bool m_IgnoreMobiles; // IgnoreMobiles should be moved to Server.Mobiles
private int m_NonAutoreinsuredItems; // number of items that could not be automaitically reinsured because gold in bank was not enough
private int m_NonAutoreinsuredItems; // number of items that could not be automatically reinsured because gold in bank was not enough
private bool m_NinjaWepCooldown;
/*
* a value of zero means, that the mobile is not executing the spell. Otherwise,
@ -1257,12 +1258,12 @@ namespace Server.Mobiles
if ( m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null) )
return false;
if ( (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
if ( (target is BaseCreature && ((BaseCreature)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
{
if ( message )
{
if ( target.Title == null )
SendMessage( "{0} the vendor cannot be harmed.", target.Name );
SendMessage( "{0} cannot be harmed.", target.Name );
else
SendMessage( "{0} {1} cannot be harmed.", target.Name, target.Title );
}
@ -1590,14 +1591,20 @@ namespace Server.Mobiles
if ( m_Quest != null )
m_Quest.GetContextMenuEntries( list );
if ( Alive && InsuranceEnabled )
if ( Alive )
{
list.Add( new CallbackEntry( 6201, new ContextCallback( ToggleItemInsurance ) ) );
if ( InsuranceEnabled )
{
list.Add( new CallbackEntry( 6201, new ContextCallback( ToggleItemInsurance ) ) ); // Toggle Item Insurance
if ( AutoRenewInsurance )
list.Add( new CallbackEntry( 6202, new ContextCallback( CancelRenewInventoryInsurance ) ) );
else
list.Add( new CallbackEntry( 6200, new ContextCallback( AutoRenewInventoryInsurance ) ) );
if ( AutoRenewInsurance )
list.Add( new CallbackEntry( 6202, new ContextCallback( CancelRenewInventoryInsurance ) ) ); // Cancel Renewing Inventory Insurance
else
list.Add( new CallbackEntry( 6200, new ContextCallback( AutoRenewInventoryInsurance ) ) ); // Auto Renew Inventory Insurance
}
if ( MLQuestSystem.Enabled )
list.Add( new CallbackEntry( 6169, new ContextCallback( ToggleQuestItem ) ) ); // Toggle Quest Item
}
BaseHouse house = BaseHouse.FindHouseAt( this );
@ -1815,6 +1822,62 @@ namespace Server.Mobiles
#endregion
#region Toggle Quest Item
private void ToggleQuestItem()
{
if ( !CheckAlive() )
return;
ToggleQuestItemTarget();
}
private void ToggleQuestItemTarget()
{
Server.Engines.MLQuests.Gumps.BaseQuestGump.CloseOtherGumps( this );
CloseGump( typeof( Server.Engines.MLQuests.Gumps.QuestLogDetailedGump ) );
CloseGump( typeof( Server.Engines.MLQuests.Gumps.QuestLogGump ) );
CloseGump( typeof( Server.Engines.MLQuests.Gumps.QuestOfferGump ) );
//CloseGump( typeof( UnknownGump802 ) );
//CloseGump( typeof( UnknownGump804 ) );
BeginTarget( -1, false, TargetFlags.None, new TargetCallback( ToggleQuestItem_Callback ) );
SendLocalizedMessage( 1072352 ); // Target the item you wish to toggle Quest Item status on <ESC> to cancel
}
private void ToggleQuestItem_Callback( Mobile from, object obj )
{
if ( !CheckAlive() )
return;
Item item = obj as Item;
if ( item == null )
return;
if ( from.Backpack == null || item.Parent != from.Backpack )
{
SendLocalizedMessage( 1074769 ); // An item must be in your backpack (and not in a container within) to be toggled as a quest item.
}
else if ( item.QuestItem )
{
item.QuestItem = false;
SendLocalizedMessage( 1072354 ); // You remove Quest Item status from the item
}
else if ( MLQuestSystem.MarkQuestItem( this, item ) )
{
SendLocalizedMessage( 1072353 ); // You set the item to Quest Item status
}
else
{
SendLocalizedMessage( 1072355, "", 0x23 ); // That item does not match any of your quest criteria
}
ToggleQuestItemTarget();
}
#endregion
private void GetVendor()
{
BaseHouse house = BaseHouse.FindHouseAt( this );
@ -2341,6 +2404,10 @@ namespace Server.Mobiles
public override DeathMoveResult GetParentMoveResultFor( Item item )
{
// It seems all items are unmarked on death, even blessed/insured ones
if ( item.QuestItem )
item.QuestItem = false;
if ( CheckInsuranceOnDeath( item ) )
return DeathMoveResult.MoveToBackpack;
@ -2354,6 +2421,10 @@ namespace Server.Mobiles
public override DeathMoveResult GetInventoryMoveResultFor( Item item )
{
// It seems all items are unmarked on death, even blessed/insured ones
if ( item.QuestItem )
item.QuestItem = false;
if ( CheckInsuranceOnDeath( item ) )
return DeathMoveResult.MoveToBackpack;
@ -2466,6 +2537,8 @@ namespace Server.Mobiles
Server.Guilds.Guild.HandleDeath( this, killer );
MLQuestSystem.HandleDeath( this );
#region Dueling
if ( m_DuelContext != null )
m_DuelContext.OnDeath( this, c );
@ -3366,6 +3439,8 @@ namespace Server.Mobiles
if ( faction != null )
faction.RemoveMember( this );
MLQuestSystem.HandleDeletion( this );
BaseHouse.HandleDeletion( this );
DisguiseTimers.RemoveTimer( this );
@ -3653,6 +3728,9 @@ namespace Server.Mobiles
acc.RemoveYoungStatus( 1019036 ); // You have successfully obtained a respectable skill level, and have outgrown your status as a young player!
}
if ( MLQuestSystem.Enabled )
MLQuestSystem.HandleSkillGain( this, skill );
InvalidateMyRunUO();
}
@ -3874,7 +3952,9 @@ namespace Server.Mobiles
private int m_CompassionGains;
public DateTime LastCompassionLoss{ get{ return m_LastCompassionLoss; } set{ m_LastCompassionLoss = value; } }
[CommandProperty( AccessLevel.GameMaster )]
public DateTime NextCompassionDay{ get{ return m_NextCompassionDay; } set{ m_NextCompassionDay = value; } }
[CommandProperty( AccessLevel.GameMaster )]
public int CompassionGains{ get{ return m_CompassionGains; } set{ m_CompassionGains = value; } }
private DateTime m_LastValorLoss;

View file

@ -6,18 +6,109 @@ using Server.Items;
using Server.Network;
using Server.ContextMenus;
using EDI = Server.Mobiles.EscortDestinationInfo;
using Server.Engines.MLQuests;
using Server.Engines.MLQuests.Definitions;
using Server.Engines.MLQuests.Objectives;
namespace Server.Mobiles
{
public class BaseEscortable : BaseCreature
{
public static readonly TimeSpan EscortDelay = TimeSpan.FromMinutes( 5.0 );
public static readonly TimeSpan AbandonDelay = MLQuestSystem.Enabled ? TimeSpan.FromMinutes( 1.0 ) : TimeSpan.FromMinutes( 2.0 );
public static readonly TimeSpan DeleteTime = MLQuestSystem.Enabled ? TimeSpan.FromSeconds( 100 ) : TimeSpan.FromSeconds( 30 );
public override bool StaticMLQuester { get { return false; } } // Suppress automatic quest registration on creation/deserialization
private MLQuest m_MLQuest;
protected override List<MLQuest> ConstructQuestList()
{
if ( m_MLQuest == null )
{
Region reg = Region;
Type[] list = reg.IsPartOf( "Haven Island" ) ? m_MLQuestTypesNH : m_MLQuestTypes;
if ( MLQuestSystem.Debug )
Console.WriteLine( "DEBUG: Assigning quest to BaseEscortable {0}, Region = {1}", Serial, ( reg == null ) ? "-null-" : reg.Name );
int randomIdx = Utility.Random( list.Length );
for ( int i = 0; i < list.Length; ++i )
{
Type questType = list[randomIdx];
MLQuest quest = MLQuestSystem.FindQuest( questType );
if ( quest != null )
{
bool okay = true;
foreach ( BaseObjective obj in quest.Objectives )
{
if ( obj is EscortObjective && ( (EscortObjective)obj ).Destination.Contains( reg ) )
{
okay = false; // We're already there!
break;
}
}
if ( okay )
{
SetMLQuest( quest );
break;
}
}
else if ( MLQuestSystem.Debug )
{
Console.WriteLine( "WARNING: Type {0} should not be eligible as it is not a registered quest", questType.Name );
}
randomIdx = ( randomIdx + 1 ) % list.Length;
}
if ( m_MLQuest == null )
{
if ( MLQuestSystem.Debug )
Console.WriteLine( "WARNING: No suitable quest found for escort {0}", Serial );
return null;
}
}
List<MLQuest> result = new List<MLQuest>();
result.Add( m_MLQuest );
return result;
}
public override bool CanShout { get { return ( !Controlled && !IsBeingDeleted ); } }
public override void Shout( PlayerMobile pm )
{
/*
* 1072301 - You there! Care to hear how to earn some easy gold?
* 1072302 - Adventurer! I have an offer for you.
* 1072303 - Wait! I have an opportunity for you to make some gold!
*/
MLQuestSystem.Tell( this, pm, Utility.Random( 1072301, 3 ) );
}
private EDI m_Destination;
private string m_DestinationString;
private DateTime m_DeleteTime;
private Timer m_DeleteTimer;
private bool m_DeleteCorpse = false;
public bool IsBeingDeleted
{
get { return ( m_DeleteTimer != null ); }
}
public override bool Commandable { get { return false; } } // Our master cannot boss us around!
public override bool DeleteCorpseOnDeath { get { return m_DeleteCorpse; } }
[CommandProperty(AccessLevel.GameMaster)]
public string Destination
@ -26,26 +117,78 @@ namespace Server.Mobiles
set { m_DestinationString = value; m_Destination = EDI.Find(value); }
}
// Classic list
// Used when: !MLQuestSystem.Enabled && !Core.ML
private static string[] m_TownNames = new string[]
{
"Cove", "Britain", "Jhelom",
"Minoc", "Ocllo", "Trinsic",
"Vesper", "Yew", "Skara Brae", //Original List, will need to add it back for Pre-ML shards
"Vesper", "Yew", "Skara Brae",
"Nujel'm", "Moonglow", "Magincia"
};
// ML list, pre-ML quest system
// Used when: !MLQuestSystem.Enabled && Core.ML
private static string[] m_MLTownNames = new string[]
{
"Cove", "Serpent's Hold", "Jhelom", //ML List
"Cove", "Serpent's Hold", "Jhelom",
"Nujel'm"
};
// ML quest system general list
// Used when: MLQuestSystem.Enabled && !Region.IsPartOf( "Haven Island" )
private static Type[] m_MLQuestTypes =
{
typeof( EscortToYew ),
typeof( EscortToVesper ),
typeof( EscortToTrinsic ),
typeof( EscortToSkaraBrae ),
typeof( EscortToSerpentsHold ),
typeof( EscortToNujelm ),
typeof( EscortToMoonglow ),
typeof( EscortToMinoc ),
typeof( EscortToMagincia ),
typeof( EscortToJhelom ),
typeof( EscortToCove ),
typeof( EscortToBritain )
// Ocllo was removed in pub 56
//typeof( EscortToOcllo )
};
// ML quest system New Haven list
// Used when: MLQuestSystem.Enabled && Region.IsPartOf( "Haven Island" )
private static Type[] m_MLQuestTypesNH =
{
typeof( EscortToNHAlchemist ),
typeof( EscortToNHBard ),
typeof( EscortToNHWarrior ),
typeof( EscortToNHTailor ),
typeof( EscortToNHCarpenter ),
typeof( EscortToNHMapmaker ),
typeof( EscortToNHMage ),
typeof( EscortToNHInn ),
// Farm destination was removed
//typeof( EscortToNHFarm ),
typeof( EscortToNHDocks ),
typeof( EscortToNHBowyer ),
typeof( EscortToNHBank )
};
public void SetMLQuest( MLQuest quest )
{
m_MLQuest = quest;
quest.Register( this );
}
[Constructable]
public BaseEscortable()
: base(AIType.AI_Melee, FightMode.Aggressor, 22, 1, 0.2, 1.0)
{
InitBody();
InitOutfit();
Fame = 200;
Karma = 4000;
}
public virtual void InitBody()
@ -109,8 +252,6 @@ namespace Server.Mobiles
get { return m_EscortTable; }
}
private static TimeSpan m_EscortDelay = TimeSpan.FromMinutes(5.0);
public virtual bool AcceptEscorter(Mobile m)
{
EDI dest = GetDestination();
@ -130,9 +271,9 @@ namespace Server.Mobiles
Say("I see you already have an escort.");
return false;
}
else if (m is PlayerMobile && (((PlayerMobile)m).LastEscortTime + m_EscortDelay) >= DateTime.Now)
else if (m is PlayerMobile && (((PlayerMobile)m).LastEscortTime + EscortDelay) >= DateTime.Now)
{
int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + m_EscortDelay) - DateTime.Now).TotalMinutes);
int minutes = (int)Math.Ceiling(((((PlayerMobile)m).LastEscortTime + EscortDelay) - DateTime.Now).TotalMinutes);
Say("You must rest {0} minute{1} before we set out on this journey.", minutes, minutes == 1 ? "" : "s");
return false;
@ -155,6 +296,9 @@ namespace Server.Mobiles
public override bool HandlesOnSpeech(Mobile from)
{
if ( MLQuestSystem.Enabled )
return false;
if (from.InRange(this.Location, 3))
return true;
@ -202,6 +346,8 @@ namespace Server.Mobiles
return true;
}
// TODO: Pre-ML methods below, might be mergeable with the ML methods in EscortObjective
public virtual void StartFollow()
{
StartFollow(GetEscorter());
@ -240,13 +386,13 @@ namespace Server.Mobiles
public virtual Mobile GetEscorter()
{
if (!Controlled)
if ( !Controlled )
return null;
Mobile master = ControlMaster;
if (master == null)
return null;
if ( MLQuestSystem.Enabled || master == null )
return master;
if (master.Deleted || master.Map != this.Map || !master.InRange(Location, 30) || !master.Alive)
{
@ -254,7 +400,7 @@ namespace Server.Mobiles
TimeSpan lastSeenDelay = DateTime.Now - m_LastSeenEscorter;
if (lastSeenDelay >= TimeSpan.FromMinutes(2.0))
if (lastSeenDelay >= AbandonDelay)
{
master.SendLocalizedMessage(1042473); // You have lost the person you were escorting.
Say(1005653); // Hmmm. I seem to have lost my master.
@ -284,7 +430,7 @@ namespace Server.Mobiles
if (m_DeleteTimer != null)
m_DeleteTimer.Stop();
m_DeleteTime = DateTime.Now + TimeSpan.FromSeconds(30.0);
m_DeleteTime = DateTime.Now + DeleteTime;
m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now);
m_DeleteTimer.Start();
@ -292,6 +438,9 @@ namespace Server.Mobiles
public virtual bool CheckAtDestination()
{
if ( MLQuestSystem.Enabled )
return false;
EDI dest = GetDestination();
if (dest == null)
@ -352,6 +501,9 @@ namespace Server.Mobiles
pm.NextCompassionDay = DateTime.Now + TimeSpan.FromDays(1.0); // in one day CompassionGains gets reset to 0
++pm.CompassionGains;
if (pm.CompassionGains >= 5)
pm.SendLocalizedMessage(1053004); // You must wait about a day before you can gain in compassion again.
}
else
{
@ -365,6 +517,13 @@ namespace Server.Mobiles
return false;
}
public override bool OnBeforeDeath()
{
m_DeleteCorpse = ( Controlled || IsBeingDeleted );
return base.OnBeforeDeath();
}
public BaseEscortable(Serial serial)
: base(serial)
{
@ -374,7 +533,7 @@ namespace Server.Mobiles
{
base.Serialize(writer);
writer.Write((int)0); // version
writer.Write((int)1); // version
EDI dest = GetDestination();
@ -387,6 +546,8 @@ namespace Server.Mobiles
if (m_DeleteTimer != null)
writer.WriteDeltaTime(m_DeleteTime);
MLQuestSystem.WriteQuestRef( writer, StaticMLQuester ? null : m_MLQuest );
}
public override void Deserialize(GenericReader reader)
@ -404,6 +565,14 @@ namespace Server.Mobiles
m_DeleteTimer = new DeleteTimer(this, m_DeleteTime - DateTime.Now);
m_DeleteTimer.Start();
}
if ( version >= 1 )
{
MLQuest quest = MLQuestSystem.ReadQuestRef( reader );
if ( quest != null && !StaticMLQuester )
SetMLQuest( quest );
}
}
public override bool CanBeRenamedBy(Mobile from)
@ -411,24 +580,26 @@ namespace Server.Mobiles
return (from.AccessLevel >= AccessLevel.GameMaster);
}
public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
public override void AddCustomContextEntries( Mobile from, List<ContextMenuEntry> list )
{
EDI dest = GetDestination();
if (dest != null && from.Alive)
if ( from.Alive )
{
Mobile escorter = GetEscorter();
if (escorter == null || escorter == from)
list.Add(new AskDestinationEntry(this, from));
if ( !MLQuestSystem.Enabled && GetDestination() != null )
{
if ( escorter == null || escorter == from )
list.Add( new AskDestinationEntry( this, from ) );
if (escorter == null)
list.Add(new AcceptEscortEntry(this, from));
else if (escorter == from)
list.Add(new AbandonEscortEntry(this, from));
if ( escorter == null )
list.Add( new AcceptEscortEntry( this, from ) );
}
if ( escorter == from )
list.Add( new AbandonEscortEntry( this, from ) );
}
base.AddCustomContextEntries(from, list);
base.AddCustomContextEntries( from, list );
}
public virtual string[] GetPossibleDestinations()
@ -461,6 +632,9 @@ namespace Server.Mobiles
public EDI GetDestination()
{
if ( MLQuestSystem.Enabled )
return null;
if (m_DestinationString == null && m_DeleteTimer == null)
m_DestinationString = PickRandomDestination();

View file

@ -11,10 +11,9 @@ namespace Server.Mobiles
public BrideGroom()
{
if ( Female )
Title = "the bride";
Title = "the bride";
else
Title = "the groom";
Title = "the groom";
}
public override bool CanTeach{ get{ return true; } }
@ -37,8 +36,7 @@ namespace Server.Mobiles
public override void InitOutfit()
{
if ( Female )
AddItem( new FancyDress() );
AddItem( new FancyDress() );
else
AddItem( new FancyShirt() );
@ -51,8 +49,6 @@ namespace Server.Mobiles
else
AddItem( new Boots( lowHue ) );
if( Utility.RandomBool() )
HairItemID = 0x203B;
else

View file

@ -11,7 +11,6 @@ namespace Server.Mobiles
public Messenger()
{
Title = "the messenger";
}
public override bool CanTeach{ get{ return true; } }

View file

@ -0,0 +1,83 @@
using System;
using Server.Items;
using Server.Engines.MLQuests;
namespace Server.Mobiles.Townfolk
{
public class Prisoner : BaseEscortable
{
[Constructable]
public Prisoner()
{
Title = Female ? "the noblewoman" : "the nobleman";
CantWalk = true;
IsPrisoner = true;
}
public override bool CanTeach { get { return true; } }
public override bool ClickTitle { get { return false; } }
public override void InitOutfit()
{
if ( Female )
{
AddItem( new FancyDress( Utility.RandomNondyedHue() ) );
}
else
{
AddItem( new FancyShirt( Utility.RandomNondyedHue() ) );
AddItem( new LongPants( Utility.RandomNondyedHue() ) );
}
if ( Utility.RandomBool() )
AddItem( new Boots() );
else
AddItem( new ThighBoots() );
Utility.AssignRandomHair( this );
Utility.AssignRandomFacialHair( this, HairHue );
}
public override void Shout( PlayerMobile pm )
{
/*
* 502261 - HELP!
* 502262 - Help me!
* 502263 - Canst thou aid me?!
* 502264 - Help a poor prisoner!
* 502265 - Help! Please!
* 502266 - Aaah! Help me!
* 502267 - Go and get some help!
*/
MLQuestSystem.Tell( this, pm, Utility.Random( 502261, 7 ) );
}
public override void OnMovement( Mobile m, Point3D oldLocation )
{
base.OnMovement( m, oldLocation );
if ( CantWalk && InRange( m, 1 ) && !InRange( oldLocation, 1 ) && ( !m.Hidden || m.AccessLevel == AccessLevel.Player ) )
Say( 502268 ); // Quickly, I beg thee! Unlock my chains! If thou dost look at me close thou canst see them.
}
public Prisoner( 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();
}
}
}

View file

@ -46,7 +46,7 @@ namespace Server.Mobiles
public virtual NpcGuild NpcGuild { get { return NpcGuild.None; } }
public virtual bool IsInvulnerable { get { return true; } }
public override bool IsInvulnerable { get { return true; } }
public virtual DateTime NextTrickOrTreat { get { return m_NextTrickOrTreat; } set { m_NextTrickOrTreat = value; } }
@ -265,9 +265,6 @@ namespace Server.Mobiles
SpeechHue = Utility.RandomDyedHue();
Hue = Utility.RandomSkinHue();
if ( IsInvulnerable && !Core.AOS )
NameHue = 0x35;
if ( Female = GetGender() )
{
Body = 0x191;
@ -306,14 +303,6 @@ namespace Server.Mobiles
get { return VendorShoeType.Shoes; }
}
public virtual int RandomBrightHue()
{
if ( 0.1 > Utility.RandomDouble() )
return Utility.RandomList( 0x62, 0x71 );
return Utility.RandomList( 0x03, 0x0D, 0x13, 0x1C, 0x21, 0x30, 0x37, 0x3A, 0x44, 0x59 );
}
public virtual void CheckMorph()
{
if ( CheckGargoyle() )
@ -439,7 +428,7 @@ namespace Server.Mobiles
FacialHairItemID = 0;
Body = 0x2F6;
Hue = RandomBrightHue() | 0x8000;
Hue = Utility.RandomBrightHue() | 0x8000;
Name = NameList.RandomName( "gargoyle vendor" );
CapitalizeTitle();
@ -1015,7 +1004,7 @@ namespace Server.Mobiles
if ( cont.ConsumeTotal( typeof( Gold ), totalCost ) )
bought = true;
else if ( totalCost < 2000 )
SayTo( buyer, 500192 );//Begging thy pardon, but thou casnt afford that.
SayTo( buyer, 500192 ); // Begging thy pardon, but thou canst not afford that.
}
if ( !bought && totalCost >= 2000 )
@ -1394,9 +1383,6 @@ namespace Server.Mobiles
if ( IsParagon )
IsParagon = false;
if ( Core.AOS && NameHue == 0x35 )
NameHue = -1;
Timer.DelayCall( TimeSpan.Zero, new TimerCallback( CheckMorph ) );
}
@ -1426,11 +1412,6 @@ namespace Server.Mobiles
{
return (IBuyItemInfo[])m_ArmorBuyInfo.ToArray( typeof( IBuyItemInfo ) );
}
public override bool CanBeDamaged()
{
return !IsInvulnerable;
}
}
}

View file

@ -104,7 +104,7 @@ namespace Server.Mobiles
public bool IsSellable( Item item )
{
if ( item.QuestItem )
if ( item.Nontransferable )
return false;
//if ( item.Hue != 0 )
@ -115,7 +115,7 @@ namespace Server.Mobiles
public bool IsResellable( Item item )
{
if ( item.QuestItem )
if ( item.Nontransferable )
return false;
//if ( item.Hue != 0 )

View file

@ -25,7 +25,7 @@ namespace Server.Mobiles
{
base.InitOutfit();
AddItem( new HalfApron( RandomBrightHue() ) );
AddItem( new HalfApron( Utility.RandomBrightHue() ) );
}
[Constructable]

View file

@ -59,7 +59,7 @@ namespace Server.Mobiles
public override int GetHairHue()
{
return RandomBrightHue();
return Utility.RandomBrightHue();
}
public override VendorShoeType ShoeType

View file

@ -37,32 +37,32 @@ namespace Server.Mobiles
Item item = FindItemOnLayer( Layer.Pants );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterTorso );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerTorso );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.Shirt );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
}
public GypsyAnimalTrainer( Serial serial ) : base( serial )

View file

@ -27,45 +27,45 @@ namespace Server.Mobiles
switch ( Utility.Random( 4 ) )
{
case 0: AddItem( new JesterHat( RandomBrightHue() ) ); break;
case 1: AddItem( new Bandana( RandomBrightHue() ) ); break;
case 2: AddItem( new SkullCap( RandomBrightHue() ) ); break;
case 0: AddItem( new JesterHat( Utility.RandomBrightHue() ) ); break;
case 1: AddItem( new Bandana( Utility.RandomBrightHue() ) ); break;
case 2: AddItem( new SkullCap( Utility.RandomBrightHue() ) ); break;
}
Item item = FindItemOnLayer( Layer.Pants );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.Shoes );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterTorso );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerTorso );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.Shirt );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
}
public GypsyBanker( Serial serial ) : base( serial )

View file

@ -35,28 +35,28 @@ namespace Server.Mobiles
switch ( Utility.Random( 4 ) )
{
case 0: AddItem( new JesterHat( RandomBrightHue() ) ); break;
case 1: AddItem( new Bandana( RandomBrightHue() ) ); break;
case 2: AddItem( new SkullCap( RandomBrightHue() ) ); break;
case 0: AddItem( new JesterHat( Utility.RandomBrightHue() ) ); break;
case 1: AddItem( new Bandana( Utility.RandomBrightHue() ) ); break;
case 2: AddItem( new SkullCap( Utility.RandomBrightHue() ) ); break;
}
if ( Utility.RandomBool() )
AddItem( new HalfApron( RandomBrightHue() ) );
AddItem( new HalfApron( Utility.RandomBrightHue() ) );
Item item = FindItemOnLayer( Layer.Pants );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
}
public GypsyMaiden( Serial serial ) : base( serial )

View file

@ -62,12 +62,12 @@ namespace Server.Mobiles
switch ( Utility.Random( 3 ) )
{
case 0:
case 1: AddItem( new JesterHat( RandomBrightHue() ) ); break;
case 2: AddItem( new Bandana( RandomBrightHue() ) ); break;
case 1: AddItem( new JesterHat( Utility.RandomBrightHue() ) ); break;
case 2: AddItem( new Bandana( Utility.RandomBrightHue() ) ); break;
}
if ( item == null )
AddItem( new FullApron( RandomBrightHue() ) );
AddItem( new FullApron( Utility.RandomBrightHue() ) );
AddItem( new Bascinet() );
AddItem( new SmithHammer() );
@ -75,32 +75,32 @@ namespace Server.Mobiles
item = FindItemOnLayer( Layer.Pants );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerLegs );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.OuterTorso );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.InnerTorso );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
item = FindItemOnLayer( Layer.Shirt );
if ( item != null )
item.Hue = RandomBrightHue();
item.Hue = Utility.RandomBrightHue();
}
public IronWorker( Serial serial ) : base( serial )

View file

@ -11,6 +11,9 @@ namespace Server.Mobiles
public override NpcGuild NpcGuild{ get{ return NpcGuild.MagesGuild; } }
private DateTime m_NextShush;
public static readonly TimeSpan ShushDelay = TimeSpan.FromMinutes( 1 );
[Constructable]
public Scribe() : base( "the scribe" )
{
@ -35,6 +38,27 @@ namespace Server.Mobiles
AddItem( new Server.Items.Robe( Utility.RandomNeutralHue() ) );
}
public override bool HandlesOnSpeech( Mobile from )
{
return from.Player;
}
public override void OnSpeech( SpeechEventArgs e )
{
base.OnSpeech( e );
if ( !e.Handled && m_NextShush <= DateTime.Now && InLOS( e.Mobile ) )
{
Direction = GetDirectionTo( e.Mobile );
PlaySound( Female ? 0x32F : 0x441 );
PublicOverheadMessage( Network.MessageType.Regular, 0x3B2, 1073990 ); // Shhhh!
m_NextShush = DateTime.Now + ShushDelay;
e.Handled = true;
}
}
public Scribe( Serial serial ) : base( serial )
{
}

View file

@ -24,12 +24,12 @@ namespace Server.Mobiles
public override void InitOutfit()
{
AddItem( new FancyShirt( RandomBrightHue() ) );
AddItem( new FancyShirt( Utility.RandomBrightHue() ) );
AddItem( new Shoes( GetShoeHue() ) );
AddItem( new LongPants( GetRandomHue() ) );
if ( Utility.RandomBool() )
AddItem( new Cloak( RandomBrightHue() ) );
AddItem( new Cloak( Utility.RandomBrightHue() ) );
switch ( Utility.Random( 2 ) )
{

View file

@ -193,7 +193,7 @@ namespace Server.Mobiles
{
base.InitOutfit();
AddItem( new HalfApron( RandomBrightHue() ) );
AddItem( new HalfApron( Utility.RandomBrightHue() ) );
Container pack = this.Backpack;

View file

@ -6,11 +6,13 @@ namespace Server.Mobiles
{
public abstract class SBInfo
{
public static readonly List<SBInfo> Empty = new List<SBInfo>();
public SBInfo()
{
}
public abstract IShopSellInfo SellInfo { get; }
public abstract List<GenericBuyInfo> BuyInfo { get; }
public abstract List<GenericBuyInfo> BuyInfo { get; }
}
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class SBNinja : SBInfo
{
private List<GenericBuyInfo> m_BuyInfo = new InternalBuyInfo();
private IShopSellInfo m_SellInfo = new InternalSellInfo();
public SBNinja()
{
}
public override IShopSellInfo SellInfo { get { return m_SellInfo; } }
public override List<GenericBuyInfo> BuyInfo { get { return m_BuyInfo; } }
public class InternalBuyInfo : List<GenericBuyInfo>
{
public InternalBuyInfo()
{
Add( new GenericBuyInfo( typeof( BookOfNinjitsu ), 335, 20, 0x23A0, 0 ) );
}
}
public class InternalSellInfo : GenericSellInfo
{
public InternalSellInfo()
{
}
}
}
}

View file

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using Server.Items;
namespace Server.Mobiles
{
public class SBSamurai : SBInfo
{
private List<GenericBuyInfo> m_BuyInfo = new InternalBuyInfo();
private IShopSellInfo m_SellInfo = new InternalSellInfo();
public SBSamurai()
{
}
public override IShopSellInfo SellInfo { get { return m_SellInfo; } }
public override List<GenericBuyInfo> BuyInfo { get { return m_BuyInfo; } }
public class InternalBuyInfo : List<GenericBuyInfo>
{
public InternalBuyInfo()
{
Add( new GenericBuyInfo( typeof( BookOfBushido ), 280, 20, 0x238C, 0 ) );
}
}
public class InternalSellInfo : GenericSellInfo
{
public InternalSellInfo()
{
}
}
}
}