Formats UO Content (#201)
This commit is contained in:
parent
86b7b3aed1
commit
ad3775c4d7
3249 changed files with 431083 additions and 440981 deletions
|
|
@ -1,196 +1,197 @@
|
|||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class BaseTreasureChest : LockableContainer
|
||||
{
|
||||
public enum TreasureLevel
|
||||
{
|
||||
Level1,
|
||||
Level2,
|
||||
Level3,
|
||||
Level4,
|
||||
Level5,
|
||||
Level6
|
||||
}
|
||||
|
||||
private TreasureResetTimer m_ResetTimer;
|
||||
|
||||
public BaseTreasureChest(int itemID, TreasureLevel level = TreasureLevel.Level2)
|
||||
: base(itemID)
|
||||
{
|
||||
Level = level;
|
||||
Locked = true;
|
||||
Movable = false;
|
||||
|
||||
SetLockLevel();
|
||||
GenerateTreasure();
|
||||
}
|
||||
|
||||
public BaseTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TreasureLevel Level { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public short MaxSpawnTime { get; set; } = 60;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public short MinSpawnTime { get; set; } = 10;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override bool Locked
|
||||
{
|
||||
get => base.Locked;
|
||||
set
|
||||
{
|
||||
if (base.Locked != value)
|
||||
{
|
||||
base.Locked = value;
|
||||
|
||||
if (!value)
|
||||
StartResetTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsDecoContainer => false;
|
||||
|
||||
public override string DefaultName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Locked)
|
||||
return "a locked treasure chest";
|
||||
|
||||
return "a treasure chest";
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0);
|
||||
writer.Write((byte)Level);
|
||||
writer.Write(MinSpawnTime);
|
||||
writer.Write(MaxSpawnTime);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
Level = (TreasureLevel)reader.ReadByte();
|
||||
MinSpawnTime = reader.ReadShort();
|
||||
MaxSpawnTime = reader.ReadShort();
|
||||
|
||||
if (!Locked)
|
||||
StartResetTimer();
|
||||
}
|
||||
|
||||
protected virtual void SetLockLevel()
|
||||
{
|
||||
RequiredSkill = Level switch
|
||||
{
|
||||
TreasureLevel.Level1 => LockLevel = 5,
|
||||
TreasureLevel.Level2 => LockLevel = 20,
|
||||
TreasureLevel.Level3 => LockLevel = 50,
|
||||
TreasureLevel.Level4 => LockLevel = 70,
|
||||
TreasureLevel.Level5 => LockLevel = 90,
|
||||
TreasureLevel.Level6 => LockLevel = 100,
|
||||
_ => RequiredSkill
|
||||
};
|
||||
}
|
||||
|
||||
private void StartResetTimer()
|
||||
{
|
||||
if (m_ResetTimer == null)
|
||||
m_ResetTimer = new TreasureResetTimer(this);
|
||||
else
|
||||
m_ResetTimer.Delay = TimeSpan.FromMinutes(Utility.Random(MinSpawnTime, MaxSpawnTime));
|
||||
|
||||
m_ResetTimer.Start();
|
||||
}
|
||||
|
||||
protected virtual void GenerateTreasure()
|
||||
{
|
||||
int MinGold = 1;
|
||||
int MaxGold = 2;
|
||||
|
||||
switch (Level)
|
||||
{
|
||||
case TreasureLevel.Level1:
|
||||
MinGold = 100;
|
||||
MaxGold = 300;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level2:
|
||||
MinGold = 300;
|
||||
MaxGold = 600;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level3:
|
||||
MinGold = 600;
|
||||
MaxGold = 900;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level4:
|
||||
MinGold = 900;
|
||||
MaxGold = 1200;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level5:
|
||||
MinGold = 1200;
|
||||
MaxGold = 5000;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level6:
|
||||
MinGold = 5000;
|
||||
MaxGold = 9000;
|
||||
break;
|
||||
}
|
||||
|
||||
DropItem(new Gold(MinGold, MaxGold));
|
||||
}
|
||||
|
||||
public void ClearContents()
|
||||
{
|
||||
for (int i = Items.Count - 1; i >= 0; --i)
|
||||
if (i < Items.Count)
|
||||
Items[i].Delete();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
if (m_ResetTimer != null)
|
||||
if (m_ResetTimer.Running)
|
||||
m_ResetTimer.Stop();
|
||||
|
||||
Locked = true;
|
||||
ClearContents();
|
||||
GenerateTreasure();
|
||||
}
|
||||
|
||||
private class TreasureResetTimer : Timer
|
||||
{
|
||||
private readonly BaseTreasureChest m_Chest;
|
||||
|
||||
public TreasureResetTimer(BaseTreasureChest chest) : base(
|
||||
TimeSpan.FromMinutes(Utility.Random(chest.MinSpawnTime, chest.MaxSpawnTime)))
|
||||
{
|
||||
m_Chest = chest;
|
||||
Priority = TimerPriority.OneMinute;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Chest.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class BaseTreasureChest : LockableContainer
|
||||
{
|
||||
public enum TreasureLevel
|
||||
{
|
||||
Level1,
|
||||
Level2,
|
||||
Level3,
|
||||
Level4,
|
||||
Level5,
|
||||
Level6
|
||||
}
|
||||
|
||||
private TreasureResetTimer m_ResetTimer;
|
||||
|
||||
public BaseTreasureChest(int itemID, TreasureLevel level = TreasureLevel.Level2)
|
||||
: base(itemID)
|
||||
{
|
||||
Level = level;
|
||||
Locked = true;
|
||||
Movable = false;
|
||||
|
||||
SetLockLevel();
|
||||
GenerateTreasure();
|
||||
}
|
||||
|
||||
public BaseTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TreasureLevel Level { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public short MaxSpawnTime { get; set; } = 60;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public short MinSpawnTime { get; set; } = 10;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override bool Locked
|
||||
{
|
||||
get => base.Locked;
|
||||
set
|
||||
{
|
||||
if (base.Locked != value)
|
||||
{
|
||||
base.Locked = value;
|
||||
|
||||
if (!value)
|
||||
StartResetTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsDecoContainer => false;
|
||||
|
||||
public override string DefaultName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Locked)
|
||||
return "a locked treasure chest";
|
||||
|
||||
return "a treasure chest";
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0);
|
||||
writer.Write((byte)Level);
|
||||
writer.Write(MinSpawnTime);
|
||||
writer.Write(MaxSpawnTime);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
Level = (TreasureLevel)reader.ReadByte();
|
||||
MinSpawnTime = reader.ReadShort();
|
||||
MaxSpawnTime = reader.ReadShort();
|
||||
|
||||
if (!Locked)
|
||||
StartResetTimer();
|
||||
}
|
||||
|
||||
protected virtual void SetLockLevel()
|
||||
{
|
||||
RequiredSkill = Level switch
|
||||
{
|
||||
TreasureLevel.Level1 => LockLevel = 5,
|
||||
TreasureLevel.Level2 => LockLevel = 20,
|
||||
TreasureLevel.Level3 => LockLevel = 50,
|
||||
TreasureLevel.Level4 => LockLevel = 70,
|
||||
TreasureLevel.Level5 => LockLevel = 90,
|
||||
TreasureLevel.Level6 => LockLevel = 100,
|
||||
_ => RequiredSkill
|
||||
};
|
||||
}
|
||||
|
||||
private void StartResetTimer()
|
||||
{
|
||||
if (m_ResetTimer == null)
|
||||
m_ResetTimer = new TreasureResetTimer(this);
|
||||
else
|
||||
m_ResetTimer.Delay = TimeSpan.FromMinutes(Utility.Random(MinSpawnTime, MaxSpawnTime));
|
||||
|
||||
m_ResetTimer.Start();
|
||||
}
|
||||
|
||||
protected virtual void GenerateTreasure()
|
||||
{
|
||||
var MinGold = 1;
|
||||
var MaxGold = 2;
|
||||
|
||||
switch (Level)
|
||||
{
|
||||
case TreasureLevel.Level1:
|
||||
MinGold = 100;
|
||||
MaxGold = 300;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level2:
|
||||
MinGold = 300;
|
||||
MaxGold = 600;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level3:
|
||||
MinGold = 600;
|
||||
MaxGold = 900;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level4:
|
||||
MinGold = 900;
|
||||
MaxGold = 1200;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level5:
|
||||
MinGold = 1200;
|
||||
MaxGold = 5000;
|
||||
break;
|
||||
|
||||
case TreasureLevel.Level6:
|
||||
MinGold = 5000;
|
||||
MaxGold = 9000;
|
||||
break;
|
||||
}
|
||||
|
||||
DropItem(new Gold(MinGold, MaxGold));
|
||||
}
|
||||
|
||||
public void ClearContents()
|
||||
{
|
||||
for (var i = Items.Count - 1; i >= 0; --i)
|
||||
if (i < Items.Count)
|
||||
Items[i].Delete();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
if (m_ResetTimer != null)
|
||||
if (m_ResetTimer.Running)
|
||||
m_ResetTimer.Stop();
|
||||
|
||||
Locked = true;
|
||||
ClearContents();
|
||||
GenerateTreasure();
|
||||
}
|
||||
|
||||
private class TreasureResetTimer : Timer
|
||||
{
|
||||
private readonly BaseTreasureChest m_Chest;
|
||||
|
||||
public TreasureResetTimer(BaseTreasureChest chest) : base(
|
||||
TimeSpan.FromMinutes(Utility.Random(chest.MinSpawnTime, chest.MaxSpawnTime))
|
||||
)
|
||||
{
|
||||
m_Chest = chest;
|
||||
Priority = TimerPriority.OneMinute;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Chest.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,389 +1,389 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
[Furniture]
|
||||
[Flippable(0x2815, 0x2816)]
|
||||
public class TallCabinet : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public TallCabinet() : base(0x2815) => Weight = 1.0;
|
||||
|
||||
public TallCabinet(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x2817, 0x2818)]
|
||||
public class ShortCabinet : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public ShortCabinet() : base(0x2817) => Weight = 1.0;
|
||||
|
||||
public ShortCabinet(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x2857, 0x2858)]
|
||||
public class RedArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public RedArmoire() : base(0x2857) => Weight = 1.0;
|
||||
|
||||
public RedArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x285D, 0x285E)]
|
||||
public class CherryArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public CherryArmoire() : base(0x285D) => Weight = 1.0;
|
||||
|
||||
public CherryArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x285B, 0x285C)]
|
||||
public class MapleArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public MapleArmoire() : base(0x285B) => Weight = 1.0;
|
||||
|
||||
public MapleArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x2859, 0x285A)]
|
||||
public class ElegantArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public ElegantArmoire() : base(0x2859) => Weight = 1.0;
|
||||
|
||||
public ElegantArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa97, 0xa99, 0xa98, 0xa9a, 0xa9b, 0xa9c)]
|
||||
public class FullBookcase : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public FullBookcase() : base(0xA97) => Weight = 1.0;
|
||||
|
||||
public FullBookcase(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa9d, 0xa9e)]
|
||||
public class EmptyBookcase : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public EmptyBookcase() : base(0xA9D)
|
||||
{
|
||||
}
|
||||
|
||||
public EmptyBookcase(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(1); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
|
||||
if (version == 0 && Weight == 1.0)
|
||||
Weight = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa2c, 0xa34)]
|
||||
public class Drawer : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public Drawer() : base(0xA2C) => Weight = 1.0;
|
||||
|
||||
public Drawer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa30, 0xa38)]
|
||||
public class FancyDrawer : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public FancyDrawer() : base(0xA30) => Weight = 1.0;
|
||||
|
||||
public FancyDrawer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa4f, 0xa53)]
|
||||
public class Armoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public Armoire() : base(0xA4F) => Weight = 1.0;
|
||||
|
||||
public Armoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DisplayTo(Mobile m)
|
||||
{
|
||||
if (DynamicFurniture.Open(this, m))
|
||||
base.DisplayTo(m);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
|
||||
DynamicFurniture.Close(this);
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa4d, 0xa51)]
|
||||
public class FancyArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public FancyArmoire() : base(0xA4D) => Weight = 1.0;
|
||||
|
||||
public FancyArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DisplayTo(Mobile m)
|
||||
{
|
||||
if (DynamicFurniture.Open(this, m))
|
||||
base.DisplayTo(m);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
int version = reader.ReadInt();
|
||||
|
||||
DynamicFurniture.Close(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class DynamicFurniture
|
||||
{
|
||||
private static readonly Dictionary<Container, Timer> m_Table = new Dictionary<Container, Timer>();
|
||||
|
||||
public static bool Open(Container c, Mobile m)
|
||||
{
|
||||
if (m_Table.ContainsKey(c))
|
||||
{
|
||||
c.SendRemovePacket();
|
||||
Close(c);
|
||||
c.Delta(ItemDelta.Update);
|
||||
c.ProcessDelta();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c is Armoire || c is FancyArmoire)
|
||||
{
|
||||
Timer t = new FurnitureTimer(c, m);
|
||||
t.Start();
|
||||
m_Table[c] = t;
|
||||
|
||||
c.ItemID = c.ItemID switch
|
||||
{
|
||||
0xA4D => 0xA4C,
|
||||
0xA4F => 0xA4E,
|
||||
0xA51 => 0xA50,
|
||||
0xA53 => 0xA52,
|
||||
_ => c.ItemID
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Close(Container c)
|
||||
{
|
||||
if (m_Table.TryGetValue(c, out Timer t))
|
||||
{
|
||||
t.Stop();
|
||||
m_Table.Remove(c);
|
||||
}
|
||||
|
||||
if (c is Armoire || c is FancyArmoire)
|
||||
c.ItemID = c.ItemID switch
|
||||
{
|
||||
0xA4C => 0xA4D,
|
||||
0xA4E => 0xA4F,
|
||||
0xA50 => 0xA51,
|
||||
0xA52 => 0xA53,
|
||||
_ => c.ItemID
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class FurnitureTimer : Timer
|
||||
{
|
||||
private readonly Container m_Container;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public FurnitureTimer(Container c, Mobile m) : base(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5))
|
||||
{
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
|
||||
m_Container = c;
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Mobile.Map != m_Container.Map || !m_Mobile.InRange(m_Container.GetWorldLocation(), 3))
|
||||
DynamicFurniture.Close(m_Container);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
[Furniture]
|
||||
[Flippable(0x2815, 0x2816)]
|
||||
public class TallCabinet : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public TallCabinet() : base(0x2815) => Weight = 1.0;
|
||||
|
||||
public TallCabinet(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x2817, 0x2818)]
|
||||
public class ShortCabinet : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public ShortCabinet() : base(0x2817) => Weight = 1.0;
|
||||
|
||||
public ShortCabinet(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x2857, 0x2858)]
|
||||
public class RedArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public RedArmoire() : base(0x2857) => Weight = 1.0;
|
||||
|
||||
public RedArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x285D, 0x285E)]
|
||||
public class CherryArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public CherryArmoire() : base(0x285D) => Weight = 1.0;
|
||||
|
||||
public CherryArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x285B, 0x285C)]
|
||||
public class MapleArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public MapleArmoire() : base(0x285B) => Weight = 1.0;
|
||||
|
||||
public MapleArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0x2859, 0x285A)]
|
||||
public class ElegantArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public ElegantArmoire() : base(0x2859) => Weight = 1.0;
|
||||
|
||||
public ElegantArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa97, 0xa99, 0xa98, 0xa9a, 0xa9b, 0xa9c)]
|
||||
public class FullBookcase : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public FullBookcase() : base(0xA97) => Weight = 1.0;
|
||||
|
||||
public FullBookcase(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa9d, 0xa9e)]
|
||||
public class EmptyBookcase : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public EmptyBookcase() : base(0xA9D)
|
||||
{
|
||||
}
|
||||
|
||||
public EmptyBookcase(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(1); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
|
||||
if (version == 0 && Weight == 1.0)
|
||||
Weight = -1;
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa2c, 0xa34)]
|
||||
public class Drawer : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public Drawer() : base(0xA2C) => Weight = 1.0;
|
||||
|
||||
public Drawer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa30, 0xa38)]
|
||||
public class FancyDrawer : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public FancyDrawer() : base(0xA30) => Weight = 1.0;
|
||||
|
||||
public FancyDrawer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa4f, 0xa53)]
|
||||
public class Armoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public Armoire() : base(0xA4F) => Weight = 1.0;
|
||||
|
||||
public Armoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DisplayTo(Mobile m)
|
||||
{
|
||||
if (DynamicFurniture.Open(this, m))
|
||||
base.DisplayTo(m);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
|
||||
DynamicFurniture.Close(this);
|
||||
}
|
||||
}
|
||||
|
||||
[Furniture]
|
||||
[Flippable(0xa4d, 0xa51)]
|
||||
public class FancyArmoire : BaseContainer
|
||||
{
|
||||
[Constructible]
|
||||
public FancyArmoire() : base(0xA4D) => Weight = 1.0;
|
||||
|
||||
public FancyArmoire(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DisplayTo(Mobile m)
|
||||
{
|
||||
if (DynamicFurniture.Open(this, m))
|
||||
base.DisplayTo(m);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
var version = reader.ReadInt();
|
||||
|
||||
DynamicFurniture.Close(this);
|
||||
}
|
||||
}
|
||||
|
||||
public class DynamicFurniture
|
||||
{
|
||||
private static readonly Dictionary<Container, Timer> m_Table = new Dictionary<Container, Timer>();
|
||||
|
||||
public static bool Open(Container c, Mobile m)
|
||||
{
|
||||
if (m_Table.ContainsKey(c))
|
||||
{
|
||||
c.SendRemovePacket();
|
||||
Close(c);
|
||||
c.Delta(ItemDelta.Update);
|
||||
c.ProcessDelta();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (c is Armoire || c is FancyArmoire)
|
||||
{
|
||||
Timer t = new FurnitureTimer(c, m);
|
||||
t.Start();
|
||||
m_Table[c] = t;
|
||||
|
||||
c.ItemID = c.ItemID switch
|
||||
{
|
||||
0xA4D => 0xA4C,
|
||||
0xA4F => 0xA4E,
|
||||
0xA51 => 0xA50,
|
||||
0xA53 => 0xA52,
|
||||
_ => c.ItemID
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Close(Container c)
|
||||
{
|
||||
if (m_Table.TryGetValue(c, out var t))
|
||||
{
|
||||
t.Stop();
|
||||
m_Table.Remove(c);
|
||||
}
|
||||
|
||||
if (c is Armoire || c is FancyArmoire)
|
||||
c.ItemID = c.ItemID switch
|
||||
{
|
||||
0xA4C => 0xA4D,
|
||||
0xA4E => 0xA4F,
|
||||
0xA50 => 0xA51,
|
||||
0xA52 => 0xA53,
|
||||
_ => c.ItemID
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class FurnitureTimer : Timer
|
||||
{
|
||||
private readonly Container m_Container;
|
||||
private readonly Mobile m_Mobile;
|
||||
|
||||
public FurnitureTimer(Container c, Mobile m) : base(TimeSpan.FromSeconds(0.5), TimeSpan.FromSeconds(0.5))
|
||||
{
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
|
||||
m_Container = c;
|
||||
m_Mobile = m;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if (m_Mobile.Map != m_Container.Map || !m_Mobile.InRange(m_Container.GetWorldLocation(), 3))
|
||||
DynamicFurniture.Close(m_Container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,318 +1,325 @@
|
|||
using System;
|
||||
using Server.Engines.Craft;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public abstract class LockableContainer : TrappableContainer, ILockable, ILockpickable, ICraftable, IShipwreckedItem
|
||||
{
|
||||
private bool m_Locked;
|
||||
|
||||
public LockableContainer(int itemID) : base(itemID) => MaxLockLevel = 100;
|
||||
|
||||
public LockableContainer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool TrapOnOpen => !TrapOnLockpick;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool TrapOnLockpick { get; set; }
|
||||
|
||||
public override bool DisplaysContent => !m_Locked;
|
||||
|
||||
public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool,
|
||||
CraftItem craftItem, int resHue)
|
||||
{
|
||||
if (from.CheckSkill(SkillName.Tinkering, -5.0, 15.0))
|
||||
{
|
||||
from.SendLocalizedMessage(500636); // Your tinker skill was sufficient to make the item lockable.
|
||||
|
||||
Key key = new Key(KeyType.Copper, Key.RandomValue());
|
||||
|
||||
KeyValue = key.KeyValue;
|
||||
DropItem(key);
|
||||
|
||||
double tinkering = from.Skills.Tinkering.Value;
|
||||
int level = (int)(tinkering * 0.8);
|
||||
|
||||
RequiredSkill = level - 4;
|
||||
LockLevel = level - 14;
|
||||
MaxLockLevel = level + 35;
|
||||
|
||||
if (LockLevel == 0)
|
||||
LockLevel = -1;
|
||||
else if (LockLevel > 95)
|
||||
LockLevel = 95;
|
||||
|
||||
if (RequiredSkill > 95)
|
||||
RequiredSkill = 95;
|
||||
|
||||
if (MaxLockLevel > 95)
|
||||
MaxLockLevel = 95;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(500637); // Your tinker skill was insufficient to make the item lockable.
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public virtual bool Locked
|
||||
{
|
||||
get => m_Locked;
|
||||
set
|
||||
{
|
||||
m_Locked = value;
|
||||
|
||||
if (m_Locked)
|
||||
Picker = null;
|
||||
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public uint KeyValue { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Mobile Picker { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int MaxLockLevel { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int LockLevel { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int RequiredSkill { get; set; }
|
||||
|
||||
public virtual void LockPick(Mobile from)
|
||||
{
|
||||
Locked = false;
|
||||
Picker = from;
|
||||
|
||||
if (TrapOnLockpick && ExecuteTrap(from)) TrapOnLockpick = false;
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool IsShipwreckedItem { get; set; }
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(6); // version
|
||||
|
||||
writer.Write(IsShipwreckedItem);
|
||||
|
||||
writer.Write(TrapOnLockpick);
|
||||
|
||||
writer.Write(RequiredSkill);
|
||||
|
||||
writer.Write(MaxLockLevel);
|
||||
|
||||
writer.Write(KeyValue);
|
||||
writer.Write(LockLevel);
|
||||
writer.Write(m_Locked);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 6:
|
||||
{
|
||||
IsShipwreckedItem = reader.ReadBool();
|
||||
|
||||
goto case 5;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
TrapOnLockpick = reader.ReadBool();
|
||||
|
||||
goto case 4;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
RequiredSkill = reader.ReadInt();
|
||||
|
||||
goto case 3;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
MaxLockLevel = reader.ReadInt();
|
||||
|
||||
goto case 2;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
KeyValue = reader.ReadUInt();
|
||||
|
||||
goto case 1;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
LockLevel = reader.ReadInt();
|
||||
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
if (version < 3)
|
||||
MaxLockLevel = 100;
|
||||
|
||||
if (version < 4)
|
||||
{
|
||||
if (MaxLockLevel - LockLevel == 40)
|
||||
{
|
||||
RequiredSkill = LockLevel + 6;
|
||||
LockLevel = RequiredSkill - 10;
|
||||
MaxLockLevel = RequiredSkill + 39;
|
||||
}
|
||||
else
|
||||
{
|
||||
RequiredSkill = LockLevel;
|
||||
}
|
||||
}
|
||||
|
||||
m_Locked = reader.ReadBool();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CheckContentDisplay(Mobile from) => !m_Locked && base.CheckContentDisplay(from);
|
||||
|
||||
public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage)
|
||||
{
|
||||
if (from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
{
|
||||
from.SendLocalizedMessage(501747); // It appears to be locked.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.TryDropItem(from, dropped, sendFullMessage);
|
||||
}
|
||||
|
||||
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
|
||||
{
|
||||
if (from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
{
|
||||
from.SendLocalizedMessage(501747); // It appears to be locked.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.OnDragDropInto(from, item, p);
|
||||
}
|
||||
|
||||
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
|
||||
{
|
||||
if (!base.CheckLift(from, item, ref reject))
|
||||
return false;
|
||||
|
||||
if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckItemUse(Mobile from, Item item)
|
||||
{
|
||||
if (!base.CheckItemUse(from, item))
|
||||
return false;
|
||||
|
||||
if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool CheckLocked(Mobile from)
|
||||
{
|
||||
bool inaccessible = false;
|
||||
|
||||
if (m_Locked)
|
||||
{
|
||||
int number;
|
||||
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
number = 502502; // That is locked, but you open it with your godly powers.
|
||||
}
|
||||
else
|
||||
{
|
||||
number = 501747; // It appears to be locked.
|
||||
inaccessible = true;
|
||||
}
|
||||
|
||||
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", ""));
|
||||
}
|
||||
|
||||
return inaccessible;
|
||||
}
|
||||
|
||||
public override void OnTelekinesis(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
{
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32,
|
||||
5022);
|
||||
Effects.PlaySound(Location, Map, 0x1F5);
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnTelekinesis(from);
|
||||
}
|
||||
|
||||
public override void OnDoubleClickSecureTrade(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
return;
|
||||
|
||||
base.OnDoubleClickSecureTrade(from);
|
||||
}
|
||||
|
||||
public override void Open(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
return;
|
||||
|
||||
base.Open(from);
|
||||
}
|
||||
|
||||
public override void OnSnoop(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
return;
|
||||
|
||||
base.OnSnoop(from);
|
||||
}
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
|
||||
if (IsShipwreckedItem)
|
||||
list.Add(1041645); // recovered from a shipwreck
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
base.OnSingleClick(from);
|
||||
|
||||
if (IsShipwreckedItem)
|
||||
LabelTo(from, 1041645); // recovered from a shipwreck
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Server.Engines.Craft;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public abstract class LockableContainer : TrappableContainer, ILockable, ILockpickable, ICraftable, IShipwreckedItem
|
||||
{
|
||||
private bool m_Locked;
|
||||
|
||||
public LockableContainer(int itemID) : base(itemID) => MaxLockLevel = 100;
|
||||
|
||||
public LockableContainer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool TrapOnOpen => !TrapOnLockpick;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool TrapOnLockpick { get; set; }
|
||||
|
||||
public override bool DisplaysContent => !m_Locked;
|
||||
|
||||
public int OnCraft(
|
||||
int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool,
|
||||
CraftItem craftItem, int resHue
|
||||
)
|
||||
{
|
||||
if (from.CheckSkill(SkillName.Tinkering, -5.0, 15.0))
|
||||
{
|
||||
from.SendLocalizedMessage(500636); // Your tinker skill was sufficient to make the item lockable.
|
||||
|
||||
var key = new Key(KeyType.Copper, Key.RandomValue());
|
||||
|
||||
KeyValue = key.KeyValue;
|
||||
DropItem(key);
|
||||
|
||||
var tinkering = from.Skills.Tinkering.Value;
|
||||
var level = (int)(tinkering * 0.8);
|
||||
|
||||
RequiredSkill = level - 4;
|
||||
LockLevel = level - 14;
|
||||
MaxLockLevel = level + 35;
|
||||
|
||||
if (LockLevel == 0)
|
||||
LockLevel = -1;
|
||||
else if (LockLevel > 95)
|
||||
LockLevel = 95;
|
||||
|
||||
if (RequiredSkill > 95)
|
||||
RequiredSkill = 95;
|
||||
|
||||
if (MaxLockLevel > 95)
|
||||
MaxLockLevel = 95;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(500637); // Your tinker skill was insufficient to make the item lockable.
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public virtual bool Locked
|
||||
{
|
||||
get => m_Locked;
|
||||
set
|
||||
{
|
||||
m_Locked = value;
|
||||
|
||||
if (m_Locked)
|
||||
Picker = null;
|
||||
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public uint KeyValue { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Mobile Picker { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int MaxLockLevel { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int LockLevel { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int RequiredSkill { get; set; }
|
||||
|
||||
public virtual void LockPick(Mobile from)
|
||||
{
|
||||
Locked = false;
|
||||
Picker = from;
|
||||
|
||||
if (TrapOnLockpick && ExecuteTrap(from)) TrapOnLockpick = false;
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool IsShipwreckedItem { get; set; }
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(6); // version
|
||||
|
||||
writer.Write(IsShipwreckedItem);
|
||||
|
||||
writer.Write(TrapOnLockpick);
|
||||
|
||||
writer.Write(RequiredSkill);
|
||||
|
||||
writer.Write(MaxLockLevel);
|
||||
|
||||
writer.Write(KeyValue);
|
||||
writer.Write(LockLevel);
|
||||
writer.Write(m_Locked);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 6:
|
||||
{
|
||||
IsShipwreckedItem = reader.ReadBool();
|
||||
|
||||
goto case 5;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
TrapOnLockpick = reader.ReadBool();
|
||||
|
||||
goto case 4;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
RequiredSkill = reader.ReadInt();
|
||||
|
||||
goto case 3;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
MaxLockLevel = reader.ReadInt();
|
||||
|
||||
goto case 2;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
KeyValue = reader.ReadUInt();
|
||||
|
||||
goto case 1;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
LockLevel = reader.ReadInt();
|
||||
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
if (version < 3)
|
||||
MaxLockLevel = 100;
|
||||
|
||||
if (version < 4)
|
||||
{
|
||||
if (MaxLockLevel - LockLevel == 40)
|
||||
{
|
||||
RequiredSkill = LockLevel + 6;
|
||||
LockLevel = RequiredSkill - 10;
|
||||
MaxLockLevel = RequiredSkill + 39;
|
||||
}
|
||||
else
|
||||
{
|
||||
RequiredSkill = LockLevel;
|
||||
}
|
||||
}
|
||||
|
||||
m_Locked = reader.ReadBool();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CheckContentDisplay(Mobile from) => !m_Locked && base.CheckContentDisplay(from);
|
||||
|
||||
public override bool TryDropItem(Mobile from, Item dropped, bool sendFullMessage)
|
||||
{
|
||||
if (from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
{
|
||||
from.SendLocalizedMessage(501747); // It appears to be locked.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.TryDropItem(from, dropped, sendFullMessage);
|
||||
}
|
||||
|
||||
public override bool OnDragDropInto(Mobile from, Item item, Point3D p)
|
||||
{
|
||||
if (from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
{
|
||||
from.SendLocalizedMessage(501747); // It appears to be locked.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.OnDragDropInto(from, item, p);
|
||||
}
|
||||
|
||||
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
|
||||
{
|
||||
if (!base.CheckLift(from, item, ref reject))
|
||||
return false;
|
||||
|
||||
if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckItemUse(Mobile from, Item item)
|
||||
{
|
||||
if (!base.CheckItemUse(from, item))
|
||||
return false;
|
||||
|
||||
if (item != this && from.AccessLevel < AccessLevel.GameMaster && m_Locked)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool CheckLocked(Mobile from)
|
||||
{
|
||||
var inaccessible = false;
|
||||
|
||||
if (m_Locked)
|
||||
{
|
||||
int number;
|
||||
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
number = 502502; // That is locked, but you open it with your godly powers.
|
||||
}
|
||||
else
|
||||
{
|
||||
number = 501747; // It appears to be locked.
|
||||
inaccessible = true;
|
||||
}
|
||||
|
||||
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", ""));
|
||||
}
|
||||
|
||||
return inaccessible;
|
||||
}
|
||||
|
||||
public override void OnTelekinesis(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
{
|
||||
Effects.SendLocationParticles(
|
||||
EffectItem.Create(Location, Map, EffectItem.DefaultDuration),
|
||||
0x376A,
|
||||
9,
|
||||
32,
|
||||
5022
|
||||
);
|
||||
Effects.PlaySound(Location, Map, 0x1F5);
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnTelekinesis(from);
|
||||
}
|
||||
|
||||
public override void OnDoubleClickSecureTrade(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
return;
|
||||
|
||||
base.OnDoubleClickSecureTrade(from);
|
||||
}
|
||||
|
||||
public override void Open(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
return;
|
||||
|
||||
base.Open(from);
|
||||
}
|
||||
|
||||
public override void OnSnoop(Mobile from)
|
||||
{
|
||||
if (CheckLocked(from))
|
||||
return;
|
||||
|
||||
base.OnSnoop(from);
|
||||
}
|
||||
|
||||
public override void AddNameProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.AddNameProperties(list);
|
||||
|
||||
if (IsShipwreckedItem)
|
||||
list.Add(1041645); // recovered from a shipwreck
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
base.OnSingleClick(from);
|
||||
|
||||
if (IsShipwreckedItem)
|
||||
LabelTo(from, 1041645); // recovered from a shipwreck
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,231 +1,233 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class MarkContainer : LockableContainer
|
||||
{
|
||||
private bool m_AutoLock;
|
||||
private InternalTimer m_RelockTimer;
|
||||
|
||||
[Constructible]
|
||||
public MarkContainer(bool bone = false, bool locked = false) : base(bone ? 0xECA : 0xE79)
|
||||
{
|
||||
Movable = false;
|
||||
|
||||
if (bone)
|
||||
Hue = 1102;
|
||||
|
||||
m_AutoLock = locked;
|
||||
Locked = locked;
|
||||
|
||||
if (locked)
|
||||
LockLevel = -255;
|
||||
}
|
||||
|
||||
public MarkContainer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool AutoLock
|
||||
{
|
||||
get => m_AutoLock;
|
||||
set
|
||||
{
|
||||
m_AutoLock = value;
|
||||
|
||||
if (!m_AutoLock)
|
||||
StopTimer();
|
||||
else if (!Locked && m_RelockTimer == null)
|
||||
m_RelockTimer = new InternalTimer(this);
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Map TargetMap { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Point3D Target { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool Bone
|
||||
{
|
||||
get => ItemID == 0xECA;
|
||||
set
|
||||
{
|
||||
ItemID = value ? 0xECA : 0xE79;
|
||||
Hue = value ? 1102 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public string Description { get; set; }
|
||||
|
||||
public override bool IsDecoContainer => false;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override bool Locked
|
||||
{
|
||||
get => base.Locked;
|
||||
set
|
||||
{
|
||||
base.Locked = value;
|
||||
|
||||
if (m_AutoLock)
|
||||
{
|
||||
StopTimer();
|
||||
|
||||
if (!Locked)
|
||||
m_RelockTimer = new InternalTimer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("SecretLocGen", AccessLevel.Administrator, SecretLocGen_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("SecretLocGen")]
|
||||
[Description("Generates mark containers to Malas secret locations.")]
|
||||
public static void SecretLocGen_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
CreateMalasPassage(951, 546, -70, 1006, 994, -70, false, false);
|
||||
CreateMalasPassage(914, 192, -79, 1019, 1062, -70, false, false);
|
||||
CreateMalasPassage(1614, 143, -90, 1214, 1313, -90, false, false);
|
||||
CreateMalasPassage(2176, 324, -90, 1554, 172, -90, false, false);
|
||||
CreateMalasPassage(864, 812, -90, 1061, 1161, -70, false, false);
|
||||
CreateMalasPassage(1051, 1434, -85, 1076, 1244, -70, false, true);
|
||||
CreateMalasPassage(1326, 523, -87, 1201, 1554, -70, false, false);
|
||||
CreateMalasPassage(424, 189, -1, 2333, 1501, -90, true, false);
|
||||
CreateMalasPassage(1313, 1115, -85, 1183, 462, -45, false, false);
|
||||
|
||||
e.Mobile.SendMessage("Secret mark containers have been created.");
|
||||
}
|
||||
|
||||
private static bool FindMarkContainer(Point3D p, Map map)
|
||||
{
|
||||
IPooledEnumerable<MarkContainer> eable = map.GetItemsInRange<MarkContainer>(p, 0);
|
||||
bool found = eable.Any(item => item.Z == p.Z);
|
||||
eable.Free();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private static void CreateMalasPassage(int x, int y, int z, int xTarget, int yTarget, int zTarget, bool bone,
|
||||
bool locked)
|
||||
{
|
||||
Point3D location = new Point3D(x, y, z);
|
||||
|
||||
if (FindMarkContainer(location, Map.Malas))
|
||||
return;
|
||||
|
||||
MarkContainer cont = new MarkContainer(bone, locked)
|
||||
{
|
||||
TargetMap = Map.Malas,
|
||||
Target = new Point3D(xTarget, yTarget, zTarget),
|
||||
Description = "strange location"
|
||||
};
|
||||
|
||||
cont.MoveToWorld(location, Map.Malas);
|
||||
}
|
||||
|
||||
public void StopTimer()
|
||||
{
|
||||
m_RelockTimer?.Stop();
|
||||
m_RelockTimer = null;
|
||||
}
|
||||
|
||||
public void Mark(RecallRune rune)
|
||||
{
|
||||
if (TargetMap != null)
|
||||
{
|
||||
rune.Marked = true;
|
||||
rune.TargetMap = TargetMap;
|
||||
rune.Target = Target;
|
||||
rune.Description = Description;
|
||||
rune.House = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnDragDrop(Mobile from, Item dropped)
|
||||
{
|
||||
if (dropped is RecallRune rune && base.OnDragDrop(from, dropped))
|
||||
{
|
||||
Mark(rune);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnDragDropInto(Mobile from, Item dropped, Point3D p)
|
||||
{
|
||||
if (dropped is RecallRune rune && base.OnDragDropInto(from, dropped, p))
|
||||
{
|
||||
Mark(rune);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_AutoLock);
|
||||
|
||||
if (!Locked && m_AutoLock)
|
||||
writer.WriteDeltaTime(m_RelockTimer.RelockTime);
|
||||
|
||||
writer.Write(TargetMap);
|
||||
writer.Write(Target);
|
||||
writer.Write(Description);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
m_AutoLock = reader.ReadBool();
|
||||
|
||||
if (!Locked && m_AutoLock)
|
||||
m_RelockTimer = new InternalTimer(this, reader.ReadDeltaTime() - DateTime.UtcNow);
|
||||
|
||||
TargetMap = reader.ReadMap();
|
||||
Target = reader.ReadPoint3D();
|
||||
Description = reader.ReadString();
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
public InternalTimer(MarkContainer container) : this(container, TimeSpan.FromMinutes(5.0))
|
||||
{
|
||||
}
|
||||
|
||||
public InternalTimer(MarkContainer container, TimeSpan delay) : base(delay)
|
||||
{
|
||||
Container = container;
|
||||
RelockTime = DateTime.UtcNow + delay;
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
public MarkContainer Container { get; }
|
||||
|
||||
public DateTime RelockTime { get; }
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
Container.Locked = true;
|
||||
Container.LockLevel = -255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class MarkContainer : LockableContainer
|
||||
{
|
||||
private bool m_AutoLock;
|
||||
private InternalTimer m_RelockTimer;
|
||||
|
||||
[Constructible]
|
||||
public MarkContainer(bool bone = false, bool locked = false) : base(bone ? 0xECA : 0xE79)
|
||||
{
|
||||
Movable = false;
|
||||
|
||||
if (bone)
|
||||
Hue = 1102;
|
||||
|
||||
m_AutoLock = locked;
|
||||
Locked = locked;
|
||||
|
||||
if (locked)
|
||||
LockLevel = -255;
|
||||
}
|
||||
|
||||
public MarkContainer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool AutoLock
|
||||
{
|
||||
get => m_AutoLock;
|
||||
set
|
||||
{
|
||||
m_AutoLock = value;
|
||||
|
||||
if (!m_AutoLock)
|
||||
StopTimer();
|
||||
else if (!Locked && m_RelockTimer == null)
|
||||
m_RelockTimer = new InternalTimer(this);
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Map TargetMap { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Point3D Target { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public bool Bone
|
||||
{
|
||||
get => ItemID == 0xECA;
|
||||
set
|
||||
{
|
||||
ItemID = value ? 0xECA : 0xE79;
|
||||
Hue = value ? 1102 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public string Description { get; set; }
|
||||
|
||||
public override bool IsDecoContainer => false;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public override bool Locked
|
||||
{
|
||||
get => base.Locked;
|
||||
set
|
||||
{
|
||||
base.Locked = value;
|
||||
|
||||
if (m_AutoLock)
|
||||
{
|
||||
StopTimer();
|
||||
|
||||
if (!Locked)
|
||||
m_RelockTimer = new InternalTimer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("SecretLocGen", AccessLevel.Administrator, SecretLocGen_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("SecretLocGen")]
|
||||
[Description("Generates mark containers to Malas secret locations.")]
|
||||
public static void SecretLocGen_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
CreateMalasPassage(951, 546, -70, 1006, 994, -70, false, false);
|
||||
CreateMalasPassage(914, 192, -79, 1019, 1062, -70, false, false);
|
||||
CreateMalasPassage(1614, 143, -90, 1214, 1313, -90, false, false);
|
||||
CreateMalasPassage(2176, 324, -90, 1554, 172, -90, false, false);
|
||||
CreateMalasPassage(864, 812, -90, 1061, 1161, -70, false, false);
|
||||
CreateMalasPassage(1051, 1434, -85, 1076, 1244, -70, false, true);
|
||||
CreateMalasPassage(1326, 523, -87, 1201, 1554, -70, false, false);
|
||||
CreateMalasPassage(424, 189, -1, 2333, 1501, -90, true, false);
|
||||
CreateMalasPassage(1313, 1115, -85, 1183, 462, -45, false, false);
|
||||
|
||||
e.Mobile.SendMessage("Secret mark containers have been created.");
|
||||
}
|
||||
|
||||
private static bool FindMarkContainer(Point3D p, Map map)
|
||||
{
|
||||
var eable = map.GetItemsInRange<MarkContainer>(p, 0);
|
||||
var found = eable.Any(item => item.Z == p.Z);
|
||||
eable.Free();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
private static void CreateMalasPassage(
|
||||
int x, int y, int z, int xTarget, int yTarget, int zTarget, bool bone,
|
||||
bool locked
|
||||
)
|
||||
{
|
||||
var location = new Point3D(x, y, z);
|
||||
|
||||
if (FindMarkContainer(location, Map.Malas))
|
||||
return;
|
||||
|
||||
var cont = new MarkContainer(bone, locked)
|
||||
{
|
||||
TargetMap = Map.Malas,
|
||||
Target = new Point3D(xTarget, yTarget, zTarget),
|
||||
Description = "strange location"
|
||||
};
|
||||
|
||||
cont.MoveToWorld(location, Map.Malas);
|
||||
}
|
||||
|
||||
public void StopTimer()
|
||||
{
|
||||
m_RelockTimer?.Stop();
|
||||
m_RelockTimer = null;
|
||||
}
|
||||
|
||||
public void Mark(RecallRune rune)
|
||||
{
|
||||
if (TargetMap != null)
|
||||
{
|
||||
rune.Marked = true;
|
||||
rune.TargetMap = TargetMap;
|
||||
rune.Target = Target;
|
||||
rune.Description = Description;
|
||||
rune.House = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool OnDragDrop(Mobile from, Item dropped)
|
||||
{
|
||||
if (dropped is RecallRune rune && base.OnDragDrop(from, dropped))
|
||||
{
|
||||
Mark(rune);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnDragDropInto(Mobile from, Item dropped, Point3D p)
|
||||
{
|
||||
if (dropped is RecallRune rune && base.OnDragDropInto(from, dropped, p))
|
||||
{
|
||||
Mark(rune);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_AutoLock);
|
||||
|
||||
if (!Locked && m_AutoLock)
|
||||
writer.WriteDeltaTime(m_RelockTimer.RelockTime);
|
||||
|
||||
writer.Write(TargetMap);
|
||||
writer.Write(Target);
|
||||
writer.Write(Description);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
m_AutoLock = reader.ReadBool();
|
||||
|
||||
if (!Locked && m_AutoLock)
|
||||
m_RelockTimer = new InternalTimer(this, reader.ReadDeltaTime() - DateTime.UtcNow);
|
||||
|
||||
TargetMap = reader.ReadMap();
|
||||
Target = reader.ReadPoint3D();
|
||||
Description = reader.ReadString();
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
public InternalTimer(MarkContainer container) : this(container, TimeSpan.FromMinutes(5.0))
|
||||
{
|
||||
}
|
||||
|
||||
public InternalTimer(MarkContainer container, TimeSpan delay) : base(delay)
|
||||
{
|
||||
Container = container;
|
||||
RelockTime = DateTime.UtcNow + delay;
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
public MarkContainer Container { get; }
|
||||
|
||||
public DateTime RelockTime { get; }
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
Container.Locked = true;
|
||||
Container.LockLevel = -255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,210 +1,210 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
[Flippable]
|
||||
public class ParagonChest : LockableContainer
|
||||
{
|
||||
private static readonly int[] m_ItemIDs =
|
||||
{
|
||||
0x9AB, 0xE40, 0xE41, 0xE7C
|
||||
};
|
||||
|
||||
private static readonly int[] m_Hues =
|
||||
{
|
||||
0x0, 0x455, 0x47E, 0x89F, 0x8A5, 0x8AB,
|
||||
0x966, 0x96D, 0x972, 0x973, 0x979
|
||||
};
|
||||
|
||||
private string m_Name;
|
||||
|
||||
[Constructible]
|
||||
public ParagonChest(string name, int level) : base(m_ItemIDs.RandomElement())
|
||||
{
|
||||
m_Name = name;
|
||||
Hue = m_Hues.RandomElement();
|
||||
Fill(level);
|
||||
}
|
||||
|
||||
public ParagonChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
base.OnSingleClick(from);
|
||||
LabelTo(from, 1063449, m_Name);
|
||||
}
|
||||
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
list.Add(1063449, m_Name);
|
||||
}
|
||||
|
||||
private static void GetRandomAOSStats(out int attributeCount, out int min, out int max)
|
||||
{
|
||||
int rnd = Utility.Random(15);
|
||||
|
||||
if (rnd < 1)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(2, 6);
|
||||
min = 20;
|
||||
max = 70;
|
||||
}
|
||||
else if (rnd < 3)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(2, 4);
|
||||
min = 20;
|
||||
max = 50;
|
||||
}
|
||||
else if (rnd < 6)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(2, 3);
|
||||
min = 20;
|
||||
max = 40;
|
||||
}
|
||||
else if (rnd < 10)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(1, 2);
|
||||
min = 10;
|
||||
max = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeCount = 1;
|
||||
min = 10;
|
||||
max = 20;
|
||||
}
|
||||
}
|
||||
|
||||
public void Flip()
|
||||
{
|
||||
ItemID = ItemID switch
|
||||
{
|
||||
0x9AB => 0xE7C,
|
||||
0xE7C => 0x9AB,
|
||||
0xE40 => 0xE41,
|
||||
0xE41 => 0xE40,
|
||||
_ => ItemID
|
||||
};
|
||||
}
|
||||
|
||||
private void Fill(int level)
|
||||
{
|
||||
TrapType = TrapType.ExplosionTrap;
|
||||
TrapPower = level * 25;
|
||||
TrapLevel = level;
|
||||
Locked = true;
|
||||
|
||||
RequiredSkill = level switch
|
||||
{
|
||||
1 => 36,
|
||||
2 => 76,
|
||||
3 => 84,
|
||||
4 => 92,
|
||||
5 => 100,
|
||||
_ => RequiredSkill
|
||||
};
|
||||
|
||||
LockLevel = RequiredSkill - 10;
|
||||
MaxLockLevel = RequiredSkill + 40;
|
||||
|
||||
DropItem(new Gold(level * 200));
|
||||
|
||||
for (int i = 0; i < level; ++i)
|
||||
DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular));
|
||||
|
||||
for (int i = 0; i < level * 2; ++i)
|
||||
{
|
||||
Item item;
|
||||
|
||||
if (Core.AOS)
|
||||
item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
|
||||
else
|
||||
item = Loot.RandomArmorOrShieldOrWeapon();
|
||||
|
||||
if (item is BaseWeapon weapon)
|
||||
{
|
||||
if (Core.AOS)
|
||||
{
|
||||
GetRandomAOSStats(out int attributeCount, out int min, out int max);
|
||||
BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6);
|
||||
weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6);
|
||||
weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6);
|
||||
}
|
||||
|
||||
DropItem(weapon);
|
||||
}
|
||||
else if (item is BaseArmor armor)
|
||||
{
|
||||
if (Core.AOS)
|
||||
{
|
||||
GetRandomAOSStats(out int attributeCount, out int min, out int max);
|
||||
BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6);
|
||||
armor.Durability = (ArmorDurabilityLevel)Utility.Random(6);
|
||||
}
|
||||
|
||||
DropItem(armor);
|
||||
}
|
||||
else if (item is BaseHat hat)
|
||||
{
|
||||
if (Core.AOS)
|
||||
{
|
||||
GetRandomAOSStats(out int attributeCount, out int min, out int max);
|
||||
BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max);
|
||||
}
|
||||
|
||||
DropItem(hat);
|
||||
}
|
||||
else if (item is BaseJewel jewel)
|
||||
{
|
||||
GetRandomAOSStats(out int attributeCount, out int min, out int max);
|
||||
BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max);
|
||||
|
||||
DropItem(jewel);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < level; i++)
|
||||
{
|
||||
Item item = Loot.RandomPossibleReagent();
|
||||
item.Amount = Utility.RandomMinMax(40, 60);
|
||||
DropItem(item);
|
||||
}
|
||||
|
||||
for (int i = 0; i < level; i++)
|
||||
{
|
||||
Item item = Loot.RandomGem();
|
||||
DropItem(item);
|
||||
}
|
||||
|
||||
DropItem(new TreasureMap(level + 1, Utility.RandomBool() ? Map.Felucca : Map.Trammel));
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Name);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
m_Name = Utility.Intern(reader.ReadString());
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Server.Items
|
||||
{
|
||||
[Flippable]
|
||||
public class ParagonChest : LockableContainer
|
||||
{
|
||||
private static readonly int[] m_ItemIDs =
|
||||
{
|
||||
0x9AB, 0xE40, 0xE41, 0xE7C
|
||||
};
|
||||
|
||||
private static readonly int[] m_Hues =
|
||||
{
|
||||
0x0, 0x455, 0x47E, 0x89F, 0x8A5, 0x8AB,
|
||||
0x966, 0x96D, 0x972, 0x973, 0x979
|
||||
};
|
||||
|
||||
private string m_Name;
|
||||
|
||||
[Constructible]
|
||||
public ParagonChest(string name, int level) : base(m_ItemIDs.RandomElement())
|
||||
{
|
||||
m_Name = name;
|
||||
Hue = m_Hues.RandomElement();
|
||||
Fill(level);
|
||||
}
|
||||
|
||||
public ParagonChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
base.OnSingleClick(from);
|
||||
LabelTo(from, 1063449, m_Name);
|
||||
}
|
||||
|
||||
public override void GetProperties(ObjectPropertyList list)
|
||||
{
|
||||
base.GetProperties(list);
|
||||
|
||||
list.Add(1063449, m_Name);
|
||||
}
|
||||
|
||||
private static void GetRandomAOSStats(out int attributeCount, out int min, out int max)
|
||||
{
|
||||
var rnd = Utility.Random(15);
|
||||
|
||||
if (rnd < 1)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(2, 6);
|
||||
min = 20;
|
||||
max = 70;
|
||||
}
|
||||
else if (rnd < 3)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(2, 4);
|
||||
min = 20;
|
||||
max = 50;
|
||||
}
|
||||
else if (rnd < 6)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(2, 3);
|
||||
min = 20;
|
||||
max = 40;
|
||||
}
|
||||
else if (rnd < 10)
|
||||
{
|
||||
attributeCount = Utility.RandomMinMax(1, 2);
|
||||
min = 10;
|
||||
max = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
attributeCount = 1;
|
||||
min = 10;
|
||||
max = 20;
|
||||
}
|
||||
}
|
||||
|
||||
public void Flip()
|
||||
{
|
||||
ItemID = ItemID switch
|
||||
{
|
||||
0x9AB => 0xE7C,
|
||||
0xE7C => 0x9AB,
|
||||
0xE40 => 0xE41,
|
||||
0xE41 => 0xE40,
|
||||
_ => ItemID
|
||||
};
|
||||
}
|
||||
|
||||
private void Fill(int level)
|
||||
{
|
||||
TrapType = TrapType.ExplosionTrap;
|
||||
TrapPower = level * 25;
|
||||
TrapLevel = level;
|
||||
Locked = true;
|
||||
|
||||
RequiredSkill = level switch
|
||||
{
|
||||
1 => 36,
|
||||
2 => 76,
|
||||
3 => 84,
|
||||
4 => 92,
|
||||
5 => 100,
|
||||
_ => RequiredSkill
|
||||
};
|
||||
|
||||
LockLevel = RequiredSkill - 10;
|
||||
MaxLockLevel = RequiredSkill + 40;
|
||||
|
||||
DropItem(new Gold(level * 200));
|
||||
|
||||
for (var i = 0; i < level; ++i)
|
||||
DropItem(Loot.RandomScroll(0, 63, SpellbookType.Regular));
|
||||
|
||||
for (var i = 0; i < level * 2; ++i)
|
||||
{
|
||||
Item item;
|
||||
|
||||
if (Core.AOS)
|
||||
item = Loot.RandomArmorOrShieldOrWeaponOrJewelry();
|
||||
else
|
||||
item = Loot.RandomArmorOrShieldOrWeapon();
|
||||
|
||||
if (item is BaseWeapon weapon)
|
||||
{
|
||||
if (Core.AOS)
|
||||
{
|
||||
GetRandomAOSStats(out var attributeCount, out var min, out var max);
|
||||
BaseRunicTool.ApplyAttributesTo(weapon, attributeCount, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
weapon.DamageLevel = (WeaponDamageLevel)Utility.Random(6);
|
||||
weapon.AccuracyLevel = (WeaponAccuracyLevel)Utility.Random(6);
|
||||
weapon.DurabilityLevel = (WeaponDurabilityLevel)Utility.Random(6);
|
||||
}
|
||||
|
||||
DropItem(weapon);
|
||||
}
|
||||
else if (item is BaseArmor armor)
|
||||
{
|
||||
if (Core.AOS)
|
||||
{
|
||||
GetRandomAOSStats(out var attributeCount, out var min, out var max);
|
||||
BaseRunicTool.ApplyAttributesTo(armor, attributeCount, min, max);
|
||||
}
|
||||
else
|
||||
{
|
||||
armor.ProtectionLevel = (ArmorProtectionLevel)Utility.Random(6);
|
||||
armor.Durability = (ArmorDurabilityLevel)Utility.Random(6);
|
||||
}
|
||||
|
||||
DropItem(armor);
|
||||
}
|
||||
else if (item is BaseHat hat)
|
||||
{
|
||||
if (Core.AOS)
|
||||
{
|
||||
GetRandomAOSStats(out var attributeCount, out var min, out var max);
|
||||
BaseRunicTool.ApplyAttributesTo(hat, attributeCount, min, max);
|
||||
}
|
||||
|
||||
DropItem(hat);
|
||||
}
|
||||
else if (item is BaseJewel jewel)
|
||||
{
|
||||
GetRandomAOSStats(out var attributeCount, out var min, out var max);
|
||||
BaseRunicTool.ApplyAttributesTo(jewel, attributeCount, min, max);
|
||||
|
||||
DropItem(jewel);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < level; i++)
|
||||
{
|
||||
var item = Loot.RandomPossibleReagent();
|
||||
item.Amount = Utility.RandomMinMax(40, 60);
|
||||
DropItem(item);
|
||||
}
|
||||
|
||||
for (var i = 0; i < level; i++)
|
||||
{
|
||||
var item = Loot.RandomGem();
|
||||
DropItem(item);
|
||||
}
|
||||
|
||||
DropItem(new TreasureMap(level + 1, Utility.RandomBool() ? Map.Felucca : Map.Trammel));
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Name);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
m_Name = Utility.Intern(reader.ReadString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,340 +1,347 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.ContextMenus;
|
||||
using Server.Engines.Craft;
|
||||
using Server.Network;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class SalvageBag : Bag
|
||||
{
|
||||
private bool m_Failure;
|
||||
|
||||
[Constructible]
|
||||
public SalvageBag()
|
||||
: this(Utility.RandomBlueHue())
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public SalvageBag(int hue)
|
||||
{
|
||||
Weight = 2.0;
|
||||
Hue = hue;
|
||||
m_Failure = false;
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1079931; // Salvage Bag
|
||||
|
||||
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
|
||||
{
|
||||
base.GetContextMenuEntries(from, list);
|
||||
|
||||
if (from.Alive)
|
||||
{
|
||||
list.Add(new SalvageIngotsEntry(this, IsChildOf(from.Backpack) && Resmeltables()));
|
||||
list.Add(new SalvageClothEntry(this, IsChildOf(from.Backpack) && Scissorables()));
|
||||
list.Add(new SalvageAllEntry(this, IsChildOf(from.Backpack) && Resmeltables() && Scissorables()));
|
||||
}
|
||||
}
|
||||
|
||||
private bool Resmelt(Mobile from, Item item, CraftResource resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CraftResources.GetType(resource) != CraftResourceType.Metal)
|
||||
return false;
|
||||
|
||||
CraftResourceInfo info = CraftResources.GetInfo(resource);
|
||||
|
||||
if (info == null || info.ResourceTypes.Length == 0)
|
||||
return false;
|
||||
|
||||
CraftItem craftItem = DefBlacksmithy.CraftSystem.CraftItems.SearchFor(item.GetType());
|
||||
|
||||
if (craftItem == null || craftItem.Resources.Count == 0)
|
||||
return false;
|
||||
|
||||
CraftRes craftResource = craftItem.Resources[0];
|
||||
|
||||
if (craftResource.Amount < 2)
|
||||
return false; // Not enough metal to resmelt
|
||||
|
||||
var difficulty = resource switch
|
||||
{
|
||||
CraftResource.DullCopper => 65.0,
|
||||
CraftResource.ShadowIron => 70.0,
|
||||
CraftResource.Copper => 75.0,
|
||||
CraftResource.Bronze => 80.0,
|
||||
CraftResource.Gold => 85.0,
|
||||
CraftResource.Agapite => 90.0,
|
||||
CraftResource.Verite => 95.0,
|
||||
CraftResource.Valorite => 99.0,
|
||||
_ => 0.0
|
||||
};
|
||||
|
||||
Type resourceType = info.ResourceTypes[0];
|
||||
Item ingot = (Item)ActivatorUtil.CreateInstance(resourceType);
|
||||
|
||||
if (item is DragonBardingDeed || (item is BaseArmor armor && armor.PlayerConstructed) ||
|
||||
(item is BaseWeapon weapon && weapon.PlayerConstructed) ||
|
||||
(item is BaseClothing clothing && clothing.PlayerConstructed))
|
||||
{
|
||||
double mining = from.Skills.Mining.Value;
|
||||
if (mining > 100.0)
|
||||
mining = 100.0;
|
||||
double amount = ((4 + mining) * craftResource.Amount - 4) * 0.0068;
|
||||
if (amount < 2)
|
||||
ingot.Amount = 2;
|
||||
else
|
||||
ingot.Amount = (int)amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
ingot.Amount = 2;
|
||||
}
|
||||
|
||||
if (difficulty > from.Skills.Mining.Value)
|
||||
{
|
||||
m_Failure = true;
|
||||
ingot.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
}
|
||||
|
||||
from.AddToBackpack(ingot);
|
||||
|
||||
from.PlaySound(0x2A);
|
||||
from.PlaySound(0x240);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Resmeltables() // Where context menu checks for metal items and dragon barding deeds
|
||||
{
|
||||
foreach (Item i in Items)
|
||||
return i?.Deleted == false && (
|
||||
(i is BaseWeapon weapon && CraftResources.GetType(weapon.Resource) == CraftResourceType.Metal) ||
|
||||
(i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Metal) ||
|
||||
i is DragonBardingDeed);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Scissorables() // Where context menu checks for Leather items and cloth items
|
||||
{
|
||||
foreach (Item i in Items)
|
||||
{
|
||||
if (!(i is IScissorable) || i.Deleted)
|
||||
continue;
|
||||
|
||||
if (i is BaseClothing || i is Cloth || i is BoltOfCloth || i is Hides || i is BonePile ||
|
||||
(i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Leather))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SalvageIngots(Mobile from)
|
||||
{
|
||||
if (from.Backpack.FindItemsByType<BaseTool>().All(tool => tool.CraftSystem != DefBlacksmithy.CraftSystem))
|
||||
{
|
||||
from.SendLocalizedMessage(1079822); // You need a blacksmithing tool in order to salvage ingots.
|
||||
return;
|
||||
}
|
||||
|
||||
DefBlacksmithy.CheckAnvilAndForge(from, 2, out _, out bool forge);
|
||||
|
||||
if (!forge)
|
||||
{
|
||||
from.SendLocalizedMessage(1044265); // You must be near a forge.
|
||||
return;
|
||||
}
|
||||
|
||||
int salvaged = 0;
|
||||
int notSalvaged = 0;
|
||||
|
||||
Container sBag = this;
|
||||
|
||||
List<Item> smeltables = sBag.FindItemsByType<Item>();
|
||||
|
||||
foreach (Item item in smeltables)
|
||||
{
|
||||
if (item?.Deleted != false)
|
||||
continue;
|
||||
|
||||
if ((item is BaseArmor armor && Resmelt(from, armor, armor.Resource)) ||
|
||||
(item is BaseWeapon weapon && Resmelt(from, weapon, weapon.Resource)) ||
|
||||
item is DragonBardingDeed)
|
||||
salvaged++;
|
||||
else
|
||||
notSalvaged++;
|
||||
}
|
||||
|
||||
if (m_Failure)
|
||||
{
|
||||
from.SendLocalizedMessage(1079975); // You failed to smelt some metal for lack of skill.
|
||||
m_Failure = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1079973,
|
||||
$"{salvaged}\t{salvaged + notSalvaged}"); // Salvaged: ~1_COUNT~/~2_NUM~ blacksmithed items
|
||||
}
|
||||
}
|
||||
|
||||
private void SalvageCloth(Mobile from)
|
||||
{
|
||||
Scissors scissors = from.Backpack.FindItemByType<Scissors>();
|
||||
|
||||
if (scissors == null)
|
||||
{
|
||||
from.SendLocalizedMessage(1079823); // You need scissors in order to salvage cloth.
|
||||
return;
|
||||
}
|
||||
|
||||
int salvaged = 0;
|
||||
int notSalvaged = 0;
|
||||
|
||||
Container sBag = this;
|
||||
|
||||
List<Item> scissorables = sBag.FindItemsByType<Item>();
|
||||
|
||||
for (int i = scissorables.Count - 1; i >= 0; --i)
|
||||
{
|
||||
Item item = scissorables[i];
|
||||
|
||||
if (!(item is IScissorable scissorable))
|
||||
continue;
|
||||
|
||||
if (Scissors.CanScissor(from, scissorable) && scissorable.Scissor(from, scissors))
|
||||
++salvaged;
|
||||
else
|
||||
++notSalvaged;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(1079974,
|
||||
$"{salvaged}\t{salvaged + notSalvaged}"); // Salvaged: ~1_COUNT~/~2_NUM~ tailored items
|
||||
|
||||
Item[] items = FindItemsByType(new[]{
|
||||
typeof(Leather), typeof(Cloth), typeof(SpinedLeather), typeof(HornedLeather), typeof(BarbedLeather),
|
||||
typeof(Bandage), typeof(Bone)
|
||||
});
|
||||
|
||||
for (int i = 0; i < items.Length; i++) from.AddToBackpack(items[i]);
|
||||
}
|
||||
|
||||
private void SalvageAll(Mobile from)
|
||||
{
|
||||
SalvageIngots(from);
|
||||
|
||||
SalvageCloth(from);
|
||||
}
|
||||
|
||||
private class SalvageAllEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly SalvageBag m_Bag;
|
||||
|
||||
public SalvageAllEntry(SalvageBag bag, bool enabled)
|
||||
: base(6276)
|
||||
{
|
||||
m_Bag = bag;
|
||||
|
||||
if (!enabled)
|
||||
Flags |= CMEFlags.Disabled;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Bag.Deleted)
|
||||
return;
|
||||
|
||||
Mobile from = Owner.From;
|
||||
|
||||
if (from.CheckAlive())
|
||||
m_Bag.SalvageAll(from);
|
||||
}
|
||||
}
|
||||
|
||||
private class SalvageIngotsEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly SalvageBag m_Bag;
|
||||
|
||||
public SalvageIngotsEntry(SalvageBag bag, bool enabled)
|
||||
: base(6277)
|
||||
{
|
||||
m_Bag = bag;
|
||||
|
||||
if (!enabled)
|
||||
Flags |= CMEFlags.Disabled;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Bag.Deleted)
|
||||
return;
|
||||
|
||||
Mobile from = Owner.From;
|
||||
|
||||
if (from.CheckAlive())
|
||||
m_Bag.SalvageIngots(from);
|
||||
}
|
||||
}
|
||||
|
||||
private class SalvageClothEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly SalvageBag m_Bag;
|
||||
|
||||
public SalvageClothEntry(SalvageBag bag, bool enabled)
|
||||
: base(6278)
|
||||
{
|
||||
m_Bag = bag;
|
||||
|
||||
if (!enabled)
|
||||
Flags |= CMEFlags.Disabled;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Bag.Deleted)
|
||||
return;
|
||||
|
||||
Mobile from = Owner.From;
|
||||
|
||||
if (from.CheckAlive())
|
||||
m_Bag.SalvageCloth(from);
|
||||
}
|
||||
}
|
||||
|
||||
public SalvageBag(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.ContextMenus;
|
||||
using Server.Engines.Craft;
|
||||
using Server.Network;
|
||||
using Server.Utilities;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class SalvageBag : Bag
|
||||
{
|
||||
private bool m_Failure;
|
||||
|
||||
[Constructible]
|
||||
public SalvageBag()
|
||||
: this(Utility.RandomBlueHue())
|
||||
{
|
||||
}
|
||||
|
||||
[Constructible]
|
||||
public SalvageBag(int hue)
|
||||
{
|
||||
Weight = 2.0;
|
||||
Hue = hue;
|
||||
m_Failure = false;
|
||||
}
|
||||
|
||||
public SalvageBag(Serial serial)
|
||||
: base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override int LabelNumber => 1079931; // Salvage Bag
|
||||
|
||||
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
|
||||
{
|
||||
base.GetContextMenuEntries(from, list);
|
||||
|
||||
if (from.Alive)
|
||||
{
|
||||
list.Add(new SalvageIngotsEntry(this, IsChildOf(from.Backpack) && Resmeltables()));
|
||||
list.Add(new SalvageClothEntry(this, IsChildOf(from.Backpack) && Scissorables()));
|
||||
list.Add(new SalvageAllEntry(this, IsChildOf(from.Backpack) && Resmeltables() && Scissorables()));
|
||||
}
|
||||
}
|
||||
|
||||
private bool Resmelt(Mobile from, Item item, CraftResource resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CraftResources.GetType(resource) != CraftResourceType.Metal)
|
||||
return false;
|
||||
|
||||
var info = CraftResources.GetInfo(resource);
|
||||
|
||||
if (info == null || info.ResourceTypes.Length == 0)
|
||||
return false;
|
||||
|
||||
var craftItem = DefBlacksmithy.CraftSystem.CraftItems.SearchFor(item.GetType());
|
||||
|
||||
if (craftItem == null || craftItem.Resources.Count == 0)
|
||||
return false;
|
||||
|
||||
var craftResource = craftItem.Resources[0];
|
||||
|
||||
if (craftResource.Amount < 2)
|
||||
return false; // Not enough metal to resmelt
|
||||
|
||||
var difficulty = resource switch
|
||||
{
|
||||
CraftResource.DullCopper => 65.0,
|
||||
CraftResource.ShadowIron => 70.0,
|
||||
CraftResource.Copper => 75.0,
|
||||
CraftResource.Bronze => 80.0,
|
||||
CraftResource.Gold => 85.0,
|
||||
CraftResource.Agapite => 90.0,
|
||||
CraftResource.Verite => 95.0,
|
||||
CraftResource.Valorite => 99.0,
|
||||
_ => 0.0
|
||||
};
|
||||
|
||||
var resourceType = info.ResourceTypes[0];
|
||||
var ingot = (Item)ActivatorUtil.CreateInstance(resourceType);
|
||||
|
||||
if (item is DragonBardingDeed || item is BaseArmor armor && armor.PlayerConstructed ||
|
||||
item is BaseWeapon weapon && weapon.PlayerConstructed ||
|
||||
item is BaseClothing clothing && clothing.PlayerConstructed)
|
||||
{
|
||||
var mining = from.Skills.Mining.Value;
|
||||
if (mining > 100.0)
|
||||
mining = 100.0;
|
||||
var amount = ((4 + mining) * craftResource.Amount - 4) * 0.0068;
|
||||
if (amount < 2)
|
||||
ingot.Amount = 2;
|
||||
else
|
||||
ingot.Amount = (int)amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
ingot.Amount = 2;
|
||||
}
|
||||
|
||||
if (difficulty > from.Skills.Mining.Value)
|
||||
{
|
||||
m_Failure = true;
|
||||
ingot.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Delete();
|
||||
}
|
||||
|
||||
from.AddToBackpack(ingot);
|
||||
|
||||
from.PlaySound(0x2A);
|
||||
from.PlaySound(0x240);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Resmeltables() // Where context menu checks for metal items and dragon barding deeds
|
||||
{
|
||||
foreach (var i in Items)
|
||||
return i?.Deleted == false && (
|
||||
i is BaseWeapon weapon && CraftResources.GetType(weapon.Resource) == CraftResourceType.Metal ||
|
||||
i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Metal ||
|
||||
i is DragonBardingDeed);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Scissorables() // Where context menu checks for Leather items and cloth items
|
||||
{
|
||||
foreach (var i in Items)
|
||||
{
|
||||
if (!(i is IScissorable) || i.Deleted)
|
||||
continue;
|
||||
|
||||
if (i is BaseClothing || i is Cloth || i is BoltOfCloth || i is Hides || i is BonePile ||
|
||||
i is BaseArmor armor && CraftResources.GetType(armor.Resource) == CraftResourceType.Leather)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void SalvageIngots(Mobile from)
|
||||
{
|
||||
if (from.Backpack.FindItemsByType<BaseTool>().All(tool => tool.CraftSystem != DefBlacksmithy.CraftSystem))
|
||||
{
|
||||
from.SendLocalizedMessage(1079822); // You need a blacksmithing tool in order to salvage ingots.
|
||||
return;
|
||||
}
|
||||
|
||||
DefBlacksmithy.CheckAnvilAndForge(from, 2, out _, out var forge);
|
||||
|
||||
if (!forge)
|
||||
{
|
||||
from.SendLocalizedMessage(1044265); // You must be near a forge.
|
||||
return;
|
||||
}
|
||||
|
||||
var salvaged = 0;
|
||||
var notSalvaged = 0;
|
||||
|
||||
Container sBag = this;
|
||||
|
||||
var smeltables = sBag.FindItemsByType<Item>();
|
||||
|
||||
foreach (var item in smeltables)
|
||||
{
|
||||
if (item?.Deleted != false)
|
||||
continue;
|
||||
|
||||
if (item is BaseArmor armor && Resmelt(@from, armor, armor.Resource) ||
|
||||
item is BaseWeapon weapon && Resmelt(@from, weapon, weapon.Resource) ||
|
||||
item is DragonBardingDeed)
|
||||
salvaged++;
|
||||
else
|
||||
notSalvaged++;
|
||||
}
|
||||
|
||||
if (m_Failure)
|
||||
{
|
||||
from.SendLocalizedMessage(1079975); // You failed to smelt some metal for lack of skill.
|
||||
m_Failure = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1079973,
|
||||
$"{salvaged}\t{salvaged + notSalvaged}"
|
||||
); // Salvaged: ~1_COUNT~/~2_NUM~ blacksmithed items
|
||||
}
|
||||
}
|
||||
|
||||
private void SalvageCloth(Mobile from)
|
||||
{
|
||||
var scissors = from.Backpack.FindItemByType<Scissors>();
|
||||
|
||||
if (scissors == null)
|
||||
{
|
||||
from.SendLocalizedMessage(1079823); // You need scissors in order to salvage cloth.
|
||||
return;
|
||||
}
|
||||
|
||||
var salvaged = 0;
|
||||
var notSalvaged = 0;
|
||||
|
||||
Container sBag = this;
|
||||
|
||||
var scissorables = sBag.FindItemsByType<Item>();
|
||||
|
||||
for (var i = scissorables.Count - 1; i >= 0; --i)
|
||||
{
|
||||
var item = scissorables[i];
|
||||
|
||||
if (!(item is IScissorable scissorable))
|
||||
continue;
|
||||
|
||||
if (Scissors.CanScissor(from, scissorable) && scissorable.Scissor(from, scissors))
|
||||
++salvaged;
|
||||
else
|
||||
++notSalvaged;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(
|
||||
1079974,
|
||||
$"{salvaged}\t{salvaged + notSalvaged}"
|
||||
); // Salvaged: ~1_COUNT~/~2_NUM~ tailored items
|
||||
|
||||
var items = FindItemsByType(
|
||||
new[]
|
||||
{
|
||||
typeof(Leather), typeof(Cloth), typeof(SpinedLeather), typeof(HornedLeather), typeof(BarbedLeather),
|
||||
typeof(Bandage), typeof(Bone)
|
||||
}
|
||||
);
|
||||
|
||||
for (var i = 0; i < items.Length; i++) from.AddToBackpack(items[i]);
|
||||
}
|
||||
|
||||
private void SalvageAll(Mobile from)
|
||||
{
|
||||
SalvageIngots(from);
|
||||
|
||||
SalvageCloth(from);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadEncodedInt();
|
||||
}
|
||||
|
||||
private class SalvageAllEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly SalvageBag m_Bag;
|
||||
|
||||
public SalvageAllEntry(SalvageBag bag, bool enabled)
|
||||
: base(6276)
|
||||
{
|
||||
m_Bag = bag;
|
||||
|
||||
if (!enabled)
|
||||
Flags |= CMEFlags.Disabled;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Bag.Deleted)
|
||||
return;
|
||||
|
||||
var from = Owner.From;
|
||||
|
||||
if (from.CheckAlive())
|
||||
m_Bag.SalvageAll(from);
|
||||
}
|
||||
}
|
||||
|
||||
private class SalvageIngotsEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly SalvageBag m_Bag;
|
||||
|
||||
public SalvageIngotsEntry(SalvageBag bag, bool enabled)
|
||||
: base(6277)
|
||||
{
|
||||
m_Bag = bag;
|
||||
|
||||
if (!enabled)
|
||||
Flags |= CMEFlags.Disabled;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Bag.Deleted)
|
||||
return;
|
||||
|
||||
var from = Owner.From;
|
||||
|
||||
if (from.CheckAlive())
|
||||
m_Bag.SalvageIngots(from);
|
||||
}
|
||||
}
|
||||
|
||||
private class SalvageClothEntry : ContextMenuEntry
|
||||
{
|
||||
private readonly SalvageBag m_Bag;
|
||||
|
||||
public SalvageClothEntry(SalvageBag bag, bool enabled)
|
||||
: base(6278)
|
||||
{
|
||||
m_Bag = bag;
|
||||
|
||||
if (!enabled)
|
||||
Flags |= CMEFlags.Disabled;
|
||||
}
|
||||
|
||||
public override void OnClick()
|
||||
{
|
||||
if (m_Bag.Deleted)
|
||||
return;
|
||||
|
||||
var from = Owner.From;
|
||||
|
||||
if (from.CheckAlive())
|
||||
m_Bag.SalvageCloth(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,137 +1,137 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Multis;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
[Flippable(0xE80, 0x9A8)]
|
||||
public class StrongBox : BaseContainer, IChoppable
|
||||
{
|
||||
private BaseHouse m_House;
|
||||
private Mobile m_Owner;
|
||||
|
||||
public StrongBox(Mobile owner, BaseHouse house) : base(0xE80)
|
||||
{
|
||||
m_Owner = owner;
|
||||
m_House = house;
|
||||
|
||||
MaxItems = 25;
|
||||
}
|
||||
|
||||
public StrongBox(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override double DefaultWeight => 100;
|
||||
public override int LabelNumber => 1023712;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Mobile Owner
|
||||
{
|
||||
get => m_Owner;
|
||||
set
|
||||
{
|
||||
m_Owner = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public override int DefaultMaxWeight => 0;
|
||||
|
||||
public override bool Decays => m_House == null || m_Owner?.Deleted != false || !m_House.IsCoOwner(m_Owner);
|
||||
|
||||
public override TimeSpan DecayTime => TimeSpan.FromMinutes(30.0);
|
||||
|
||||
public void OnChop(Mobile from)
|
||||
{
|
||||
if (m_House?.Deleted != false || m_Owner?.Deleted != false || from == m_Owner || m_House.IsOwner(from))
|
||||
Chop(from);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Owner);
|
||||
writer.Write(m_House);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Owner = reader.ReadMobile();
|
||||
m_House = reader.ReadItem() as BaseHouse;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(1.0), Validate);
|
||||
}
|
||||
|
||||
private void Validate()
|
||||
{
|
||||
if (m_Owner != null && m_House?.IsCoOwner(m_Owner) == false)
|
||||
{
|
||||
Console.WriteLine("Warning: Destroying strongbox of {0}", m_Owner.Name);
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddNameProperty(ObjectPropertyList list)
|
||||
{
|
||||
if (m_Owner != null)
|
||||
list.Add(1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~
|
||||
else
|
||||
base.AddNameProperty(list);
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
if (m_Owner != null)
|
||||
{
|
||||
LabelTo(from, 1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~
|
||||
|
||||
if (CheckContentDisplay(from))
|
||||
LabelTo(from, "({0} items, {1} stones)", TotalItems, TotalWeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnSingleClick(from);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsAccessibleTo(Mobile m) =>
|
||||
m_Owner?.Deleted != false || m_House?.Deleted != false ||
|
||||
m.AccessLevel >= AccessLevel.GameMaster ||
|
||||
(m == m_Owner && m_House.IsCoOwner(m) && base.IsAccessibleTo(m));
|
||||
|
||||
private void Chop(Mobile from)
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x3B3);
|
||||
from.SendLocalizedMessage(500461); // You destroy the item.
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public Container ConvertToStandardContainer()
|
||||
{
|
||||
Container metalBox = new MetalBox();
|
||||
List<Item> subItems = new List<Item>(Items);
|
||||
|
||||
foreach (Item subItem in subItems) metalBox.AddItem(subItem);
|
||||
|
||||
Delete();
|
||||
|
||||
return metalBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server.Multis;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
[Flippable(0xE80, 0x9A8)]
|
||||
public class StrongBox : BaseContainer, IChoppable
|
||||
{
|
||||
private BaseHouse m_House;
|
||||
private Mobile m_Owner;
|
||||
|
||||
public StrongBox(Mobile owner, BaseHouse house) : base(0xE80)
|
||||
{
|
||||
m_Owner = owner;
|
||||
m_House = house;
|
||||
|
||||
MaxItems = 25;
|
||||
}
|
||||
|
||||
public StrongBox(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override double DefaultWeight => 100;
|
||||
public override int LabelNumber => 1023712;
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public Mobile Owner
|
||||
{
|
||||
get => m_Owner;
|
||||
set
|
||||
{
|
||||
m_Owner = value;
|
||||
InvalidateProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public override int DefaultMaxWeight => 0;
|
||||
|
||||
public override bool Decays => m_House == null || m_Owner?.Deleted != false || !m_House.IsCoOwner(m_Owner);
|
||||
|
||||
public override TimeSpan DecayTime => TimeSpan.FromMinutes(30.0);
|
||||
|
||||
public void OnChop(Mobile from)
|
||||
{
|
||||
if (m_House?.Deleted != false || m_Owner?.Deleted != false || from == m_Owner || m_House.IsOwner(from))
|
||||
Chop(from);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
|
||||
writer.Write(m_Owner);
|
||||
writer.Write(m_House);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
m_Owner = reader.ReadMobile();
|
||||
m_House = reader.ReadItem() as BaseHouse;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(1.0), Validate);
|
||||
}
|
||||
|
||||
private void Validate()
|
||||
{
|
||||
if (m_Owner != null && m_House?.IsCoOwner(m_Owner) == false)
|
||||
{
|
||||
Console.WriteLine("Warning: Destroying strongbox of {0}", m_Owner.Name);
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddNameProperty(ObjectPropertyList list)
|
||||
{
|
||||
if (m_Owner != null)
|
||||
list.Add(1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~
|
||||
else
|
||||
base.AddNameProperty(list);
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
{
|
||||
if (m_Owner != null)
|
||||
{
|
||||
LabelTo(from, 1042887, m_Owner.Name); // a strong box owned by ~1_OWNER_NAME~
|
||||
|
||||
if (CheckContentDisplay(from))
|
||||
LabelTo(from, "({0} items, {1} stones)", TotalItems, TotalWeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnSingleClick(from);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsAccessibleTo(Mobile m) =>
|
||||
m_Owner?.Deleted != false || m_House?.Deleted != false ||
|
||||
m.AccessLevel >= AccessLevel.GameMaster ||
|
||||
m == m_Owner && m_House.IsCoOwner(m) && base.IsAccessibleTo(m);
|
||||
|
||||
private void Chop(Mobile from)
|
||||
{
|
||||
Effects.PlaySound(Location, Map, 0x3B3);
|
||||
from.SendLocalizedMessage(500461); // You destroy the item.
|
||||
Destroy();
|
||||
}
|
||||
|
||||
public Container ConvertToStandardContainer()
|
||||
{
|
||||
Container metalBox = new MetalBox();
|
||||
var subItems = new List<Item>(Items);
|
||||
|
||||
foreach (var subItem in subItems) metalBox.AddItem(subItem);
|
||||
|
||||
Delete();
|
||||
|
||||
return metalBox;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,224 +1,224 @@
|
|||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public enum TrapType
|
||||
{
|
||||
None,
|
||||
MagicTrap,
|
||||
ExplosionTrap,
|
||||
DartTrap,
|
||||
PoisonTrap
|
||||
}
|
||||
|
||||
public abstract class TrappableContainer : BaseContainer, ITelekinesisable
|
||||
{
|
||||
public TrappableContainer(int itemID) : base(itemID)
|
||||
{
|
||||
}
|
||||
|
||||
public TrappableContainer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TrapType TrapType { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int TrapPower { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int TrapLevel { get; set; }
|
||||
|
||||
public virtual bool TrapOnOpen => true;
|
||||
|
||||
public virtual void OnTelekinesis(Mobile from)
|
||||
{
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022);
|
||||
Effects.PlaySound(Location, Map, 0x1F5);
|
||||
|
||||
if (TrapOnOpen) ExecuteTrap(from);
|
||||
}
|
||||
|
||||
private void SendMessageTo(Mobile to, int number, int hue)
|
||||
{
|
||||
if (Deleted || !to.CanSee(this))
|
||||
return;
|
||||
|
||||
to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, "", ""));
|
||||
}
|
||||
|
||||
private void SendMessageTo(Mobile to, string text, int hue)
|
||||
{
|
||||
if (Deleted || !to.CanSee(this))
|
||||
return;
|
||||
|
||||
to.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, hue, 3, "ENU", "", text));
|
||||
}
|
||||
|
||||
public virtual bool ExecuteTrap(Mobile from)
|
||||
{
|
||||
if (TrapType != TrapType.None)
|
||||
{
|
||||
Point3D loc = GetWorldLocation();
|
||||
Map facet = Map;
|
||||
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
SendMessageTo(from, "That is trapped, but you open it with your godly powers.", 0x3B2);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (TrapType)
|
||||
{
|
||||
case TrapType.ExplosionTrap:
|
||||
{
|
||||
SendMessageTo(from, 502999, 0x3B2); // You set off a trap!
|
||||
|
||||
if (from.InRange(loc, 3))
|
||||
{
|
||||
int damage;
|
||||
|
||||
if (TrapLevel > 0)
|
||||
damage = Utility.RandomMinMax(10, 30) * TrapLevel;
|
||||
else
|
||||
damage = TrapPower;
|
||||
|
||||
AOS.Damage(from, damage, 0, 100, 0, 0, 0);
|
||||
|
||||
// Your skin blisters from the heat!
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x2A, 503000);
|
||||
}
|
||||
|
||||
Effects.SendLocationEffect(loc, facet, 0x36BD, 15, 10);
|
||||
Effects.PlaySound(loc, facet, 0x307);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrapType.MagicTrap:
|
||||
{
|
||||
if (from.InRange(loc, 1))
|
||||
from.Damage(TrapPower);
|
||||
// AOS.Damage( from, m_TrapPower, 0, 100, 0, 0, 0 );
|
||||
|
||||
Effects.PlaySound(loc, Map, 0x307);
|
||||
|
||||
Effects.SendLocationEffect(new Point3D(loc.X - 1, loc.Y, loc.Z), Map, 0x36BD, 15);
|
||||
Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y, loc.Z), Map, 0x36BD, 15);
|
||||
|
||||
Effects.SendLocationEffect(new Point3D(loc.X, loc.Y - 1, loc.Z), Map, 0x36BD, 15);
|
||||
Effects.SendLocationEffect(new Point3D(loc.X, loc.Y + 1, loc.Z), Map, 0x36BD, 15);
|
||||
|
||||
Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y + 1, loc.Z + 11), Map, 0x36BD, 15);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrapType.DartTrap:
|
||||
{
|
||||
SendMessageTo(from, 502999, 0x3B2); // You set off a trap!
|
||||
|
||||
if (from.InRange(loc, 3))
|
||||
{
|
||||
int damage;
|
||||
|
||||
if (TrapLevel > 0)
|
||||
damage = Utility.RandomMinMax(5, 15) * TrapLevel;
|
||||
else
|
||||
damage = TrapPower;
|
||||
|
||||
AOS.Damage(from, damage, 100, 0, 0, 0, 0);
|
||||
|
||||
// A dart imbeds itself in your flesh!
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x62, 502998);
|
||||
}
|
||||
|
||||
Effects.PlaySound(loc, facet, 0x223);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrapType.PoisonTrap:
|
||||
{
|
||||
SendMessageTo(from, 502999, 0x3B2); // You set off a trap!
|
||||
|
||||
if (from.InRange(loc, 3))
|
||||
{
|
||||
Poison poison;
|
||||
|
||||
if (TrapLevel > 0)
|
||||
{
|
||||
poison = Poison.GetPoison(Math.Max(0, Math.Min(4, TrapLevel - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
AOS.Damage(from, TrapPower, 0, 0, 0, 100, 0);
|
||||
poison = Poison.Greater;
|
||||
}
|
||||
|
||||
from.ApplyPoison(from, poison);
|
||||
|
||||
// You are enveloped in a noxious green cloud!
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x44, 503004);
|
||||
}
|
||||
|
||||
Effects.SendLocationEffect(loc, facet, 0x113A, 10, 20);
|
||||
Effects.PlaySound(loc, facet, 0x231);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TrapType = TrapType.None;
|
||||
TrapPower = 0;
|
||||
TrapLevel = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Open(Mobile from)
|
||||
{
|
||||
if (!TrapOnOpen || !ExecuteTrap(from))
|
||||
base.Open(from);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(2); // version
|
||||
|
||||
writer.Write(TrapLevel);
|
||||
|
||||
writer.Write(TrapPower);
|
||||
writer.Write((int)TrapType);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
TrapLevel = reader.ReadInt();
|
||||
goto case 1;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TrapPower = reader.ReadInt();
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
TrapType = (TrapType)reader.ReadInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public enum TrapType
|
||||
{
|
||||
None,
|
||||
MagicTrap,
|
||||
ExplosionTrap,
|
||||
DartTrap,
|
||||
PoisonTrap
|
||||
}
|
||||
|
||||
public abstract class TrappableContainer : BaseContainer, ITelekinesisable
|
||||
{
|
||||
public TrappableContainer(int itemID) : base(itemID)
|
||||
{
|
||||
}
|
||||
|
||||
public TrappableContainer(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public TrapType TrapType { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int TrapPower { get; set; }
|
||||
|
||||
[CommandProperty(AccessLevel.GameMaster)]
|
||||
public int TrapLevel { get; set; }
|
||||
|
||||
public virtual bool TrapOnOpen => true;
|
||||
|
||||
public virtual void OnTelekinesis(Mobile from)
|
||||
{
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x376A, 9, 32, 5022);
|
||||
Effects.PlaySound(Location, Map, 0x1F5);
|
||||
|
||||
if (TrapOnOpen) ExecuteTrap(from);
|
||||
}
|
||||
|
||||
private void SendMessageTo(Mobile to, int number, int hue)
|
||||
{
|
||||
if (Deleted || !to.CanSee(this))
|
||||
return;
|
||||
|
||||
to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, "", ""));
|
||||
}
|
||||
|
||||
private void SendMessageTo(Mobile to, string text, int hue)
|
||||
{
|
||||
if (Deleted || !to.CanSee(this))
|
||||
return;
|
||||
|
||||
to.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, hue, 3, "ENU", "", text));
|
||||
}
|
||||
|
||||
public virtual bool ExecuteTrap(Mobile from)
|
||||
{
|
||||
if (TrapType != TrapType.None)
|
||||
{
|
||||
var loc = GetWorldLocation();
|
||||
var facet = Map;
|
||||
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
SendMessageTo(from, "That is trapped, but you open it with your godly powers.", 0x3B2);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (TrapType)
|
||||
{
|
||||
case TrapType.ExplosionTrap:
|
||||
{
|
||||
SendMessageTo(from, 502999, 0x3B2); // You set off a trap!
|
||||
|
||||
if (from.InRange(loc, 3))
|
||||
{
|
||||
int damage;
|
||||
|
||||
if (TrapLevel > 0)
|
||||
damage = Utility.RandomMinMax(10, 30) * TrapLevel;
|
||||
else
|
||||
damage = TrapPower;
|
||||
|
||||
AOS.Damage(from, damage, 0, 100, 0, 0, 0);
|
||||
|
||||
// Your skin blisters from the heat!
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x2A, 503000);
|
||||
}
|
||||
|
||||
Effects.SendLocationEffect(loc, facet, 0x36BD, 15, 10);
|
||||
Effects.PlaySound(loc, facet, 0x307);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrapType.MagicTrap:
|
||||
{
|
||||
if (from.InRange(loc, 1))
|
||||
from.Damage(TrapPower);
|
||||
// AOS.Damage( from, m_TrapPower, 0, 100, 0, 0, 0 );
|
||||
|
||||
Effects.PlaySound(loc, Map, 0x307);
|
||||
|
||||
Effects.SendLocationEffect(new Point3D(loc.X - 1, loc.Y, loc.Z), Map, 0x36BD, 15);
|
||||
Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y, loc.Z), Map, 0x36BD, 15);
|
||||
|
||||
Effects.SendLocationEffect(new Point3D(loc.X, loc.Y - 1, loc.Z), Map, 0x36BD, 15);
|
||||
Effects.SendLocationEffect(new Point3D(loc.X, loc.Y + 1, loc.Z), Map, 0x36BD, 15);
|
||||
|
||||
Effects.SendLocationEffect(new Point3D(loc.X + 1, loc.Y + 1, loc.Z + 11), Map, 0x36BD, 15);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrapType.DartTrap:
|
||||
{
|
||||
SendMessageTo(from, 502999, 0x3B2); // You set off a trap!
|
||||
|
||||
if (from.InRange(loc, 3))
|
||||
{
|
||||
int damage;
|
||||
|
||||
if (TrapLevel > 0)
|
||||
damage = Utility.RandomMinMax(5, 15) * TrapLevel;
|
||||
else
|
||||
damage = TrapPower;
|
||||
|
||||
AOS.Damage(from, damage, 100, 0, 0, 0, 0);
|
||||
|
||||
// A dart imbeds itself in your flesh!
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x62, 502998);
|
||||
}
|
||||
|
||||
Effects.PlaySound(loc, facet, 0x223);
|
||||
|
||||
break;
|
||||
}
|
||||
case TrapType.PoisonTrap:
|
||||
{
|
||||
SendMessageTo(from, 502999, 0x3B2); // You set off a trap!
|
||||
|
||||
if (from.InRange(loc, 3))
|
||||
{
|
||||
Poison poison;
|
||||
|
||||
if (TrapLevel > 0)
|
||||
{
|
||||
poison = Poison.GetPoison(Math.Max(0, Math.Min(4, TrapLevel - 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
AOS.Damage(from, TrapPower, 0, 0, 0, 100, 0);
|
||||
poison = Poison.Greater;
|
||||
}
|
||||
|
||||
from.ApplyPoison(from, poison);
|
||||
|
||||
// You are enveloped in a noxious green cloud!
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x44, 503004);
|
||||
}
|
||||
|
||||
Effects.SendLocationEffect(loc, facet, 0x113A, 10, 20);
|
||||
Effects.PlaySound(loc, facet, 0x231);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TrapType = TrapType.None;
|
||||
TrapPower = 0;
|
||||
TrapLevel = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void Open(Mobile from)
|
||||
{
|
||||
if (!TrapOnOpen || !ExecuteTrap(from))
|
||||
base.Open(from);
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(2); // version
|
||||
|
||||
writer.Write(TrapLevel);
|
||||
|
||||
writer.Write(TrapPower);
|
||||
writer.Write((int)TrapType);
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
TrapLevel = reader.ReadInt();
|
||||
goto case 1;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
TrapPower = reader.ReadInt();
|
||||
goto case 0;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
TrapType = (TrapType)reader.ReadInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,83 +1,83 @@
|
|||
namespace Server.Items
|
||||
{
|
||||
[Flippable(0xe43, 0xe42)]
|
||||
public class WoodenTreasureChest : BaseTreasureChest
|
||||
{
|
||||
[Constructible]
|
||||
public WoodenTreasureChest() : base(0xE43)
|
||||
{
|
||||
}
|
||||
|
||||
public WoodenTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Flippable(0xe41, 0xe40)]
|
||||
public class MetalGoldenTreasureChest : BaseTreasureChest
|
||||
{
|
||||
[Constructible]
|
||||
public MetalGoldenTreasureChest() : base(0xE41)
|
||||
{
|
||||
}
|
||||
|
||||
public MetalGoldenTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Flippable(0x9ab, 0xe7c)]
|
||||
public class MetalTreasureChest : BaseTreasureChest
|
||||
{
|
||||
[Constructible]
|
||||
public MetalTreasureChest() : base(0x9AB)
|
||||
{
|
||||
}
|
||||
|
||||
public MetalTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Server.Items
|
||||
{
|
||||
[Flippable(0xe43, 0xe42)]
|
||||
public class WoodenTreasureChest : BaseTreasureChest
|
||||
{
|
||||
[Constructible]
|
||||
public WoodenTreasureChest() : base(0xE43)
|
||||
{
|
||||
}
|
||||
|
||||
public WoodenTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Flippable(0xe41, 0xe40)]
|
||||
public class MetalGoldenTreasureChest : BaseTreasureChest
|
||||
{
|
||||
[Constructible]
|
||||
public MetalGoldenTreasureChest() : base(0xE41)
|
||||
{
|
||||
}
|
||||
|
||||
public MetalGoldenTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
|
||||
[Flippable(0x9ab, 0xe7c)]
|
||||
public class MetalTreasureChest : BaseTreasureChest
|
||||
{
|
||||
[Constructible]
|
||||
public MetalTreasureChest() : base(0x9AB)
|
||||
{
|
||||
}
|
||||
|
||||
public MetalTreasureChest(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.Write(0); // version
|
||||
}
|
||||
|
||||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
var version = reader.ReadInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue