This commit is contained in:
mark 2009-09-06 02:06:07 +00:00
parent 4ee6ca5951
commit 06e5c8b732
70 changed files with 2798 additions and 286 deletions

View file

@ -1069,8 +1069,16 @@ namespace Server.Mobiles
{
get
{
if ( m_HitsMax >= 0 )
return m_HitsMax + GetStatOffset( StatType.Str );
if ( m_HitsMax > 0 ) {
int value = m_HitsMax + GetStatOffset( StatType.Str );
if( value < 1 )
value = 1;
else if( value > 65000 )
value = 65000;
return value;
}
return Str;
}
@ -1088,8 +1096,16 @@ namespace Server.Mobiles
{
get
{
if ( m_StamMax >= 0 )
return m_StamMax + GetStatOffset( StatType.Dex );
if ( m_StamMax > 0 ) {
int value = m_StamMax + GetStatOffset( StatType.Dex );
if( value < 1 )
value = 1;
else if( value > 65000 )
value = 65000;
return value;
}
return Dex;
}
@ -1107,8 +1123,16 @@ namespace Server.Mobiles
{
get
{
if ( m_ManaMax >= 0 )
return m_ManaMax + GetStatOffset( StatType.Int );
if ( m_ManaMax > 0 ) {
int value = m_ManaMax + GetStatOffset( StatType.Int );
if( value < 1 )
value = 1;
else if( value > 65000 )
value = 65000;
return value;
}
return Int;
}

View file

@ -192,17 +192,17 @@ namespace Server.Engines.Craft
if ( context != null )
resIndex = ( m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex );
bool cropScroll = ( m_CraftItem.Ressources.Count > 1 )
&& m_CraftItem.Ressources.GetAt( m_CraftItem.Ressources.Count - 1 ).ItemType == typeofBlankScroll
bool cropScroll = ( m_CraftItem.Resources.Count > 1 )
&& m_CraftItem.Resources.GetAt( m_CraftItem.Resources.Count - 1 ).ItemType == typeofBlankScroll
&& typeofSpellScroll.IsAssignableFrom( m_CraftItem.ItemType );
for ( int i = 0; i < m_CraftItem.Ressources.Count - (cropScroll ? 1 : 0) && i < 4; i++ )
for ( int i = 0; i < m_CraftItem.Resources.Count - (cropScroll ? 1 : 0) && i < 4; i++ )
{
Type type;
string nameString;
int nameNumber;
CraftRes craftResource = m_CraftItem.Ressources.GetAt( i );
CraftRes craftResource = m_CraftItem.Resources.GetAt( i );
type = craftResource.ItemType;
nameString = craftResource.NameString;
@ -240,8 +240,8 @@ namespace Server.Engines.Craft
if ( m_CraftItem.NameNumber == 1041267 ) // runebook
{
AddHtmlLocalized( 170, 219 + (m_CraftItem.Ressources.Count * 20), 310, 18, 1044447, LabelColor, false, false );
AddLabel( 430, 219 + (m_CraftItem.Ressources.Count * 20), LabelHue, "1" );
AddHtmlLocalized( 170, 219 + (m_CraftItem.Resources.Count * 20), 310, 18, 1044447, LabelColor, false, false );
AddLabel( 430, 219 + (m_CraftItem.Resources.Count * 20), LabelHue, "1" );
}
if ( cropScroll )

View file

@ -226,7 +226,7 @@ namespace Server.Engines.Craft
get { return m_NameNumber; }
}
public CraftResCol Ressources
public CraftResCol Resources
{
get { return m_arCraftRes; }
}

View file

@ -36,7 +36,7 @@ namespace Server.Engines.Craft
CraftItem craftItem = craftSystem.CraftItems.SearchFor( item.GetType() );
if ( craftItem == null || craftItem.Ressources.Count == 0 )
if ( craftItem == null || craftItem.Resources.Count == 0 )
return EnhanceResult.BadItem;
bool allRequiredSkills = false;

View file

@ -336,7 +336,7 @@ namespace Server.Engines.Craft
toDelete = true;
}
}
else if ( (targeted is BaseClothing) )
else if ( targeted is BaseClothing )
{
BaseClothing clothing = (BaseClothing)targeted;
SkillName skill = m_CraftSystem.MainSkill;
@ -358,8 +358,8 @@ namespace Server.Engines.Craft
toWeaken = 3;
}
if (m_CraftSystem.CraftItems.SearchForSubclass(clothing.GetType()) == null && !IsSpecialClothing(clothing) && !((targeted is TribalMask) || (targeted is HornedTribalMask) || targeted.GetType().IsSubclassOf(typeof(HornedTribalMask)) || targeted.GetType().IsSubclassOf(typeof(TribalMask))))
{
if (m_CraftSystem.CraftItems.SearchForSubclass(clothing.GetType()) == null && !IsSpecialClothing(clothing) && !((targeted is TribalMask) || (targeted is HornedTribalMask)) )
{
number = (usingDeed) ? 1061136 : 1044277; // That item cannot be repaired. // You cannot repair that item with this type of repair contract.
}
else if ( !clothing.IsChildOf( from.Backpack ) )

View file

@ -5,6 +5,13 @@ using Server.Items;
namespace Server.Engines.Craft
{
public enum SmeltResult
{
Success,
Invalid,
NoSkill
}
public class Resmelt
{
public Resmelt()
@ -37,27 +44,44 @@ namespace Server.Engines.Craft
m_Tool = tool;
}
private bool Resmelt( Mobile from, Item item, CraftResource resource )
private SmeltResult Resmelt( Mobile from, Item item, CraftResource resource )
{
try
{
if ( CraftResources.GetType( resource ) != CraftResourceType.Metal )
return false;
return SmeltResult.Invalid;
CraftResourceInfo info = CraftResources.GetInfo( resource );
if ( info == null || info.ResourceTypes.Length == 0 )
return false;
return SmeltResult.Invalid;
CraftItem craftItem = m_CraftSystem.CraftItems.SearchFor( item.GetType() );
if ( craftItem == null || craftItem.Ressources.Count == 0 )
return false;
if ( craftItem == null || craftItem.Resources.Count == 0 )
return SmeltResult.Invalid;
CraftRes craftResource = craftItem.Ressources.GetAt( 0 );
CraftRes craftResource = craftItem.Resources.GetAt( 0 );
if ( craftResource.Amount < 2 )
return false; // Not enough metal to resmelt
return SmeltResult.Invalid; // Not enough metal to resmelt
double difficulty = 0.0;
switch ( resource )
{
case CraftResource.DullCopper: difficulty = 65.0; break;
case CraftResource.ShadowIron: difficulty = 70.0; break;
case CraftResource.Copper: difficulty = 75.0; break;
case CraftResource.Bronze: difficulty = 80.0; break;
case CraftResource.Gold: difficulty = 85.0; break;
case CraftResource.Agapite: difficulty = 90.0; break;
case CraftResource.Verite: difficulty = 95.0; break;
case CraftResource.Valorite: difficulty = 99.0; break;
}
if ( difficulty > from.Skills[ SkillName.Mining ].Value )
return SmeltResult.NoSkill;
Type resourceType = info.ResourceTypes[0];
Item ingot = (Item)Activator.CreateInstance( resourceType );
@ -72,13 +96,13 @@ namespace Server.Engines.Craft
from.PlaySound( 0x2A );
from.PlaySound( 0x240 );
return true;
return SmeltResult.Success;
}
catch
{
}
return false;
return SmeltResult.Invalid;
}
protected override void OnTarget( Mobile from, object targeted )
@ -91,29 +115,35 @@ namespace Server.Engines.Craft
}
else
{
bool success = false;
SmeltResult result = SmeltResult.Invalid;
bool isStoreBought = false;
int message;
if ( targeted is BaseArmor )
{
success = Resmelt( from, (BaseArmor)targeted, ((BaseArmor)targeted).Resource );
result = Resmelt( from, (BaseArmor)targeted, ((BaseArmor)targeted).Resource );
isStoreBought = !((BaseArmor)targeted).PlayerConstructed;
}
else if ( targeted is BaseWeapon )
{
success = Resmelt( from, (BaseWeapon)targeted, ((BaseWeapon)targeted).Resource );
result = Resmelt( from, (BaseWeapon)targeted, ((BaseWeapon)targeted).Resource );
isStoreBought = !((BaseWeapon)targeted).PlayerConstructed;
}
else if ( targeted is DragonBardingDeed )
{
success = Resmelt( from, (DragonBardingDeed)targeted, ((DragonBardingDeed)targeted).Resource );
result = Resmelt( from, (DragonBardingDeed)targeted, ((DragonBardingDeed)targeted).Resource );
isStoreBought = false;
}
if ( success )
from.SendGump( new CraftGump( from, m_CraftSystem, m_Tool, isStoreBought ? 500418 : 1044270 ) ); // You melt the item down into ingots.
else
from.SendGump( new CraftGump( from, m_CraftSystem, m_Tool, 1044272 ) ); // You can't melt that down into ingots.
switch ( result )
{
default:
case SmeltResult.Invalid: message = 1044272; break; // You can't melt that down into ingots.
case SmeltResult.NoSkill: message = 1044269; break; // You have no idea how to work this metal.
case SmeltResult.Success: message = isStoreBought ? 500418 : 1044270; break; // You melt the item down into ingots.
}
from.SendGump( new CraftGump( from, m_CraftSystem, m_Tool, message ) );
}
}
}

View file

@ -0,0 +1,87 @@
using System;
using Server;
using Server.Items;
using Server.Engines.Doom;
namespace Server.Mobiles
{
[CorpseName( "a dark guardians' corpse" )]
public class DarkGuardian : BaseCreature
{
[Constructable]
public DarkGuardian() : base( AIType.AI_Mage, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
Name = "a dark guardian";
Body = 78;
BaseSoundID = 0x3E9;
SetStr( 125, 150 );
SetDex( 100, 120 );
SetInt( 200, 235 );
SetHits( 150, 180 );
SetDamage( 43, 48 );
SetDamageType( ResistanceType.Physical, 10 );
SetDamageType( ResistanceType.Cold, 40 );
SetDamageType( ResistanceType.Energy, 50 );
SetResistance( ResistanceType.Physical, 40, 50 );
SetResistance( ResistanceType.Fire, 20, 45 );
SetResistance( ResistanceType.Cold, 50, 60 );
SetResistance( ResistanceType.Poison, 20, 45 );
SetResistance( ResistanceType.Energy, 30, 40 );
SetSkill( SkillName.EvalInt, 40.1, 50);
SetSkill( SkillName.Magery, 50.1, 60.0 );
SetSkill( SkillName.Meditation, 85.1, 95.0 );
SetSkill( SkillName.MagicResist, 50.1, 70.0 );
SetSkill( SkillName.Tactics, 50.1, 70.0 );
Fame = 5000;
Karma = -5000;
VirtualArmor = 50;
PackNecroReg( 15, 25 );
PackItem( new DaemonBone( 30 ) );
}
public DarkGuardian( Serial serial ) : base( serial )
{
}
public override void GenerateLoot()
{
AddLoot( LootPack.Rich );
AddLoot( LootPack.MedScrolls, 2 );
}
public override OppositionGroup OppositionGroup
{
get{ return OppositionGroup.FeyAndUndead; }
}
public override int TreasureMapLevel{ get{ return 2; } }
public override bool BleedImmune{ get{ return true; } }
public override Poison PoisonImmune{ get{ return Poison.Lethal; } }
public override bool Unprovokable { get { return true; } }
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
if ( Region is GuardianRoomRegion )
Delete();
}
}
}

View file

@ -0,0 +1,599 @@
using System;
using System.Collections.Generic;
using Server;
using Server.Items;
using Server.Mobiles;
using Server.Regions;
using Server.Commands;
namespace Server.Engines.Doom
{
public class GuardianRoomRegion : BaseRegion
{
private static GuardianRoomRegion m_Region;
public static void Initialize()
{
CommandSystem.Register( "GenGuardianRoom", AccessLevel.Administrator, new CommandEventHandler( GenRoom_OnCommand ) );
}
[Usage( "GenGuardianRoom" )]
[Description( "Generates guardian room in doom." )]
public static void GenRoom_OnCommand( CommandEventArgs e )
{
e.Mobile.SendMessage( "Generating room, please wait." );
int count = 0;
// doors
MetalDoor north = FindItem( new GuardianRoomDoor( DoorFacing.NorthCCW ), 0, 355, 14, -1, Map.Malas, ref count ) as MetalDoor;
MetalDoor south = FindItem( new GuardianRoomDoor( DoorFacing.SouthCW ), 0, 355, 15, -1, Map.Malas, ref count ) as MetalDoor;
if ( north != null && south != null )
{
north.Link = south;
south.Link = north;
}
// pentagram center
FindItem( new Static( 0xFEA ), 0x835, 365, 15, -1, Map.Malas, ref count );
// ghost teleporters
Teleporter tele;
tele = FindItem( new GhostTeleporter(), 0x835, 354, 14, -1, Map.Malas, ref count ) as Teleporter;
if ( tele != null )
{
tele.PointDest = new Point3D( 349, 176, 14 );
tele.MapDest = Map.Malas;
}
tele = FindItem( new GhostTeleporter(), 0x835, 354, 15, -1, Map.Malas, ref count ) as Teleporter;
if ( tele != null )
{
tele.PointDest = new Point3D( 349, 176, 14 );
tele.MapDest = Map.Malas;
}
// treasure chest spawner
Spawner spawner = new Spawner( 3, 1, 5, 0, 9, "GuardianTreasureChest" );
spawner = FindItem( spawner, 0, 365, 15, 0, Map.Malas, ref count ) as Spawner;
if ( spawner != null )
{
spawner.Movable = false;
spawner.Respawn();
}
if ( count > 0 )
e.Mobile.SendMessage( "Room generating complete. {0} items were generated.", count );
else
e.Mobile.SendMessage( "Room generating complete. No changes neccessary." );
}
public static Item FindItem( Item item, int hue, int x, int y, int z, Map map, ref int count )
{
Point3D p = new Point3D( x, y, z );
Type type = item.GetType();
foreach ( Item i in map.GetItemsInRange( p, 0 ) )
{
if ( i.GetType() == type && i.ItemID == item.ItemID && i.Hue == hue )
{
item.Delete();
return i;
}
}
count++;
item.MoveToWorld( p, map );
if ( hue > 0 )
item.Hue = hue;
return item;
}
private BaseDoor m_Door;
private List<Mobile> m_Dead;
private Timer m_Timer;
private int m_LightLevel;
public List<Mobile> Dead
{
get { return m_Dead; }
}
public bool Active
{
get { return m_Timer != null && m_Timer.Running; }
}
private static Rectangle2D[] m_Bounds = new Rectangle2D[]
{
new Rectangle2D( new Point2D( 356, 5 ), new Point2D( 375, 25 ) )
};
public GuardianRoomRegion( BaseDoor door ) : base( "NorthDoomPoisonRoom", Map.Malas, 51, m_Bounds )
{
m_Door = door;
m_Dead = new List<Mobile>();
m_LightLevel = LightCycle.DungeonLevel;
m_Guardians = new List<Mobile>();
ExcludeFromParentSpawns = true;
}
public override void OnEnter( Mobile m )
{
if ( !Active && IsTrappable( m, true ) )
m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( Utility.RandomMinMax( 5, 35 ) ), new TimerCallback( StartTrap ) );
}
public override void OnDeath( Mobile m )
{
base.OnDeath( m );
if ( m.IsDeadBondedPet || ( m.Player && m.AccessLevel == AccessLevel.Player ) )
m_Dead.Add( m );
if ( m is DarkGuardian )
m_Guardians.Remove( m );
if ( m_Guardians.Count == 0 )
Timer.DelayCall( TimeSpan.FromSeconds( 5 ), new TimerCallback( StopTrap ) );
List<Mobile> list = GetPoisonableMobiles();
list.Remove( m );
if ( list.Count == 0 )
Timer.DelayCall( TimeSpan.FromSeconds( 5 ), new TimerCallback( StopTrap ) );
}
public override void AlterLightLevel( Mobile m, ref int global, ref int personal )
{
global = m_LightLevel;
}
public virtual void PoisonMobiles( Poison poison, int ticks )
{
List<Mobile> list = GetPoisonableMobiles();
int number = 0;
int hue = 0x485;
if ( ticks % 12 == 0 ) // every 60 seconds
{
switch ( poison.Level )
{
// It is becoming more difficult for you to breathe as the poisons in the room become more concentrated.
case 1: number = 1050001; break;
// You begin to panic as the poison clouds thicken.
case 2: number = 1050003; break;
// Terror grips your spirit as you realize you may never leave this room alive.
case 3: number = 1050056; break;
case 4:
if ( ticks < 50 )
{
number = 1050057; // The end is near. You feel hopeless and desolate. The poison is beginning to stiffen your muscles.
}
else
{
hue = 0x23F3;
number = 1062091; // The poison is becoming too much for you to bear. You fear that you may die at any moment.
}
break;
}
}
foreach ( Mobile m in list )
{
if ( m.Player && number > 0 )
m.SendLocalizedMessage( number, null, hue );
if ( ( m.Poison == null || m.Poison.Level < poison.Level ) )
m.ApplyPoison( null, poison );
}
}
public virtual void HurtMobiles( int level )
{
foreach ( Mobile m in GetPoisonableMobiles() )
{
if ( m.Player )
{
m.Say( 1062092 ); // Your body reacts violently from the pain.
m.Animate( 32, 5, 1, true, false, 0 );
}
m.Damage( Utility.Random( 15, 20 ) );
if ( level >= 10 )
m.Kill();
}
}
public virtual List<Mobile> GetPoisonableMobiles()
{
List<Mobile> list = new List<Mobile>();
foreach ( Mobile m in GetMobiles() )
{
if ( IsTrappable( m, false ) )
list.Add( m );
}
return list;
}
public virtual bool IsTrappable( Mobile m, bool trapStart )
{
if ( m.Alive )
{
if ( m.Player && m.AccessLevel == AccessLevel.Player )
return true;
BaseCreature bc = m as BaseCreature;
if ( bc != null )
{
Mobile master = null;
if ( bc.Controlled && bc.ControlMaster != null )
master = bc.ControlMaster;
else if ( !trapStart && bc.Summoned && bc.SummonMaster != null )
master = bc.SummonMaster;
if ( master != null )
return master.Player && master.AccessLevel == AccessLevel.Player;
}
}
return false;
}
public virtual bool CanStart( List<Mobile> list )
{
foreach ( Mobile m in list )
if ( IsTrappable( m, true ) )
return true;
return false;
}
public virtual void RestartTrap()
{
if ( !Active )
StartTrap();
}
public virtual void StartTrap()
{
List<Mobile> list = GetPoisonableMobiles();
if ( !CanStart( list ) )
return;
m_Timer = new PoisonRoomTimer( this );
m_Timer.Start();
if ( m_Door != null )
{
m_Door.Locked = true;
m_Door.Open = false;
if ( m_Door.Link != null )
{
m_Door.Link.Locked = true;
m_Door.Link.Open = false;
Effects.PlaySound( m_Door.Link.Location, Map, 0x1FF );
}
Effects.PlaySound( m_Door.Location, Map, 0x1FF );
}
foreach ( Mobile m in list )
m.SendLocalizedMessage( 1050000, null, 0x41 ); // The locks on the door click loudly and you begin to hear a faint hissing near the walls.
for ( int i = m_Dead.Count - 1; i >= 0; i-- )
if ( m_Dead[ i ].Alive )
m_Dead.RemoveAt( i );
SpawnGuardians( list.Count * 2 );
}
public virtual void StopTrap()
{
Timer.DelayCall( TimeSpan.FromSeconds( Utility.RandomMinMax( 30, 60 ) ), new TimerCallback( RestartTrap ) );
if ( m_Door != null )
{
m_Door.Locked = false;
if ( m_Door.Link != null )
{
m_Door.Link.Locked = false;
Effects.PlaySound( m_Door.Link.Location, Map, 0x1FF );
}
Effects.PlaySound( m_Door.Location, Map, 0x1FF );
}
if ( m_Timer != null && m_Timer.Running )
m_Timer.Stop();
foreach ( Mobile m in GetPlayers() )
m.SendLocalizedMessage( 1050055, null, 0x41 ); // You hear the doors unlocking and the hissing stops.
ClearGuardians();
}
#region Spawns
private List<Mobile> m_Guardians;
public void SpawnGuardians( int amount )
{
for ( int i = 0; i < amount; ++i )
{
DarkGuardian guardian = new DarkGuardian();
switch ( Utility.Random( 4 ) )
{
case 0: guardian.MoveToWorld( new Point3D( 364, 15, -1 ), Map.Malas ); break;
case 1: guardian.MoveToWorld( new Point3D( 366, 15, -1 ), Map.Malas ); break;
case 2: guardian.MoveToWorld( new Point3D( 365, 14, -1 ), Map.Malas ); break;
case 3: guardian.MoveToWorld( new Point3D( 365, 16, -1 ), Map.Malas ); break;
}
m_Guardians.Add( guardian );
}
}
public void ClearGuardians()
{
foreach ( Mobile m in m_Guardians )
{
if ( m.Alive && !m.Deleted )
{
Effects.SendLocationParticles( EffectItem.Create( m.Location, m.Map, EffectItem.DefaultDuration ), 0x3728, 8, 20, 5042 );
Effects.PlaySound( m, m.Map, 0x201 );
m.Delete();
}
}
m_Guardians.Clear();
}
#endregion
#region Effects
private static Point3D[] m_GasLocations = new Point3D[]
{
// west
new Point3D( 356, 7, -1 ), new Point3D( 356, 13, -1 ),
new Point3D( 356, 16, -1 ), new Point3D( 356, 22, -1 ),
// north
new Point3D( 358, 6, -1 ), new Point3D( 363, 6, -1 ),
new Point3D( 368, 6, -1 ), new Point3D( 373, 6, -1 )
};
public virtual void DoGasEffect()
{
for ( int i = Utility.RandomMinMax( 2, 4 ); i > 0; i-- )
{
int pos = Utility.Random( m_GasLocations.Length );
int itemID;
if ( pos <= 3 )
itemID = 0x1145;
else
itemID = 0x113A;
Effects.SendLocationParticles( EffectItem.Create( m_GasLocations[ pos ], Map, EffectItem.DefaultDuration ), itemID, 1, 100, 0, 4, 0x139D, 0 );
}
}
private static int[] m_PoisonEffects = new int[]
{
0x36B0, 0x36BD, 0x36CB
};
public virtual void DoPoisonEffect( int level )
{
int hue = 0;
switch ( level )
{
default:
case 0: hue = 0xA6; break;
case 1: hue = 0xAA; break;
case 2: hue = 0xAC; break;
case 3: hue = 0xA8; break;
case 4: hue = 0xA4; break;
}
for ( int i = Utility.RandomMinMax( 5, 7 ); i > 0; i-- )
{
Point3D p = RandomSpawnLocation( 0, true, true, Point3D.Zero, 0 );
if ( p != Point3D.Zero )
{
IEntity e = EffectItem.Create( p, Map, EffectItem.DefaultDuration );
int itemID = Utility.RandomList( m_PoisonEffects );
int duration = Utility.RandomMinMax( 150, 200 );
Effects.SendLocationParticles( e, itemID, 1, duration, hue, 0, 0x139D, 0 );
}
}
}
#endregion
public class PoisonRoomTimer : Timer
{
private GuardianRoomRegion m_Room;
private int m_Count;
public PoisonRoomTimer( GuardianRoomRegion room ) : base( TimeSpan.FromSeconds( 1 ), TimeSpan.FromSeconds( 1 ) )
{
m_Room = room;
m_Count = 0;
}
public int CurrentPoisonLevel()
{
int poisonLevel = 1 + m_Count / 20;
if ( poisonLevel > 4 )
poisonLevel = 4;
return poisonLevel;
}
protected override void OnTick()
{
m_Count++;
if ( m_Count % 5 == 0 && m_Room.Active )
{
int level = CurrentPoisonLevel();
m_Room.PoisonMobiles( Poison.GetPoison( level ), m_Count / 5 );
}
if ( m_Count % 8 == 0 && m_Room.Active )
{
m_Room.DoPoisonEffect( CurrentPoisonLevel() );
m_Room.DoGasEffect();
}
if ( m_Count >= 720 && m_Count % 10 == 0 && m_Room.Active )
m_Room.HurtMobiles( ( m_Count - 720 ) / 10 );
}
}
public class GhostTeleporter : Teleporter
{
private static BaseRegion m_GhostRegion;
private static Rectangle2D[] m_GhostRegionBounds = new Rectangle2D[]
{
new Rectangle2D( new Point2D( 345, 180 ), new Point2D( 352, 184 ) ),
new Rectangle2D( new Point2D( 342, 172 ), new Point2D( 344, 181 ) ),
new Rectangle2D( new Point2D( 345, 169 ), new Point2D( 352, 172 ) )
};
[Constructable]
public GhostTeleporter() : base()
{
Name = "GhostTeleporter";
if ( m_GhostRegion == null )
{
m_GhostRegion = new BaseRegion( "DoomGhostTeleportRegion", Map.Malas, 55, m_GhostRegionBounds );
m_GhostRegion.Register();
}
}
public GhostTeleporter( Serial serial ) : base( serial )
{
}
public override bool OnMoveOver( Mobile m )
{
if ( !DiedInside( m ) )
return true;
return base.OnMoveOver( m );
}
public bool DiedInside( Mobile m )
{
bool valid = false;
if ( m_Region != null )
valid = m_Region.Dead.Remove( m );
return valid && !m.Alive;
}
public override void DoTeleport( Mobile m )
{
if ( m.Corpse != null && !m.Corpse.Deleted )
{
Point3D location = Point3D.Zero;
if ( m_GhostRegion != null )
location = m_GhostRegion.RandomSpawnLocation( 0, true, false, Point3D.Zero, 0 );
if ( location == Point3D.Zero )
location = new Point3D( 349, 176, 14 );
m.Corpse.MoveToWorld( location, Map.Malas );
m.MoveToWorld( location, Map.Malas );
}
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
if ( m_GhostRegion == null )
{
m_GhostRegion = new BaseRegion( "DoomGhostTeleportRegion", Map.Malas, 55, m_GhostRegionBounds );
m_GhostRegion.Register();
}
}
}
public class GuardianRoomDoor : MetalDoor
{
public GuardianRoomDoor( DoorFacing facing ) : base( facing )
{
if ( m_Region == null )
{
m_Region = new GuardianRoomRegion( this );
m_Region.Register();
}
}
public GuardianRoomDoor( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
Locked = false;
if ( m_Region == null )
{
m_Region = new GuardianRoomRegion( this );
m_Region.Register();
}
}
}
}
}

View file

@ -0,0 +1,179 @@
using System;
using Server;
using Server.Engines.Doom;
namespace Server.Items
{
public class GuardianTreasureChest : LockableContainer
{
private const int m_Level = 6;
public override bool Decays { get { return true; } }
public override int DefaultGumpID { get { return 0x42; } }
public override int DefaultDropSound { get { return 0x42; } }
public override Rectangle2D Bounds
{
get { return new Rectangle2D( 18, 105, 144, 73 ); }
}
private Timer m_DecayTimer;
[Constructable]
public GuardianTreasureChest() : base( 0xE41 )
{
SetChestAppearance();
Movable = false;
/* TrapType = TrapType.ExplosionTrap;
TrapPower = m_Level * Utility.Random( 20, 35 );*/
Locked = true;
RequiredSkill = 99;
LockLevel = RequiredSkill - Utility.Random( 1, 10 );
MaxLockLevel = RequiredSkill + 21;
// According to OSI, loot in level 4 chest is:
// Gold 500 - 900
// Reagents
// Scrolls
// Blank scrolls
// Potions
// Gems
// Magic Wand
// Magic weapon
// Magic armour
// Magic clothing (not implemented)
// Magic jewelry (not implemented)
// Crystal ball (not implemented)
// Gold
DropItem( new Gold( Utility.Random( 300, 325 ) ) );
// Reagents
for ( int i = Utility.Random( 1, m_Level ); i > 1; i-- )
{
Item ReagentLoot = Loot.RandomReagent();
ReagentLoot.Amount = 12;
DropItem( ReagentLoot );
}
// Scrolls
for ( int i = Utility.Random( 1, m_Level ); i > 1; i-- )
{
Item ScrollLoot = Loot.RandomScroll( 0, 47, SpellbookType.Regular );
ScrollLoot.Amount = 16;
DropItem( ScrollLoot );
}
// Drop blank scrolls
DropItem( new BlankScroll( Utility.Random( 1, m_Level ) ) );
// Potions
for ( int i = Utility.Random( 1, m_Level ); i > 1; i-- )
{
Item PotionLoot = Loot.RandomPotion();
DropItem( PotionLoot );
}
// Gems
for ( int i = Utility.Random( 1, m_Level ); i > 1; i-- )
{
Item GemLoot = Loot.RandomGem();
GemLoot.Amount = 15;
DropItem( GemLoot );
}
// Magic Wand
for ( int i = Utility.Random( 1, m_Level ); i > 1; i-- )
DropItem( Loot.RandomWand() );
// Equipment
for ( int i = Utility.Random( 1, m_Level ); i > 1; i-- )
{
Item item = Loot.RandomArmorOrShieldOrWeapon();
if ( item is BaseWeapon )
{
BaseWeapon weapon = (BaseWeapon) item;
weapon.DamageLevel = (WeaponDamageLevel) Utility.Random( m_Level );
weapon.AccuracyLevel = (WeaponAccuracyLevel) Utility.Random( m_Level );
weapon.DurabilityLevel = (WeaponDurabilityLevel) Utility.Random( m_Level );
weapon.Quality = WeaponQuality.Regular;
}
else if ( item is BaseArmor )
{
BaseArmor armor = (BaseArmor) item;
armor.ProtectionLevel = (ArmorProtectionLevel) Utility.Random( m_Level );
armor.Durability = (ArmorDurabilityLevel) Utility.Random( m_Level );
armor.Quality = ArmorQuality.Regular;
}
DropItem( item );
}
// Clothing
for ( int i = Utility.Random( 1, 2 ); i > 1; i-- )
DropItem( Loot.RandomClothing() );
// Jewelry
for ( int i = Utility.Random( 1, 2 ); i > 1; i-- )
DropItem( Loot.RandomJewelry() );
// Crystal ball (not implemented)
m_DecayTimer = Timer.DelayCall( TimeSpan.FromMinutes( Utility.RandomMinMax( 1, 5 ) ), new TimerCallback( Delete ) );
}
private void SetChestAppearance()
{
bool facing = Utility.RandomBool();
switch ( Utility.RandomList( 0, 1, 2 ) )
{
case 0:// Wooden Chest
ItemID = ( facing ? 0xE42 : 0xE43 );
GumpID = 0x49;
break;
case 1:// Metal Chest
ItemID = ( facing ? 0x9AB : 0xE7C );
GumpID = 0x4A;
break;
case 2:// Metal Golden Chest
ItemID = ( facing ? 0xE40 : 0xE41 );
GumpID = 0x42;
break;
}
}
public override void OnAfterDelete()
{
if ( m_DecayTimer != null || m_DecayTimer.Running )
m_DecayTimer.Stop();
m_DecayTimer = null;
}
public GuardianTreasureChest( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
m_DecayTimer = Timer.DelayCall( TimeSpan.FromMinutes( Utility.RandomMinMax( 1, 5 ) ), new TimerCallback( Delete ) );
}
}
}

View file

@ -0,0 +1,230 @@
using System;
using System.Collections.Generic;
using Server;
using Server.Mobiles;
using Server.Regions;
using Server.Spells.Fourth;
using Server.Spells.Sixth;
using Server.Spells.Seventh;
using Server.Spells.Chivalry;
namespace Server.Misc
{
public class PoisonRoom
{
public virtual int GasEffects { get { return 3; } }
public virtual double TimePerPoisonCast { get { return 3; } }
public virtual int TicksPerPoisonLevel { get { return 15; } }
public virtual Poison MinPoisonLevel { get { return Poison.Lesser; } }
public virtual Poison MaxPoisonLevel { get { return Poison.Lethal; } }
public virtual int GasEffectHeight { get { return 0; } }
public virtual bool HasPoisonSoundEffect { get { return true; } }
protected PoisonRoomRegion m_Region;
protected PoisonRoomTimer m_Timer;
protected int m_EffectHue = 1166;
protected int m_EffectId = 4518;
protected int m_EffectDuration = 16;
protected List<Mobile> m_Dead;
public List<Mobile> Dead
{
get { return m_Dead; }
}
public PoisonRoom( string name, Map map, int priority, Rectangle2D[] rect, int LightLevel )
{
m_Region = new PoisonRoomRegion( this, name, map, priority, rect, LightLevel );
m_Region.Register();
m_Dead = new List<Mobile>();
}
public virtual void OnEnter( Mobile m )
{
if ( m.AccessLevel == AccessLevel.Player && m_Timer == null )
StartGas();
}
public virtual void OnPoison( Poison poison, int tick )
{
}
public virtual void StartGas()
{
m_Timer = new PoisonRoomTimer( this );
m_Timer.Start();
}
public virtual void StopGas()
{
if ( m_Timer != null )
m_Timer.Stop();
m_Timer = null;
}
public virtual void OnExit( Mobile m )
{
if ( GetPoisonableMobiles( m ).Count == 0 )
{
StopGas();
return;
}
}
public virtual void OnDeath( Mobile m )
{
m_Dead.Add( m );
}
public virtual void DoGasEffect()
{
for ( int i = 0; i < this.GasEffects; ++i )
RandomGasEffect();
}
public virtual void RandomGasEffect()
{
Point3D location = m_Region.RandomSpawnLocation( GasEffectHeight, true, true, Point3D.Zero, 0 );
if ( location != Point3D.Zero )
{
Effects.SendLocationEffect( location, m_Region.Map, 4518, 16, 1, 1166, 0 );
if ( HasPoisonSoundEffect )
Effects.PlaySound( location, m_Region.Map, 0x231 );
}
}
public virtual void PoisonPlayers( Poison poison )
{
List<Mobile> list = GetPoisonableMobiles( null );
foreach ( Mobile m in list )
{
if ( ( m.Poison == null || m.Poison.Level < poison.Level ) )
m.ApplyPoison( null, poison );
}
}
public int CurrentPoisonLevel()
{
if ( m_Timer != null )
return m_Timer.CurrentPoisonLevel();
return 0;
}
protected virtual bool IsPoisonable( Mobile m )
{
if ( m.AccessLevel == AccessLevel.Player && m.CheckAlive() && ( m.Player || ( m is BaseCreature && ((BaseCreature)m).Controlled ) ) )
return true;
return false;
}
public virtual List<Mobile> GetPoisonableMobiles( Mobile toexclude )
{
List<Mobile> list = new List<Mobile>();
List<Mobile> templist = m_Region.GetMobiles();
foreach ( Mobile m in templist )
{
if ( IsPoisonable( m ) )
list.Add( m );
}
if ( toexclude != null )
list.Remove( toexclude );
return list;
}
public class PoisonRoomTimer : Timer
{
private PoisonRoom m_Room;
private int m_Count = 0;
public PoisonRoomTimer( PoisonRoom room ) : base( TimeSpan.FromSeconds( 0 ), TimeSpan.FromSeconds( room.TimePerPoisonCast ) )
{
m_Room = room;
}
public int CurrentPoisonLevel()
{
int poisonLevel = m_Room.MinPoisonLevel.Level + m_Count / m_Room.TicksPerPoisonLevel;
if ( poisonLevel > m_Room.MaxPoisonLevel.Level )
poisonLevel = m_Room.MaxPoisonLevel.Level;
return poisonLevel;
}
protected override void OnTick()
{
m_Count++;
int poisonLevel = CurrentPoisonLevel();
m_Room.OnPoison( Poison.GetPoison( poisonLevel ), m_Count );
m_Room.PoisonPlayers( Poison.GetPoison( poisonLevel ) );
m_Room.DoGasEffect();
}
}
public class PoisonRoomRegion : BaseRegion
{
private PoisonRoom m_Room;
private int m_LightLevel;
public PoisonRoomRegion( PoisonRoom room, string name, Map map, int priority, Rectangle2D[] rect, int lightlevel ) : base( name, map, priority, rect )
{
ExcludeFromParentSpawns = true;
m_Room = room;
m_LightLevel = lightlevel;
}
public override void OnEnter( Mobile m )
{
base.OnEnter( m );
m_Room.OnEnter( m );
}
public override void OnExit( Mobile m )
{
base.OnExit( m );
m_Room.OnExit( m );
}
public override void OnDeath( Mobile m )
{
base.OnDeath( m );
m_Room.OnDeath( m );
}
public override bool OnResurrect( Mobile from )
{
return true;
}
public override void AlterLightLevel( Mobile m, ref int global, ref int personal )
{
global = m_LightLevel;
}
public override bool OnBeginSpellCast( Mobile m, ISpell s )
{
if ( ( s is MarkSpell || s is GateTravelSpell || s is RecallSpell || s is SacredJourneySpell ) && m.AccessLevel == AccessLevel.Player )
{
m.SendLocalizedMessage( 501802 ); // Thy spell doth not appear to work...
return false;
}
return base.OnBeginSpellCast( m, s );
}
}
}
}

View file

@ -0,0 +1,744 @@
using System;
using System.Collections;
using Server.Commands;
using Server;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
{
public class LampController : Item
{
public static void Initialize()
{
CommandSystem.Register( "GenLampPuzzle", AccessLevel.Administrator, new CommandEventHandler( GenLampPuzzle_OnCommand ) );
}
[Usage( "GenLampPuzzle" )]
[Description( "Generates lamp room puzzle in doom." )]
public static void GenLampPuzzle_OnCommand( CommandEventArgs e )
{
e.Mobile.SendMessage( "Generating puzzle, please wait." );
Point3D loc = new Point3D( 324, 64, -1 );
bool exists = false;
foreach ( Item item in Map.Malas.GetItemsInRange( loc, 0 ) )
{
if ( item is LampController )
{
exists = true;
break;
}
}
if ( !exists )
{
LampController controller = new LampController();
controller.MoveToWorld( loc, Map.Malas );
e.Mobile.SendMessage( "Puzzle generating complete. Puzzle were generated." );
}
else
e.Mobile.SendMessage( "Puzzle generating complete. Puzzle aleardy exists." );
}
public Rectangle2D Rect = new Rectangle2D( 464, 91, 10, 10 );
public PoisonTimer m_Timer;
private string m_Code;
private string m_PuzzleCode;
[CommandProperty( AccessLevel.GameMaster )]
public string PuzzleCode { get { return m_PuzzleCode; } set { m_PuzzleCode = value; } }
[CommandProperty( AccessLevel.GameMaster )]
public string Code
{
get { return m_Code; }
set
{
m_Code = value;
if ( m_Code.Length == 4 )
{
CheckCode();
}
}
}
private ArrayList m_Levers;
private ArrayList m_Statues;
private ArrayList m_Pads;
private PuzzleBox m_Box;
private bool m_CanActive;
[CommandProperty( AccessLevel.GameMaster )]
public bool CanActive { get { return m_CanActive; } set { m_CanActive = value; } }
private bool Check()
{
foreach ( Item item in World.Items.Values )
{
if ( item is LampController && !item.Deleted && item != this )
{
return true;
}
}
return false;
}
[Constructable]
public LampController() : base( 0x1BC3 )
{
if ( Check() )
{
World.Broadcast( 0x35, true, "Another Lamp's room controller exists in the world!" );
Delete();
return;
}
Visible = false;
Movable = false;
Setup();
}
public void Setup()
{
m_CanActive = true;
m_Code = "";
m_PuzzleCode = "";
m_Levers = new ArrayList();
m_Statues = new ArrayList();
m_Pads = new ArrayList();
PuzzleLever lever1 = new PuzzleLever( 1 );
lever1.Controller = this;
lever1.MoveToWorld( new Point3D( 316, 64, 5 ), Map.Malas );
m_Levers.Add( lever1 );
PuzzleLever lever2 = new PuzzleLever( 2 );
lever2.Controller = this;
lever2.MoveToWorld( new Point3D( 323, 58, 5 ), Map.Malas );
m_Levers.Add( lever2 );
PuzzleLever lever3 = new PuzzleLever( 3 );
lever3.Controller = this;
lever3.MoveToWorld( new Point3D( 332, 63, 5 ), Map.Malas );
m_Levers.Add( lever3 );
PuzzleLever lever4 = new PuzzleLever( 4 );
lever4.Controller = this;
lever4.MoveToWorld( new Point3D( 323, 71, 5 ), Map.Malas );
m_Levers.Add( lever4 );
PuzzleStatue statue1 = new PuzzleStatue( 0x12D8 );
statue1.MoveToWorld( new Point3D( 319, 70, 18 ), Map.Malas );
m_Statues.Add( statue1 );
PuzzleStatue statue2 = new PuzzleStatue( 0x12D9 );
statue2.MoveToWorld( new Point3D( 329, 60, 18 ), Map.Malas );
m_Statues.Add( statue2 );
PuzzlePad pad1 = new PuzzlePad();
pad1.MoveToWorld( new Point3D( 324, 58, -1 ), Map.Malas );
pad1.Visible = false;
m_Pads.Add( pad1 );
PuzzlePad pad2 = new PuzzlePad();
pad2.MoveToWorld( new Point3D( 332, 64, -1 ), Map.Malas );
pad2.Visible = false;
m_Pads.Add( pad2 );
PuzzlePad pad3 = new PuzzlePad();
pad3.MoveToWorld( new Point3D( 323, 72, -1 ), Map.Malas );
pad3.Visible = false;
m_Pads.Add( pad3 );
PuzzlePad pad4 = new PuzzlePad();
pad4.MoveToWorld( new Point3D( 316, 65, -1 ), Map.Malas );
pad4.Visible = false;
m_Pads.Add( pad4 );
PuzzlePad pad5 = new PuzzlePad();
pad5.MoveToWorld( new Point3D( 324, 64, -1 ), Map.Malas );
m_Pads.Add( pad5 );
Teleporter teleporter1 = new Teleporter();
teleporter1.MapDest = Map.Malas;
teleporter1.PointDest = new Point3D( 353, 172, -1 );
teleporter1.MoveToWorld( new Point3D( 468, 92, -1 ), Map.Malas );
Teleporter teleporter2 = new Teleporter();
teleporter2.MapDest = Map.Malas;
teleporter2.PointDest = new Point3D( 353, 172, -1 );
teleporter2.MoveToWorld( new Point3D( 469, 92, -1 ), Map.Malas );
Teleporter teleporter3 = new Teleporter();
teleporter3.MapDest = Map.Malas;
teleporter3.PointDest = new Point3D( 353, 172, -1 );
teleporter3.MoveToWorld( new Point3D( 470, 92, -1 ), Map.Malas );
m_Box = new PuzzleBox();
m_Box.CanSummon = true;
m_Box.MoveToWorld( new Point3D( 469, 96, 6 ), Map.Malas );
m_PuzzleCode = GenerateCode( m_PuzzleCode );
}
public void ClearRoom()
{
IPooledEnumerable eable = Map.Malas.GetMobilesInBounds( Rect );
ArrayList list = new ArrayList();
foreach ( object obj in eable )
{
if ( obj is Mobile )
{
Mobile mobile = obj as Mobile;
list.Add( mobile );
}
}
for ( int i = 0; i < list.Count; i++ )
{
Mobile m = list[ i ] as Mobile;
if ( m is WandererOfTheVoid )
{
m.Delete();
}
else
{
Rectangle2D rect = new Rectangle2D( 342, 168, 16, 16 );
int x = Utility.Random( rect.X, rect.Width );
int y = Utility.Random( rect.Y, rect.Height );
if ( x >= 345 && x <= 352 && y >= 173 && y <= 179 )
{
x = 353;
y = 172;
}
m.MoveToWorld( new Point3D( x, y, -1 ), Map.Malas );
}
}
if ( m_Timer != null )
{
m_Timer.Stop();
}
m_CanActive = true;
m_Box.CanSummon = true;
m_PuzzleCode = "";
m_PuzzleCode = GenerateCode( m_PuzzleCode );
}
public static string[] m_Combinations = new string[] { "1234", "1243", "1324", "1342", "1423", "1432", "2134", "2143", "2314", "2341", "2413", "2431", "3124", "3142", "3214", "3241", "3412", "3421", "4123", "4132", "4213", "4231", "4312", "4321" };
public void FreeLevers()
{
for ( int i = 0; i < m_Levers.Count; i++ )
{
PuzzleLever lever = m_Levers[ i ] as PuzzleLever;
lever.ItemID = 0x108E;
}
m_Code = "";
Timer.DelayCall( TimeSpan.FromSeconds( 30.0 ), new TimerCallback( SayQuitMessage ) );
}
public void SayQuitMessage()
{
SayStatues( 1062053, -1 ); // The sands of time have run their course.
for ( int i = 0; i < m_Levers.Count; i++ )
{
PuzzleLever lever = m_Levers[ i ] as PuzzleLever;
lever.ItemID = 0x108E;
}
}
public static string GenerateCode( string puzzle )
{
// at OSI code scheme is right order of pressed levers
// any press at any of 4 levers is one bit of code
// orientation of lever doesn't play any role
// code can't have equal numbers in it, only different, i.e: 1-4-2-3, no 1-1-1-1
// so, we have 24 combinations for solving
string old_code = puzzle;
string new_code = "";
while ( new_code == old_code )
{
new_code = m_Combinations[ Utility.Random( m_Combinations.Length ) ];
}
return new_code;
}
public int CompareCodes( string puzzle, string player )
{
int result = 0;
if ( puzzle.Length != player.Length || puzzle.Length > 4 || player.Length > 4 )
{
return 0;
}
for ( int i = 0; i < puzzle.Length; i++ )
{
if ( puzzle[ i ] == player[ i ] )
{
result++;
}
}
return result;
}
public void SayStatues( int message, int souls )
{
string args = "";
if ( souls != -1 )
{
args = souls.ToString();
}
for ( int i = 0; i < m_Statues.Count; i++ )
{
PuzzleStatue statue = m_Statues[ i ] as PuzzleStatue;
if ( statue != null )
{
statue.PublicOverheadMessage( Network.MessageType.Regular, 0x3B2, message, args );
}
}
}
public void CheckCode()
{
bool incomplete = false;
int correct_souls = 0;
for ( int i = 0; i < m_Pads.Count; i++ )
{
PuzzlePad pad = m_Pads[ i ] as PuzzlePad;
if ( pad == null || !pad.Busy )
{
incomplete = true;
}
}
correct_souls = CompareCodes( m_PuzzleCode, m_Code );
if ( incomplete )
{
SayStatues( 1050004, -1 ); // The circle is the key, the key is incomplete and so the gate remains closed.
}
else
{
// we don't guess code
if ( correct_souls >= 0 && correct_souls < 4 )
{
ArrayList players = new ArrayList();
for ( int i = 0; i < m_Pads.Count; i++ )
{
PuzzlePad pad = m_Pads[ i ] as PuzzlePad;
if ( pad != null && pad.Stander != null && pad.Stander.Alive )
{
players.Add( pad.Stander );
}
}
for ( int j = 0; j < players.Count; j++ )
{
PlayerMobile player = players[ j ] as PlayerMobile;
if ( player != null )
{
Point3D location1 = player.Location;
location1.Z = 49;
Point3D location2 = player.Location;
location2.Z = -1;
Effects.SendPacket( player, player.Map, new HuedEffect( EffectType.Moving, Serial.Zero, player.Serial, 0x11B7, location1, location2, 20, 0, true, true, 0, 0 ) );
Effects.PlaySound( new Point3D( 324, 64, -1 ), Map.Malas, 0x144 );
Effects.PlaySound( new Point3D( player.X, player.Y, -1 ), Map.Malas, Utility.RandomList( 0x154, 0x14B ) );
player.Send( new AsciiMessage( Serial.MinusOne, 0xFFFF, MessageType.Label, 0x66D, 3, "", "You are pinned down by the weight of the boulder!!!" ) );
}
}
switch ( correct_souls )
{
case 0:
SayStatues( 1050009, correct_souls );
break; // The circle of souls has failed to turn the key. The gate remains closed...
case 1:
SayStatues( 1050007, correct_souls );
break; // ~1_NUM~ soul has turned the key correctly, but the rest have forsaken the circle...
default:
SayStatues( 1050008, correct_souls );
break; // ~1_NUM~ souls have turned the key correctly, but the rest have forsaken the circle...
}
for ( int j = 0; j < players.Count; j++ )
{
PlayerMobile player = players[ j ] as PlayerMobile;
if ( player != null )
{
Effects.SendPacket( player, player.Map, new HuedEffect( EffectType.FixedXYZ, Serial.Zero, Serial.Zero, 0x36BD, new Point3D( player.X, player.Y, 0 ), new Point3D( player.X, player.Y, 0 ), 20, 10, true, false, 0, 0 ) );
Effects.SendPacket( player, player.Map, new HuedEffect( EffectType.FixedFrom, player.Serial, Serial.Zero, 0x36BD, new Point3D( player.X, player.Y, -1 ), new Point3D( player.X, player.Y, -1 ), 20, 10, true, false, 0, 0 ) );
Effects.PlaySound( new Point3D( player.X, player.Y, -1 ), player.Map, 0x307 );
for ( int k = 0; k < 5; k++ )
{
Effects.SendPacket( player, player.Map, new HuedEffect( EffectType.Moving, Serial.Zero, Serial.Zero, 0x1363 + Utility.Random( 0, 11 ), new Point3D( player.X, player.Y, 0 ), new Point3D( player.X, player.Y, 0 ), 5, 0, false, false, 0, 0 ) );
Effects.PlaySound( new Point3D( player.X, player.Y, -1 ), Map.Malas, 0x13F );
Effects.PlaySound( new Point3D( player.X, player.Y, -1 ), Map.Malas, 0x154 );
player.Say( "OUCH!" );
}
player.Damage( 90, null );
player.Send( new AsciiMessage( Serial.MinusOne, 0xFFFF, MessageType.Label, 0x66D, 3, "", "A speeding rock hits you in the head!" ) );
player.SendLocalizedMessage( 502382 ); // You can move!
}
}
}
else
{
// we done it!
PlayerMobile center = ( (PuzzlePad) m_Pads[ 4 ] ).Stander;
for ( int i = 0; i < m_Pads.Count; i++ )
{
PuzzlePad pad = m_Pads[ i ] as PuzzlePad;
if ( pad != null && pad.Stander != null && pad.Stander.Alive )
{
Effects.SendPacket( pad.Stander, Map.Malas, new HuedEffect( EffectType.FixedXYZ, Serial.Zero, Serial.Zero, 0x1153, new Point3D( 325, 64, -1 ), new Point3D( 325, 64, -1 ), 1, 60, true, false, 0, 0 ) );
Effects.SendPacket( pad.Stander, Map.Malas, new HuedEffect( EffectType.FixedXYZ, Serial.Zero, Serial.Zero, 0x1153, new Point3D( 325, 64, -1 ), new Point3D( 325, 64, -1 ), 1, 60, true, false, 0, 0 ) );
Effects.PlaySound( new Point3D( 325, 64, -1 ), Map.Malas, 0x244 );
if ( center != null )
{
Effects.SendPacket( pad.Stander, Map.Malas, new HuedEffect( EffectType.Lightning, center.Serial, Serial.Zero, 0x0, new Point3D( 324, 64, -1 ), new Point3D( 324, 64, -1 ), 0, 0, false, false, 0, 0 ) );
Effects.SendPacket( pad.Stander, Map.Malas, new ParticleEffect( EffectType.FixedFrom, center.Serial, Serial.Zero, 0x0, new Point3D( 324, 64, -1 ), new Point3D( 324, 64, -1 ), 0, 0, false, false, 0, 0, 0x13A7, 0, 0, center.Serial, 3, 0 ) );
}
}
}
if ( center != null )
{
center.MoveToWorld( new Point3D( 467, 96, -1 ), Map.Malas );
if ( m_Timer != null )
{
m_Timer.Stop();
}
m_Timer = new PoisonTimer( this );
m_Timer.Start();
m_CanActive = false;
m_Box.CanSummon = true;
}
}
}
FreeLevers();
}
public LampController( Serial serial ) : base( serial )
{
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.WriteItemList( m_Levers, true );
writer.WriteItemList( m_Statues, true );
writer.WriteItemList( m_Pads, true );
writer.Write( m_Box );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_Code = "";
m_PuzzleCode = "";
m_PuzzleCode = GenerateCode( m_PuzzleCode );
m_Levers = reader.ReadItemList();
m_Statues = reader.ReadItemList();
m_Pads = reader.ReadItemList();
m_Box = reader.ReadItem() as PuzzleBox;
m_CanActive = true;
m_Box.CanSummon = true;
}
public class PoisonTimer : Timer
{
public LampController m_Controller;
public int count = 1;
public PoisonTimer( LampController controller ) : base( TimeSpan.FromSeconds( 8.0 ), TimeSpan.FromSeconds( 1.0 ) )
{
m_Controller = controller;
}
public void CheckAlive()
{
bool AliveCreatures = false;
IPooledEnumerable eable = Map.Malas.GetMobilesInBounds( m_Controller.Rect );
foreach ( object obj in eable )
{
if ( obj is Mobile )
{
Mobile mobile = obj as Mobile;
if ( mobile != null && mobile.Alive && !( mobile is WandererOfTheVoid ) )
{
AliveCreatures = true;
}
}
}
eable.Free();
if ( !AliveCreatures )
{
m_Controller.ClearRoom();
Stop();
}
}
public void Gas( int level )
{
int[] x = new int[ 3 ], y = new int[ 3 ];
for ( int i = 0; i < x.Length; i++ )
{
x[ i ] = Utility.Random( m_Controller.Rect.X, m_Controller.Rect.Width );
y[ i ] = Utility.Random( m_Controller.Rect.Y, m_Controller.Rect.Height );
}
int hue = 0xAC;
Poison poison = null;
switch ( level )
{
case 0:
hue = 0xA6;
poison = Poison.Lesser;
break;
case 1:
hue = 0xAA;
poison = Poison.Regular;
break;
case 2:
hue = 0xAC;
poison = Poison.Greater;
break;
case 3:
hue = 0xA8;
poison = Poison.Deadly;
break;
case 4:
hue = 0xA4;
poison = Poison.Lethal;
break;
case 5:
hue = 0xAC;
poison = Poison.Lethal;
break;
}
Effects.SendLocationParticles( EffectItem.Create( new Point3D( x[ 0 ], y[ 0 ], -1 ), Map.Malas, EffectItem.DefaultDuration ), 0x36B0, 1, Utility.Random( 160, 200 ), hue, 0, 0x1F78, 0 );
Effects.SendLocationParticles( EffectItem.Create( new Point3D( x[ 1 ], y[ 1 ], -1 ), Map.Malas, EffectItem.DefaultDuration ), 0x36CB, 1, Utility.Random( 160, 200 ), hue, 0, 0x1F78, 0 );
Effects.SendLocationParticles( EffectItem.Create( new Point3D( x[ 2 ], y[ 2 ], -1 ), Map.Malas, EffectItem.DefaultDuration ), 0x36BD, 1, Utility.Random( 160, 200 ), hue, 0, 0x1F78, 0 );
IPooledEnumerable eable = Map.Malas.GetMobilesInBounds( m_Controller.Rect );
foreach ( object obj in eable )
{
if ( obj is Mobile )
{
Mobile mobile = obj as Mobile;
if ( mobile != null && poison != null && mobile.Poison == null && !( mobile is WandererOfTheVoid ) )
{
double chance = ( level + 1 ) * 0.3;
if ( chance >= Utility.RandomDouble() )
{
mobile.ApplyPoison( mobile, poison );
}
}
}
}
eable.Free();
}
protected override void OnTick()
{
CheckAlive();
count++;
int level = (int) ( count / 60 );
if ( count % 60 == 0 ) // every minute we need send message to player about level's change
{
int number = 0;
int hue = 0x485;
switch ( level )
{
case 1:
number = 1050001;
break; // It is becoming more difficult for you to breathe as the poisons in the room become more concentrated.
case 2:
number = 1050003;
break; // You begin to panic as the poison clouds thicken.
case 3:
number = 1050056;
break; // Terror grips your spirit as you realize you may never leave this room alive.
case 4:
number = 1050057;
break; // The end is near. You feel hopeless and desolate. The poison is beginning to stiffen your muscles.
case 5:
number = 1062091;
hue = 0x23F3;
break; // The poison is becoming too much for you to bear. You fear that you may die at any moment.
}
IPooledEnumerable eable = Map.Malas.GetMobilesInBounds( m_Controller.Rect );
foreach ( object obj in eable )
{
if ( obj is Mobile )
{
Mobile mobile = obj as Mobile;
if ( mobile != null && mobile.Player )
{
if ( number != 0 )
{
mobile.SendLocalizedMessage( number, null, hue );
}
}
}
}
eable.Free();
if ( level == 5 )
{
PainTimer timer = new PainTimer( m_Controller );
timer.Start();
}
}
if ( count % 5 == 0 ) // every 5 seconds we fill room with a gas
{
Gas( level );
}
}
}
public class PainTimer : Timer
{
public LampController m_Controller;
public int count = 1;
public PainTimer( LampController controller ) : base( TimeSpan.FromSeconds( 10.0 ), TimeSpan.FromSeconds( 10.0 ) )
{
m_Controller = controller;
}
protected override void OnTick()
{
count++;
IPooledEnumerable eable = Map.Malas.GetMobilesInBounds( m_Controller.Rect );
ArrayList targets = new ArrayList();
foreach ( Mobile mobile in eable )
{
targets.Add( mobile );
}
for ( int i = 0; i < targets.Count; ++i )
{
Mobile mobile = targets[ i ] as Mobile;
if ( mobile != null && !( mobile is WandererOfTheVoid ) )
{
if ( mobile.Player )
{
mobile.Say( 1062092 ); // Your body reacts violently from the pain.
mobile.Animate( 32, 5, 1, true, false, 0 );
}
mobile.Damage( Utility.Random( 15, 20 ) );
if ( count == 10 ) // at OSI at this second all mobiles is killed and room is cleared
{
mobile.Kill();
}
}
}
eable.Free();
if ( count == 10 )
{
if ( m_Controller != null )
{
m_Controller.ClearRoom(); // clear room
if ( m_Controller.m_Timer != null )
{
m_Controller.m_Timer.Stop(); // stop gas effects
}
Stop(); // stop convulsions
}
}
}
}
}
}

View file

@ -0,0 +1,80 @@
using System;
using System.Collections;
using Server;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
{
public class PuzzleBox : Item
{
private bool m_CanSummon;
[CommandProperty( AccessLevel.GameMaster )]
public bool CanSummon { get { return m_CanSummon; } set { m_CanSummon = value; } }
private WandererOfTheVoid m_Wanderer;
[CommandProperty( AccessLevel.GameMaster )]
public WandererOfTheVoid Wanderer { get { return m_Wanderer; } set { m_Wanderer = value; } }
public override bool ForceShowProperties { get { return true; } }
[Constructable]
public PuzzleBox() : base( 0xE80 )
{
Movable = false;
m_Wanderer = null;
}
public PuzzleBox( Serial serial ) : base( serial )
{
}
public override void OnDoubleClick( Mobile from )
{
if ( !from.InRange( this.GetWorldLocation(), 3 ) )
return;
if ( m_CanSummon && ( m_Wanderer == null || !m_Wanderer.Alive ) )
{
m_Wanderer = new WandererOfTheVoid();
m_Wanderer.MoveToWorld( new Point3D( 467, 94, -1 ), Map.Malas );
// I am the guardian of the Tomb of Sektu. Suffer my wrath!
m_Wanderer.PublicOverheadMessage( Network.MessageType.Regular, 0x3B2, 1060002, "" );
Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), new TimerCallback( SayFakeMessage ) );
m_CanSummon = false;
}
}
public void SayFakeMessage()
{
// You try to pry the box open, when you notice that there is no opening. It's a fake box.
PublicOverheadMessage( Network.MessageType.Regular, 0x3B2, 1060003, "" );
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( m_Wanderer );
writer.Write( (bool) m_CanSummon );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_Wanderer = reader.ReadMobile() as WandererOfTheVoid;
m_CanSummon = reader.ReadBool();
}
}
}

View file

@ -0,0 +1,87 @@
using System;
using System.Collections;
using Server;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
{
public class PuzzleLever : Item
{
private LampController m_Controller;
private int m_Code;
[CommandProperty( AccessLevel.GameMaster )]
public LampController Controller
{
get { return m_Controller; }
set { m_Controller = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int Code
{
get { return m_Code; }
set { m_Code = value; }
}
[Constructable]
public PuzzleLever( int code ) : base( 0x108E )
{
m_Code = code;
Hue = 0x66D;
Movable = false;
}
public PuzzleLever( Serial serial ) : base( serial )
{
}
public override void OnDoubleClick( Mobile from )
{
if ( m_Controller != null && m_Controller.CanActive )
{
if ( m_Controller.Code.Length < 4 )
{
m_Controller.Code += m_Code;
if ( ItemID == 0x108E )
{
ItemID = 0x108C;
}
else if ( ItemID == 0x108C )
{
ItemID = 0x108E;
}
Effects.PlaySound( Location, Map, 0x3E8 );
}
}
else
{
from.SendLocalizedMessage( 1060001 ); // You throw the switch, but the mechanism cannot be engaged again so soon.
}
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( (int) m_Code );
writer.Write( m_Controller );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
m_Code = reader.ReadInt();
m_Controller = reader.ReadItem() as LampController;
}
}
}

View file

@ -0,0 +1,124 @@
using System;
using System.Collections;
using Server;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
{
public class PuzzlePad : Item
{
private PlayerMobile m_Stander;
private bool m_Busy;
[CommandProperty( AccessLevel.GameMaster )]
public PlayerMobile Stander
{
get { return m_Stander; }
set { m_Stander = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public bool Busy
{
get { return m_Busy; }
set { m_Busy = value; }
}
private InternalStandTimer m_Timer;
[Constructable]
public PuzzlePad() : base( 0x1822 )
{
m_Busy = false;
m_Stander = null;
m_Timer = null;
Hue = 0x4C;
Movable = false;
}
public override bool HandlesOnMovement { get { return true; } } // Tell the core that we implement OnMovement
public override bool OnMoveOver( Mobile m )
{
if ( ( m != null ) && ( m is PlayerMobile ) )
{
if ( m_Stander == null )
{
m_Stander = (PlayerMobile) m;
if ( m_Timer != null )
{
m_Timer.Stop();
}
m_Timer = new InternalStandTimer( this );
m_Timer.Start();
}
}
return base.OnMoveOver( m );
}
public PuzzlePad( 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();
}
private class InternalStandTimer : Timer
{
private PuzzlePad m_Pad;
public InternalStandTimer( PuzzlePad pad ) : base( TimeSpan.FromSeconds( 0.25 ), TimeSpan.FromSeconds( 0.25 ) )
{
m_Pad = pad;
Priority = TimerPriority.FiftyMS;
}
private void Vacance()
{
if ( m_Pad != null )
{
m_Pad.Stander = null;
m_Pad.Busy = false;
}
Stop();
}
protected override void OnTick()
{
if ( m_Pad != null && !m_Pad.Deleted && m_Pad.Stander != null )
{
if ( !m_Pad.Stander.Deleted && m_Pad.Stander.Alive && m_Pad.Stander.Location == m_Pad.Location )
{
m_Pad.Busy = true;
}
else
{
Vacance();
}
}
else
{
Vacance();
}
}
}
}
}

View file

@ -0,0 +1,36 @@
using System;
using System.Collections;
using Server;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
{
public class PuzzleStatue : Item
{
[Constructable]
public PuzzleStatue( int itemID ) : base( itemID )
{
Hue = 0x44E;
Movable = false;
}
public PuzzleStatue( 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

@ -129,7 +129,11 @@ namespace Server.Engines.Plants
PlantTypeInfo typeInfo = PlantTypeInfo.GetInfo( m_Plant.PlantType );
PlantHueInfo hueInfo = PlantHueInfo.GetInfo( m_Plant.PlantHue );
AddItem( 130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, typeInfo.ItemID, hueInfo.Hue );
// The large images for these trees trigger a client crash, so use a smaller, generic tree.
if ( m_Plant.PlantType == PlantType.CypressTwisted || m_Plant.PlantType == PlantType.CypressStraight )
AddItem( 130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, 0x0CCA, hueInfo.Hue );
else
AddItem( 130 + typeInfo.OffsetX, 96 + typeInfo.OffsetY, typeInfo.ItemID, hueInfo.Hue );
}
if ( status != PlantStatus.BowlOfDirt )

View file

@ -259,23 +259,38 @@ namespace Server.Engines.Plants
if ( m_PlantStatus < PlantStatus.DecorativePlant )
{
string args = string.Format( "#{0}\t#{1}\t#{2}", m_PlantSystem.GetLocalizedHealth(), title, typeInfo.Name );
if ( typeInfo.ContainsPlant )
if ( m_PlantType == PlantType.SugarCanes )
{
// a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~
list.Add( hueInfo.IsBright() ? 1061891 : 1061889, args );
string args = string.Format( "#{0}", m_PlantSystem.GetLocalizedHealth() );
list.Add ( 1094702, args );
}
else
{
// a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ plant
list.Add( hueInfo.IsBright() ? 1061892 : 1061890, args );
string args = string.Format( "#{0}\t#{1}\t#{2}", m_PlantSystem.GetLocalizedHealth(), title, typeInfo.Name );
if ( typeInfo.ContainsPlant )
{
// a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~
list.Add( hueInfo.IsBright() ? 1061891 : 1061889, args );
}
else
{
// a ~1_HEALTH~ [bright] ~2_COLOR~ ~3_NAME~ plant
list.Add( hueInfo.IsBright() ? 1061892 : 1061890, args );
}
}
}
else
{
// a decorative ~1_COLOR~ ~2_TYPE~ plant
list.Add( hueInfo.IsBright() ? 1074267 : 1070973, string.Format( "#{0}\t#{1}", title, typeInfo.Name ) );
if ( m_PlantType == PlantType.SugarCanes )
list.Add ( 1094703 );
else if ( title == 1080528 )
// a decorative ~2_TYPE~
list.Add( 1080539, string.Format( "#{0}\t#{1}", title, typeInfo.Name ) );
else
// a decorative ~1_COLOR~ ~2_TYPE~ plant
list.Add( hueInfo.IsBright() ? 1074267 : 1070973, string.Format( "#{0}\t#{1}", title, typeInfo.Name ) );
}
}
else if ( m_PlantStatus >= PlantStatus.Seed )

View file

@ -29,7 +29,24 @@ namespace Server.Engines.Plants
RareGreenBonsai,
RarePinkBonsai,
ExceptionalBonsai,
ExoticBonsai
ExoticBonsai,
Cactus,
FlaxFlowers,
FoxgloveFlowers,
HopsEast,
OrfluerFlowers,
CypressTwisted,
HedgeShort,
JuniperBush,
SnowdropPatch,
Cattails,
PoppyPatch,
SpiderTree,
WaterLily,
CypressStraight,
HedgeTall,
HopsSouth,
SugarCanes
}
public class PlantTypeInfo
@ -60,7 +77,24 @@ namespace Server.Engines.Plants
new PlantTypeInfo( 0x28DE, -5, 5, PlantType.RareGreenBonsai, true, false, false ),
new PlantTypeInfo( 0x28E1, -5, 5, PlantType.RarePinkBonsai, true, false, false ),
new PlantTypeInfo( 0x28E2, -5, 5, PlantType.ExceptionalBonsai, true, false, false ),
new PlantTypeInfo( 0x28E3, -5, 5, PlantType.ExoticBonsai, true, false, false )
new PlantTypeInfo( 0x28E3, -5, 5, PlantType.ExoticBonsai, true, false, false ),
new PlantTypeInfo( 0x0D25, 0, 0, PlantType.Cactus, false, false, false ),
new PlantTypeInfo( 0x1A9A, 5, 10, PlantType.FlaxFlowers, false, true, false ),
new PlantTypeInfo( 0x0C84, 0, 0, PlantType.FoxgloveFlowers, false, true, false ),
new PlantTypeInfo( 0x1A9F, 5, -25, PlantType.HopsEast, false, false, false ),
new PlantTypeInfo( 0x0CC1, 0, 0, PlantType.OrfluerFlowers, false, true, false ),
new PlantTypeInfo( 0x0CFE, -45, -30, PlantType.CypressTwisted, false, false, false ),
new PlantTypeInfo( 0x0C8F, 0, 0, PlantType.HedgeShort, false, false, false ),
new PlantTypeInfo( 0x0CC8, 0, 0, PlantType.JuniperBush, true, false, false ),
new PlantTypeInfo( 0x0C8E, -20, 0, PlantType.SnowdropPatch, false, true, false ),
new PlantTypeInfo( 0x0CB7, 0, 0, PlantType.Cattails, false, false, false ),
new PlantTypeInfo( 0x0CBE, -20, 0, PlantType.PoppyPatch, false, true, false ),
new PlantTypeInfo( 0x0CC9, 0, 0, PlantType.SpiderTree, false, false, false ),
new PlantTypeInfo( 0x0DC1, -5, 15, PlantType.WaterLily, false, true, false ),
new PlantTypeInfo( 0x0CFB, -45, -30, PlantType.CypressStraight, false, false, false ),
new PlantTypeInfo( 0x0DB8, 0, -20, PlantType.HedgeTall, false, false, false ),
new PlantTypeInfo( 0x1AA1, 10, -25, PlantType.HopsSouth, false, false, false ),
new PlantTypeInfo( 0x246C, -25, -20, PlantType.SugarCanes, false, false, false )
};
public static PlantTypeInfo GetInfo( PlantType plantType )
@ -83,6 +117,51 @@ namespace Server.Engines.Plants
}
}
public static PlantType RandomPeculiarGroupOne()
{
switch ( Utility.Random( 5 ) )
{
case 0: return PlantType.Cactus;
case 1: return PlantType.FlaxFlowers;
case 2: return PlantType.FoxgloveFlowers;
case 3: return PlantType.HopsEast;
default: return PlantType.OrfluerFlowers;
}
}
public static PlantType RandomPeculiarGroupTwo()
{
switch ( Utility.Random( 4 ) )
{
case 0: return PlantType.CypressTwisted;
case 1: return PlantType.HedgeShort;
case 2: return PlantType.JuniperBush;
default: return PlantType.SnowdropPatch;
}
}
public static PlantType RandomPeculiarGroupThree()
{
switch ( Utility.Random( 4 ) )
{
case 0: return PlantType.Cattails;
case 1: return PlantType.PoppyPatch;
case 2: return PlantType.SpiderTree;
default: return PlantType.WaterLily;
}
}
public static PlantType RandomPeculiarGroupFour()
{
switch ( Utility.Random( 4 ) )
{
case 0: return PlantType.CypressStraight;
case 1: return PlantType.HedgeTall;
case 2: return PlantType.HopsSouth;
default: return PlantType.SugarCanes;
}
}
public static PlantType RandomBonsai( double increaseRatio )
{
/* Chances of each plant type are equal to the chances of the previous plant type * increaseRatio:
@ -152,6 +231,25 @@ namespace Server.Engines.Plants
{
switch ( plantType )
{
case PlantType.Cactus:
case PlantType.FlaxFlowers:
case PlantType.FoxgloveFlowers:
case PlantType.HopsEast:
case PlantType.OrfluerFlowers:
case PlantType.CypressTwisted:
case PlantType.HedgeShort:
case PlantType.JuniperBush:
case PlantType.SnowdropPatch:
case PlantType.Cattails:
case PlantType.PoppyPatch:
case PlantType.SpiderTree:
case PlantType.WaterLily:
case PlantType.CypressStraight:
case PlantType.HedgeTall:
case PlantType.HopsSouth:
case PlantType.SugarCanes:
return 1080528; // peculiar
case PlantType.CommonGreenBonsai:
case PlantType.CommonPinkBonsai:
return 1063335; // common

View file

@ -56,6 +56,17 @@ namespace Server.Engines.Plants
return new Seed( PlantTypeInfo.RandomBonsai( increaseRatio ), PlantHue.Plain, false );
}
public static Seed RandomPeculiarSeed( int group )
{
switch ( group )
{
case 1: return new Seed ( PlantTypeInfo.RandomPeculiarGroupOne(), PlantHue.Plain, false );
case 2: return new Seed ( PlantTypeInfo.RandomPeculiarGroupTwo(), PlantHue.Plain, false );
case 3: return new Seed ( PlantTypeInfo.RandomPeculiarGroupThree(), PlantHue.Plain, false );
default: return new Seed ( PlantTypeInfo.RandomPeculiarGroupFour(), PlantHue.Plain, false );
}
}
[Constructable]
public Seed() : this( PlantTypeInfo.RandomFirstGeneration(), PlantHueInfo.RandomFirstGeneration(), false )
{

View file

@ -594,8 +594,6 @@ namespace Server.Mobiles
from.SendLocalizedMessage( 500269 ); // You cannot build that there.
else if ( result == AddonFitResult.NotInHouse )
from.SendLocalizedMessage( 1076192 ); // Statues can only be placed in houses where you are the owner or co-owner.
else if ( result == AddonFitResult.DoorsNotClosed )
from.SendMessage( "You must close all house doors before placing this." );
else if ( result == AddonFitResult.DoorTooClose )
from.SendLocalizedMessage( 500271 ); // You cannot build near the door.
}
@ -621,9 +619,6 @@ namespace Server.Mobiles
{
BaseDoor door = doors[ i ] as BaseDoor;
if ( door != null && door.Open )
return AddonFitResult.DoorsNotClosed;
Point3D doorLoc = door.GetWorldLocation();
int doorHeight = door.ItemData.CalcHeight;

View file

@ -12,7 +12,6 @@ namespace Server.Items
Valid,
Blocked,
NotInHouse,
DoorsNotClosed,
DoorTooClose,
NoWall
}
@ -142,9 +141,6 @@ namespace Server.Items
{
BaseDoor door = doors[i] as BaseDoor;
if ( door != null && door.Open )
return AddonFitResult.DoorsNotClosed;
Point3D doorLoc = door.GetWorldLocation();
int doorHeight = door.ItemData.CalcHeight;

View file

@ -83,8 +83,6 @@ namespace Server.Items
from.SendLocalizedMessage( 500269 ); // You cannot build that there.
else if ( res == AddonFitResult.NotInHouse )
from.SendLocalizedMessage( 500274 ); // You can only place this in a house that you own!
else if ( res == AddonFitResult.DoorsNotClosed )
from.SendMessage( "You must close all house doors before placing this." );
else if ( res == AddonFitResult.DoorTooClose )
from.SendLocalizedMessage( 500271 ); // You cannot build near the door.
else if ( res == AddonFitResult.NoWall )

View file

@ -564,13 +564,13 @@ namespace Server.Items
CraftItem item = system.CraftItems.SearchFor( GetType() );
if ( item != null && item.Ressources.Count == 1 && item.Ressources.GetAt( 0 ).Amount >= 2 )
if ( item != null && item.Resources.Count == 1 && item.Resources.GetAt( 0 ).Amount >= 2 )
{
try
{
Item res = (Item)Activator.CreateInstance( CraftResources.GetInfo( m_Resource ).ResourceTypes[0] );
ScissorHelper( from, res, m_PlayerConstructed ? (item.Ressources.GetAt( 0 ).Amount / 2) : 1 );
ScissorHelper( from, res, m_PlayerConstructed ? (item.Resources.GetAt( 0 ).Amount / 2) : 1 );
return true;
}
catch
@ -1602,7 +1602,7 @@ namespace Server.Items
Type resourceType = typeRes;
if ( resourceType == null )
resourceType = craftItem.Ressources.GetAt( 0 ).ItemType;
resourceType = craftItem.Resources.GetAt( 0 ).ItemType;
Resource = CraftResources.GetFromType( resourceType );
PlayerConstructed = true;

View file

@ -475,6 +475,26 @@ namespace Server.Items
return ( m_AosAttributes.SpellChanneling != 0 );
}
public void UnscaleDurability()
{
int scale = 100 + m_AosClothingAttributes.DurabilityBonus;
m_HitPoints = ( ( m_HitPoints * 100 ) + ( scale - 1 ) ) / scale;
m_MaxHitPoints = ( ( m_MaxHitPoints * 100 ) + ( scale - 1 ) ) / scale;
InvalidateProperties();
}
public void ScaleDurability()
{
int scale = 100 + m_AosClothingAttributes.DurabilityBonus;
m_HitPoints = ( ( m_HitPoints * scale ) + 99 ) / 100;
m_MaxHitPoints = ( ( m_MaxHitPoints * scale ) + 99 ) / 100;
InvalidateProperties();
}
public override bool CheckPropertyConfliction( Mobile m )
{
if ( base.CheckPropertyConfliction( m ) )
@ -931,7 +951,7 @@ namespace Server.Items
CraftItem item = system.CraftItems.SearchFor( GetType() );
if ( item != null && item.Ressources.Count == 1 && item.Ressources.GetAt( 0 ).Amount >= 2 )
if ( item != null && item.Resources.Count == 1 && item.Resources.GetAt( 0 ).Amount >= 2 )
{
try
{
@ -943,11 +963,11 @@ namespace Server.Items
resourceType = info.ResourceTypes[0];
if ( resourceType == null )
resourceType = item.Ressources.GetAt( 0 ).ItemType;
resourceType = item.Resources.GetAt( 0 ).ItemType;
Item res = (Item)Activator.CreateInstance( resourceType );
ScissorHelper( from, res, m_PlayerConstructed ? (item.Ressources.GetAt( 0 ).Amount / 2) : 1 );
ScissorHelper( from, res, m_PlayerConstructed ? (item.Resources.GetAt( 0 ).Amount / 2) : 1 );
res.LootType = LootType.Regular;
@ -993,7 +1013,7 @@ namespace Server.Items
Type resourceType = typeRes;
if ( resourceType == null )
resourceType = craftItem.Ressources.GetAt( 0 ).ItemType;
resourceType = craftItem.Resources.GetAt( 0 ).ItemType;
Resource = CraftResources.GetFromType( resourceType );
}

View file

@ -107,6 +107,14 @@ namespace Server.Items
return true;
}
public override void UpdateTotal( Item sender, TotalType type, int delta )
{
base.UpdateTotal( sender, type, delta );
if ( type == TotalType.Weight && RootParent is Mobile )
((Mobile) RootParent).InvalidateProperties();
}
public override void OnDoubleClick( Mobile from )
{
if ( from.AccessLevel > AccessLevel.Player || from.InRange( this.GetWorldLocation(), 2 ) || this.RootParent is PlayerVendor )
@ -142,7 +150,7 @@ namespace Server.Items
public StrongBackpack()
{
Layer = Layer.Backpack;
Weight = 3.0;
Weight = 13.0;
}
public override bool CheckHold( Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight )
@ -170,7 +178,7 @@ namespace Server.Items
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
writer.Write( (int) 1 ); // version
}
public override void Deserialize( GenericReader reader )
@ -178,6 +186,9 @@ namespace Server.Items
base.Deserialize( reader );
int version = reader.ReadInt();
if ( version == 0 )
Weight = 13.0;
}
}

View file

@ -66,7 +66,7 @@ namespace Server.Items
}
}
if ( !( m_Commodity is ICommodity ) ) //Apparently, there may be items out there with this. Funky.
if ( m_Commodity != null && !( m_Commodity is ICommodity ) ) //Apparently, there may be items out there with this. Funky.
{
Timer.DelayCall( TimeSpan.Zero, this.Delete );
}
@ -101,7 +101,7 @@ namespace Server.Items
public override int LabelNumber{ get{ return m_Commodity == null ? 1047016 : 1047017; } }
public override void GetProperties(ObjectPropertyList list)
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );

View file

@ -132,7 +132,7 @@ namespace Server.Items
Type resourceType = typeRes;
if ( resourceType == null )
resourceType = craftItem.Ressources.GetAt( 0 ).ItemType;
resourceType = craftItem.Resources.GetAt( 0 ).ItemType;
Resource = CraftResources.GetFromType( resourceType );

View file

@ -759,6 +759,17 @@ namespace Server.Items
from.SendLocalizedMessage( 1010089 ); // You fill the container with water.
}
else if ( targ is Cow )
{
Cow cow = (Cow)targ;
if ( cow.TryMilk( from ) )
{
Content = BeverageType.Milk;
Quantity = MaxQuantity;
from.SendLocalizedMessage( 1080197 ); // You fill the container with milk.
}
}
else if ( targ is LandTarget )
{
int tileID = ((LandTarget)targ).TileID;

View file

@ -375,7 +375,7 @@ namespace Server.Items
Type resourceType = typeRes;
if ( resourceType == null )
resourceType = craftItem.Ressources.GetAt( 0 ).ItemType;
resourceType = craftItem.Resources.GetAt( 0 ).ItemType;
Resource = CraftResources.GetFromType( resourceType );
@ -384,9 +384,9 @@ namespace Server.Items
if ( context != null && context.DoNotColor )
Hue = 0;
if ( 1 < craftItem.Ressources.Count )
if ( 1 < craftItem.Resources.Count )
{
resourceType = craftItem.Ressources.GetAt( 1 ).ItemType;
resourceType = craftItem.Resources.GetAt( 1 ).ItemType;
if ( resourceType == typeof( StarSapphire ) )
GemType = GemType.StarSapphire;

View file

@ -5,13 +5,16 @@ namespace Server.Items
{
interface IDurability
{
bool CanFortify { get; }
int InitMinHits { get; }
int InitMaxHits { get; }
int HitPoints { get; set; }
int MaxHitPoints { get; set; }
//Maybe a scale/unscale durability?
void ScaleDurability();
void UnscaleDurability();
}
interface IWearableDurability : IDurability

View file

@ -15,16 +15,9 @@ namespace Server.Items
}
[Constructable]
public OilCloth() : this( 1 )
{
}
[Constructable]
public OilCloth( int amount ) : base( 0x175D )
public OilCloth() : base( 0x175D )
{
Hue = 2001;
Stackable = true;
Amount = amount;
}
public bool Dye( Mobile from, DyeTub sender )

View file

@ -106,186 +106,71 @@ namespace Server.Items
return;
}
if ( targeted is BaseArmor /*&& (DefBlacksmithy.CraftSystem.CraftItems.SearchForSubclass( targeted.GetType() ) != null)*/ )
if ( targeted is IDurability && targeted is Item )
{
BaseArmor ar = (BaseArmor)targeted;
IDurability wearable = (IDurability) targeted;
Item item = (Item) targeted;
if ( !ar.CanFortify )
if ( !wearable.CanFortify )
{
from.SendLocalizedMessage( 1049083 ); // You cannot use the powder on that item.
return;
}
if ( ar.IsChildOf( from.Backpack ) && m_Powder.IsChildOf( from.Backpack ) )
if ( item.IsChildOf( from.Backpack ) && m_Powder.IsChildOf( from.Backpack ) )
{
int origMaxHP = ar.MaxHitPoints;
int origCurHP = ar.HitPoints;
int origMaxHP = wearable.MaxHitPoints;
int origCurHP = wearable.HitPoints;
int initMaxHP = Core.AOS ? 255 : ar.InitMaxHits;
ar.UnscaleDurability();
if ( ar.MaxHitPoints < initMaxHP )
if ( origMaxHP > 0 )
{
int bonus = initMaxHP - ar.MaxHitPoints;
int initMaxHP = Core.AOS ? 255 : wearable.InitMaxHits;
if ( bonus > 10 )
bonus = 10;
wearable.UnscaleDurability();
ar.MaxHitPoints += bonus;
ar.HitPoints += bonus;
ar.ScaleDurability();
if ( ar.MaxHitPoints > 255 ) ar.MaxHitPoints = 255;
if ( ar.HitPoints > 255 ) ar.HitPoints = 255;
if ( ar.MaxHitPoints > origMaxHP )
if ( wearable.MaxHitPoints < initMaxHP )
{
from.SendLocalizedMessage( 1049084 ); // You successfully use the powder on the item.
int bonus = initMaxHP - wearable.MaxHitPoints;
--m_Powder.UsesRemaining;
if ( bonus > 10 )
bonus = 10;
if ( m_Powder.UsesRemaining <= 0 )
wearable.MaxHitPoints += bonus;
wearable.HitPoints += bonus;
wearable.ScaleDurability();
if ( wearable.MaxHitPoints > 255 ) wearable.MaxHitPoints = 255;
if ( wearable.HitPoints > 255 ) wearable.HitPoints = 255;
if ( wearable.MaxHitPoints > origMaxHP )
{
from.SendLocalizedMessage( 1049086 ); // You have used up your powder of temperament.
m_Powder.Delete();
from.SendLocalizedMessage( 1049084 ); // You successfully use the powder on the item.
--m_Powder.UsesRemaining;
if ( m_Powder.UsesRemaining <= 0 )
{
from.SendLocalizedMessage( 1049086 ); // You have used up your powder of temperament.
m_Powder.Delete();
}
}
else
{
wearable.MaxHitPoints = origMaxHP;
wearable.HitPoints = origCurHP;
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
}
}
else
{
ar.MaxHitPoints = origMaxHP;
ar.HitPoints = origCurHP;
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
wearable.ScaleDurability();
}
}
else
{
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
ar.ScaleDurability();
}
}
else
{
from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it.
}
}
else if ( targeted is BaseWeapon /*&& (DefBlacksmithy.CraftSystem.CraftItems.SearchForSubclass( targeted.GetType() ) != null)*/ )
{
BaseWeapon wep = (BaseWeapon)targeted;
if ( !wep.CanFortify )
{
from.SendLocalizedMessage( 1049083 ); // You cannot use the powder on that item.
return;
}
if ( wep.IsChildOf( from.Backpack ) && m_Powder.IsChildOf( from.Backpack ) )
{
int origMaxHP = wep.MaxHitPoints;
int origCurHP = wep.HitPoints;
int initMaxHP = Core.AOS ? 255 : wep.InitMaxHits;
wep.UnscaleDurability();
if ( wep.MaxHitPoints < initMaxHP )
{
int bonus = initMaxHP - wep.MaxHitPoints;
if ( bonus > 10 )
bonus = 10;
wep.MaxHitPoints += bonus;
wep.HitPoints += bonus;
wep.ScaleDurability();
if ( wep.MaxHitPoints > 255 ) wep.MaxHitPoints = 255;
if ( wep.HitPoints > 255 ) wep.HitPoints = 255;
if ( wep.MaxHitPoints > origMaxHP )
{
from.SendLocalizedMessage( 1049084 ); // You successfully use the powder on the item.
--m_Powder.UsesRemaining;
if ( m_Powder.UsesRemaining <= 0 )
{
from.SendLocalizedMessage( 1049086 ); // You have used up your powder of temperament.
m_Powder.Delete();
}
}
else
{
wep.MaxHitPoints = origMaxHP;
wep.HitPoints = origCurHP;
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
}
}
else
{
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
wep.ScaleDurability();
}
}
else
{
from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it.
}
}
else if ( targeted is BaseClothing /*&& (DefBlacksmithy.CraftSystem.CraftItems.SearchForSubclass( targeted.GetType() ) != null)*/ )
{
BaseClothing clothing = (BaseClothing)targeted;
if ( !clothing.CanFortify )
{
from.SendLocalizedMessage( 1049083 ); // You cannot use the powder on that item.
return;
}
if ( clothing.IsChildOf( from.Backpack ) && m_Powder.IsChildOf( from.Backpack ) )
{
int origMaxHP = clothing.MaxHitPoints;
int origCurHP = clothing.HitPoints;
int initMaxHP = Core.AOS ? 255 : clothing.InitMaxHits;
if ( clothing.MaxHitPoints < initMaxHP )
{
int bonus = initMaxHP - clothing.MaxHitPoints;
if ( bonus > 10 )
bonus = 10;
clothing.MaxHitPoints += bonus;
clothing.HitPoints += bonus;
if ( clothing.MaxHitPoints > 255 ) clothing.MaxHitPoints = 255;
if ( clothing.HitPoints > 255 ) clothing.HitPoints = 255;
if ( clothing.MaxHitPoints > origMaxHP )
{
from.SendLocalizedMessage( 1049084 ); // You successfully use the powder on the item.
--m_Powder.UsesRemaining;
if ( m_Powder.UsesRemaining <= 0 )
{
from.SendLocalizedMessage( 1049086 ); // You have used up your powder of temperament.
m_Powder.Delete();
}
}
else
{
clothing.MaxHitPoints = origMaxHP;
clothing.HitPoints = origCurHP;
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
}
}
else
{
from.SendLocalizedMessage( 1049085 ); // The item cannot be improved any further.
from.SendLocalizedMessage( 1049083 ); // You cannot use the powder on that item.
}
}
else

View file

@ -910,6 +910,8 @@ namespace Server
{
if( m_Owner is BaseArmor )
((BaseArmor)m_Owner).UnscaleDurability();
else if( m_Owner is BaseClothing )
((BaseClothing)m_Owner).UnscaleDurability();
}
uint mask = (uint)bitmask;
@ -979,6 +981,8 @@ namespace Server
{
if( m_Owner is BaseArmor )
((BaseArmor)m_Owner).ScaleDurability();
else if( m_Owner is BaseClothing )
((BaseClothing)m_Owner).ScaleDurability();
}
if( m_Owner.Parent is Mobile )

View file

@ -6,6 +6,24 @@ namespace Server.Mobiles
[CorpseName( "a cow corpse" )]
public class Cow : BaseCreature
{
private DateTime m_MilkedOn;
[CommandProperty( AccessLevel.GameMaster )]
public DateTime MilkedOn
{
get { return m_MilkedOn; }
set { m_MilkedOn = value; }
}
private int m_Milk;
[CommandProperty( AccessLevel.GameMaster )]
public int Milk
{
get { return m_Milk; }
set { m_Milk = value; }
}
[Constructable]
public Cow() : base( AIType.AI_Animal, FightMode.Aggressor, 10, 1, 0.2, 0.4 )
{
@ -69,22 +87,53 @@ namespace Server.Mobiles
Animate( 8, 0, 3, true, false, 0 );
}
public Cow(Serial serial) : base(serial)
public bool TryMilk( Mobile from )
{
if ( !from.InLOS( this ) || !from.InRange( Location, 2 ) )
from.SendLocalizedMessage( 1080400 ); // You can not milk the cow from this location.
if ( Controlled && ControlMaster != from )
from.SendLocalizedMessage( 1071182 ); // The cow nimbly escapes your attempts to milk it.
if ( m_Milk == 0 && m_MilkedOn + TimeSpan.FromDays( 1 ) > DateTime.Now )
from.SendLocalizedMessage( 1080198 ); // This cow can not be milked now. Please wait for some time.
else
{
if ( m_Milk == 0 )
m_Milk = 4;
m_MilkedOn = DateTime.Now;
m_Milk--;
return true;
}
return false;
}
public Cow( Serial serial ) : base( serial )
{
}
public override void Serialize(GenericWriter writer)
public override void Serialize( GenericWriter writer )
{
base.Serialize(writer);
base.Serialize( writer );
writer.Write((int) 0);
writer.Write( (int) 1 );
writer.Write( (DateTime) m_MilkedOn );
writer.Write( (int) m_Milk );
}
public override void Deserialize(GenericReader reader)
public override void Deserialize( GenericReader reader )
{
base.Deserialize(reader);
base.Deserialize( reader );
int version = reader.ReadInt();
if ( version > 0 )
{
m_MilkedOn = reader.ReadDateTime();
m_Milk = reader.ReadInt();
}
}
}
}

View file

@ -123,9 +123,9 @@ namespace Server.Mobiles
public virtual bool Validate( Mobile from )
{
if( !IsChildOf( from.Backpack ) )
if( Parent == null )
{
from.SendLocalizedMessage( 1042001 ); // That must be in your pack for you to use it.
from.SayTo( from,1010095 ); // This must be on your person to use.
return false;
}
else if( m_IsRewardItem && !Engines.VeteranRewards.RewardSystem.CheckIsUsableBy( from, this, null ) )

View file

@ -110,6 +110,9 @@ namespace Server.Mobiles
if( Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomBonsaiSeed() );
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(3) );
}

View file

@ -12,6 +12,8 @@ namespace Server.Mobiles
[CorpseName( "a horde minion corpse" )]
public class HordeMinionFamiliar : BaseFamiliar
{
public override bool DisplayWeight{ get { return true; } }
public HordeMinionFamiliar()
{
Name = "a horde minion";
@ -47,6 +49,7 @@ namespace Server.Mobiles
pack = new Backpack();
pack.Movable = false;
pack.Weight = 13.0;
AddItem( pack );
}

View file

@ -88,7 +88,6 @@ namespace Server.Mobiles
public virtual void OfferResurrection( Mobile m )
{
Direction = GetDirectionTo( m );
Say( 501224 ); // Thou hast strayed from the path of virtue, but thou still deservest a second chance.
m.PlaySound( 0x214 );
m.FixedEffect( 0x376A, 10, 16 );

View file

@ -40,6 +40,12 @@ namespace Server.Mobiles
public override bool CheckResurrect( Mobile m )
{
if ( Core.AOS && m.Criminal )
{
Say( 501222 ); // Thou art a criminal. I shall not resurrect thee.
return false;
}
return true;
}

View file

@ -38,6 +38,12 @@ namespace Server.Mobiles
public override bool CheckResurrect( Mobile m )
{
if ( Core.AOS && m.Criminal )
{
Say( 501222 ); // Thou art a criminal. I shall not resurrect thee.
return false;
}
return true;
}

View file

@ -51,6 +51,10 @@ namespace Server.Mobiles
Say( 501223 ); // Thou'rt not a decent and good person. I shall not resurrect thee.
return false;
}
else if ( m.Karma < 0 )
{
Say( 501224 ); // Thou hast strayed from the path of virtue, but thou still deservest a second chance.
}
return true;
}

View file

@ -46,6 +46,10 @@ namespace Server.Mobiles
Say( 501223 ); // Thou'rt not a decent and good person. I shall not resurrect thee.
return false;
}
else if ( m.Karma < 0 )
{
Say( 501224 ); // Thou hast strayed from the path of virtue, but thou still deservest a second chance.
}
return true;
}

View file

@ -44,6 +44,9 @@ namespace Server.Mobiles
PackItem( new Bone( 3 ) );
PackItem( new FertileDirt( Utility.RandomMinMax( 1, 5 ) ) );
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(2) );
switch ( Utility.Random( 4 ) )
{
case 0: PackItem( new DullCopperOre( Utility.RandomMinMax( 1, 10 ) ) ); break;

View file

@ -41,6 +41,9 @@ namespace Server.Mobiles
Karma = -4000;
VirtualArmor = 30;
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(3) );
}
public override void GenerateLoot()

View file

@ -40,6 +40,9 @@ namespace Server.Mobiles
Karma = -11500;
VirtualArmor = 40;
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(1) );
}
public override void GenerateLoot()

View file

@ -5,13 +5,13 @@ using Server.Targeting;
namespace Server.Mobiles
{
[CorpseName( "a cyclops corpse" )]
[CorpseName( "a cyclopean corpse" )]
public class Cyclops : BaseCreature
{
[Constructable]
public Cyclops() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.2, 0.4 )
{
Name = "a cyclops";
Name = "a cyclopean warrior";
Body = 75;
BaseSoundID = 604;

View file

@ -41,6 +41,9 @@ namespace Server.Mobiles
VirtualArmor = 50;
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(2) );
PackItem( new Garlic( 5 ) );
PackItem( new Bandage( 10 ) );
}

View file

@ -15,7 +15,7 @@ namespace Server.Mobiles
[Constructable]
public RestlessSoul() : base( AIType.AI_Melee, FightMode.Closest, 10, 1, 0.4, 0.8 )
{
Name = "a restless soul";
Name = "restless soul";
Body = 0x3CA;
Hue = 0x453;
@ -71,12 +71,12 @@ namespace Server.Mobiles
public override int GetIdleSound()
{
return 0x1BF;
return 0x107;
}
public override int GetAngerSound()
{
return 0x107;
return 0x1BF;
}
public override int GetDeathSound()

View file

@ -64,6 +64,9 @@ namespace Server.Mobiles
PackItem( new ArcaneGem() );
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(4) );
m_NextAbilityTime = DateTime.Now + TimeSpan.FromSeconds( Utility.RandomMinMax( 2, 5 ) );
}

View file

@ -56,6 +56,9 @@ namespace Server.Mobiles
Karma = 5000;
VirtualArmor = 28; // Don't know what it should be
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(1) );
}
public override void GenerateLoot()

View file

@ -63,7 +63,7 @@ namespace Server.Mobiles
public override bool AutoDispel{ get{ return !Controlled; } }
public override int TreasureMapLevel{ get{ return 5; } }
public override int Meat{ get{ return 19; } }
public override int Hides{ get{ return 20; } }
public override int Hides{ get{ return 30; } }
public override HideType HideType{ get{ return HideType.Barbed; } }
public override int Scales{ get{ return 7; } }
public override ScaleType ScaleType{ get{ return ( Body == 12 ? ScaleType.Yellow : ScaleType.Red ); } }

View file

@ -51,6 +51,9 @@ namespace Server.Mobiles
VirtualArmor = 40;
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(3) );
AddItem( new LightSource() );
}

View file

@ -40,6 +40,9 @@ namespace Server.Mobiles
VirtualArmor = 30;
PackArmor( 1, 5 );
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(4) );
}
public override void GenerateLoot()

View file

@ -42,6 +42,9 @@ namespace Server.Mobiles
Karma = 15000;
VirtualArmor = 36;
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(2) );
}
public override void GenerateLoot()

View file

@ -60,6 +60,96 @@ namespace Server.Mobiles
public override int Hides{ get{ return 10; } }
public override HideType HideType{ get{ return HideType.Barbed; } }
public override FoodType FavoriteFood{ get{ return FoodType.Fish; } }
public override bool ShowFameTitle{ get{ return false; } }
public override bool ClickTitle{ get{ return false; } }
public override bool PropertyTitle{ get{ return false; } }
public override void OnCombatantChange()
{
if ( Combatant == null && !IsBodyMod && !Controlled && m_DisguiseTimer == null && Utility.RandomBool() )
m_DisguiseTimer = Timer.DelayCall( TimeSpan.FromSeconds( Utility.RandomMinMax( 15, 30 ) ), new TimerCallback( Disguise ) );
}
public override bool OnBeforeDeath()
{
RemoveDisguise();
return base.OnBeforeDeath();
}
#region Disguise
private Timer m_DisguiseTimer;
public void Disguise()
{
if ( Combatant != null || IsBodyMod || Controlled )
return;
FixedEffect( 0x376A, 8, 32 );
PlaySound( 0x1FE );
Female = Utility.RandomBool();
if ( Female )
{
BodyMod = 0x191;
Name = NameList.RandomName( "female" );
}
else
{
BodyMod = 0x190;
Name = NameList.RandomName( "male" );
}
Title = "the mystic llama herder";
Hue = Race.Human.RandomSkinHue();
HairItemID = Race.Human.RandomHair( this );
HairHue = Race.Human.RandomHairHue();
FacialHairItemID = Race.Human.RandomFacialHair( this );
FacialHairHue = HairHue;
switch ( Utility.Random( 4 ) )
{
case 0: AddItem( new Shoes( Utility.RandomNeutralHue() ) ); break;
case 1: AddItem( new Boots( Utility.RandomNeutralHue() ) ); break;
case 2: AddItem( new Sandals( Utility.RandomNeutralHue() ) ); break;
case 3: AddItem( new ThighBoots( Utility.RandomNeutralHue() ) ); break;
}
AddItem( new Robe( Utility.RandomNondyedHue() ) );
m_DisguiseTimer = null;
m_DisguiseTimer = Timer.DelayCall( TimeSpan.FromSeconds( 75 ), new TimerCallback( RemoveDisguise ) );
}
public void RemoveDisguise()
{
if ( !IsBodyMod )
return;
Name = "a bake kitsune";
Title = null;
BodyMod = 0;
Hue = 0;
HairItemID = 0;
HairHue = 0;
FacialHairItemID = 0;
FacialHairHue = 0;
DeleteItemOnLayer( Layer.OuterTorso );
DeleteItemOnLayer( Layer.Shoes );
m_DisguiseTimer = null;
}
public void DeleteItemOnLayer( Layer layer )
{
Item item = FindItemOnLayer( layer );
if ( item != null )
item.Delete();
}
#endregion
public override void OnGaveMeleeAttack( Mobile defender )
{
@ -180,6 +270,8 @@ namespace Server.Mobiles
SetResistance( ResistanceType.Poison, 40, 60 );
SetResistance( ResistanceType.Energy, 40, 60 );
}
Timer.DelayCall( TimeSpan.Zero, new TimerCallback( RemoveDisguise ) );
}
}
}

View file

@ -51,10 +51,10 @@ namespace Server.Mobiles
case 2: PackItem( new Axle() ); break;
}
}
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(4) );
}
public override void GenerateLoot()
{
AddLoot( LootPack.Meager );
@ -126,11 +126,10 @@ namespace Server.Mobiles
if ( m.Alive )
{
int damageGiven = AOS.Damage( m, from, 5, 0, 0, 0, 0, 100 );
from.Hits += damageGiven;
}
else
{
{
EndLifeDrain( m );
}
}
@ -165,7 +164,7 @@ namespace Server.Mobiles
}
if ( amt > 0 )
{
SpillAcid( target, amt, "slime" );
SpillAcid( target, amt );
from.SendLocalizedMessage( 1070820 );
if ( Mana > 14)
Mana -= 15;
@ -175,6 +174,11 @@ namespace Server.Mobiles
base.OnDamage( amount, from, willKill );
}
public override Item NewHarmfulItem()
{
return new AcidSlime( TimeSpan.FromSeconds(10), 5, 10 );
}
public Kappa( Serial serial ) : base( serial )
{
}

View file

@ -47,7 +47,8 @@ namespace Server.Mobiles
Fame = 8500;
Karma = -8500;
if ( Core.ML && Utility.RandomDouble() < .33 )
PackItem( Engines.Plants.Seed.RandomPeculiarSeed(1) );
switch( Utility.Random( 10 ) )
{

View file

@ -297,7 +297,7 @@ namespace Server.Mobiles
{
Container bank = from.FindBankNoCreate();
if ( bank != null && bank.ConsumeTotal( typeof( Gold ), 30 ) )
if ( ( from.Backpack != null && from.Backpack.ConsumeTotal( typeof( Gold ), 30 ) ) || ( bank != null && bank.ConsumeTotal( typeof( Gold ), 30 ) ) )
{
pet.ControlTarget = null;
pet.ControlOrder = OrderType.Stay;

View file

@ -1004,6 +1004,8 @@ namespace Server.Multis
return HasSecureAccess( from, ((ISecurable)item).Level );
else if ( item is Container )
return IsCoOwner( from );
else if ( item.Stackable )
return true;
else if ( item is BaseLight )
return IsFriend( from );
else if ( item is PotionKeg )
@ -1405,7 +1407,7 @@ namespace Server.Multis
}
else
{
m_Trash.MoveToWorld( from.Location, from.Map );
from.SendLocalizedMessage( 502117 ); // You already have a trash barrel!
}
}
@ -3417,7 +3419,7 @@ namespace Server.Multis
}
else
{
if ( targeted is VendorRentalContract || ( targeted is Container && ((Container)targeted).FindItemByType( typeof( VendorRentalContract ) ) != null ) )
if ( targeted is VendorRentalContract )
{
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1062392 ); // You must double click the contract in your pack to lock it down.
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 501732 ); // I cannot lock this down!
@ -3475,7 +3477,7 @@ namespace Server.Multis
}
else
{
if ( targeted is VendorRentalContract || ( targeted is Container && ((Container)targeted).FindItemByType( typeof( VendorRentalContract ) ) != null ) )
if ( targeted is VendorRentalContract )
{
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1062392 ); // You must double click the contract in your pack to lock it down.
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 501732 ); // I cannot lock this down!

View file

@ -122,6 +122,16 @@ namespace Server.SkillHandlers
return String.Format( "<div align=right>{0}%</div>", val );
}
#region Mondain's Legacy
private static string FormatDamage( int min, int max )
{
if ( min <= 0 || max <= 0 )
return "<div align=right>---</div>";
return String.Format( "<div align=right>{0}-{1}</div>", min, max );
}
#endregion
private const int LabelColor = 0x24E5;
public AnimalLoreGump( BaseCreature c ) : base( 250, 50 )
@ -255,6 +265,14 @@ namespace Server.SkillHandlers
AddHtmlLocalized( 153, 240, 160, 18, 1061650, LabelColor, false, false ); // Energy
AddHtml( 320, 240, 35, 18, FormatElement( c.EnergyDamage ), false, false );
#region Mondain's Legacy
if ( Core.ML )
{
AddHtmlLocalized( 153, 258, 160, 18, 1076750, LabelColor, false, false ); // Base Damage
AddHtml( 300, 258, 55, 18, FormatDamage( c.DamageMin, c.DamageMax ), false, false );
}
#endregion
AddButton( 340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1 );
AddButton( 317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1 );
}
@ -278,8 +296,18 @@ namespace Server.SkillHandlers
AddHtmlLocalized( 153, 222, 160, 18, 1044061, LabelColor, false, false ); // Anatomy
AddHtml( 320, 222, 35, 18, FormatSkill( c, SkillName.Anatomy ), false, false );
AddHtmlLocalized( 153, 240, 160, 18, 1044090, LabelColor, false, false ); // Poisoning
AddHtml( 320, 240, 35, 18, FormatSkill( c, SkillName.Poisoning ), false, false );
#region Mondain's Legacy
if ( c is CuSidhe )
{
AddHtmlLocalized( 153, 240, 160, 18, 1044077, LabelColor, false, false ); // Healing
AddHtml( 320, 240, 35, 18, FormatSkill( c, SkillName.Healing ), false, false );
}
else
{
AddHtmlLocalized( 153, 240, 160, 18, 1044090, LabelColor, false, false ); // Poisoning
AddHtml( 320, 240, 35, 18, FormatSkill( c, SkillName.Poisoning ), false, false );
}
#endregion
AddImage( 128, 260, 2086 );
AddHtmlLocalized( 147, 258, 160, 18, 3001032, 200, false, false ); // Lore & Knowledge

View file

@ -20,7 +20,7 @@ namespace Server.SkillHandlers
src.SendLocalizedMessage( 500819 );//Where will you search?
src.Target = new InternalTarget();
return TimeSpan.FromSeconds( 1.0 );
return TimeSpan.FromSeconds( 6.0 );
}
private class InternalTarget : Target

View file

@ -150,10 +150,10 @@ namespace Server.SkillHandlers
m_Thief.SendLocalizedMessage( 1010586 ); // YOU STOLE THE SIGIL!!! (woah, calm down now)
if ( sig.LastMonolith != null )
if ( sig.LastMonolith != null && sig.LastMonolith.Sigil != null ) {
sig.LastMonolith.Sigil = null;
sig.LastStolen = DateTime.Now;
sig.LastStolen = DateTime.Now;
}
return sig;
}

View file

@ -4,6 +4,7 @@ using Server.Targeting;
using Server.Network;
using Server.Misc;
using Server.Items;
using Server.Mobiles;
namespace Server.Spells.Fifth
{
@ -183,7 +184,9 @@ namespace Server.Spells.Fifth
p = Poison.Regular;
}
m.ApplyPoison( m_Caster, p );
if ( m.ApplyPoison( m_Caster, p ) == ApplyPoisonResult.Poisoned )
if ( SpellHelper.CanRevealCaster( m ) )
m_Caster.RevealingAction();
}
public override bool OnMoveOver( Mobile m )

View file

@ -4,6 +4,7 @@ using Server.Targeting;
using Server.Network;
using Server.Misc;
using Server.Items;
using Server.Mobiles;
namespace Server.Spells.Fourth
{
@ -184,6 +185,9 @@ namespace Server.Spells.Fourth
{
if ( Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && SpellHelper.ValidIndirectTarget( m_Caster, m ) && m_Caster.CanBeHarmful( m, false ) )
{
if ( SpellHelper.CanRevealCaster( m ) )
m_Caster.RevealingAction();
m_Caster.DoHarmful( m );
int damage = m_Damage;
@ -257,6 +261,9 @@ namespace Server.Spells.Fourth
while ( m_Queue.Count > 0 )
{
Mobile m = (Mobile)m_Queue.Dequeue();
if ( SpellHelper.CanRevealCaster( m ) )
caster.RevealingAction();
caster.DoHarmful( m );

View file

@ -62,9 +62,12 @@ namespace Server.Spells.Necromancy
if( map != null )
{
List<Mobile> targets = new List<Mobile>();
if ( Caster.CanBeHarmful(m, false ) )
targets.Add( m );
foreach( Mobile targ in m.GetMobilesInRange( 2 ) )
if( (Caster == targ || m == targ || SpellHelper.ValidIndirectTarget( Caster, targ )) && Caster.CanBeHarmful( targ, false ) )
if( ( targ != Caster ) && ( SpellHelper.ValidIndirectTarget( Caster, targ ) && Caster.CanBeHarmful( targ, false) ) )
targets.Add( targ );
for( int i = 0; i < targets.Count; ++i )

View file

@ -120,8 +120,7 @@ namespace Server.Spells.Ninjitsu
{
m_Owner.FinishSequence();
if ( !from.CheckSkill( SkillName.Hiding, 0.0, 100.0 ) ) //TODO: Hiding check or stealth check?
from.RevealingAction();
Server.SkillHandlers.Stealth.OnUse( from );
}
}
}

View file

@ -3,6 +3,7 @@ using Server.Targeting;
using Server.Items;
using Server.Network;
using Server.Misc;
using Server.Mobiles;
namespace Server.Spells.Sixth
{
@ -161,6 +162,9 @@ namespace Server.Spells.Sixth
{
if ( Visible && m_Caster != null && (!Core.AOS || m != m_Caster) && SpellHelper.ValidIndirectTarget( m_Caster, m ) && m_Caster.CanBeHarmful( m, false ) )
{
if ( SpellHelper.CanRevealCaster( m ) )
m_Caster.RevealingAction();
m_Caster.DoHarmful( m );
double duration;

View file

@ -69,18 +69,14 @@ namespace Server.Spells.Spellweaving
if ( house != null)
if ( !house.IsFriend ( Caster ) )
return;
if( !SpellHelper.FindValidSpawnLocation( map, ref p, m_MobileTarg ) )
if (m != null) //say "Target can not be seen" if you target directly a mobile, like in OSI
{
Caster.SendLocalizedMessage( 500237 ); // Target can not be seen.
}
else if ( map == null || !map.CanSpawnMobile( p.X, p.Y, p.Z ) )
{
Caster.SendLocalizedMessage( 501942 ); // That location is blocked.
}
//say "Target can not be seen" if you target directly a mobile, like in OSI
if (m != null)
{
Caster.SendLocalizedMessage(500237); // Target can not be seen.
}
else if( SpellHelper.CheckTown( p, Caster ) && (m_MobileTarg ? CheckHSequence( m ) : CheckSequence()) )
{
TimeSpan duration = TimeSpan.FromSeconds( Caster.Skills.Spellweaving.Value/24 + 25 + FocusLevel*2 );
@ -89,8 +85,7 @@ namespace Server.Spells.Spellweaving
m = null;
NatureFury nf = new NatureFury( m );
if ( !Caster.InLOS ( p ) )
return;
BaseCreature.Summon( nf, false, Caster, p , 0x5CB, duration );
Timer t = null;
@ -112,8 +107,7 @@ namespace Server.Spells.Spellweaving
{
private NatureFurySpell m_Owner;
public InternalTarget( NatureFurySpell owner )
: base( 10, true, TargetFlags.None )
public InternalTarget( NatureFurySpell owner ) : base( 10, true, TargetFlags.None )
{
m_Owner = owner;
CheckLOS = true;
@ -124,8 +118,6 @@ namespace Server.Spells.Spellweaving
if( o is IPoint3D )
m_Owner.Target( (IPoint3D)o );
}
protected override void OnTargetFinish( Mobile from )
{
if( m_Owner != null )

View file

@ -95,6 +95,16 @@ namespace Server.Spells.Third
}
m.PlaySound( 0x1FE );
IPooledEnumerable eable = m.GetItemsInRange( 0 );
foreach ( Item item in eable )
{
if ( item is ParalyzeFieldSpell.InternalItem || item is PoisonFieldSpell.InternalItem || item is FireFieldItem )
item.OnMoveOver( m );
}
eable.Free();
}
FinishSequence();