Some cleanup of contains keys and try get values (#246)
This commit is contained in:
parent
9cbb0cfd23
commit
a236617ad9
69 changed files with 3508 additions and 350 deletions
|
|
@ -197,7 +197,9 @@ namespace Server.Items
|
|||
var version = reader.ReadInt();
|
||||
|
||||
if (version == 0 && Weight == 1.0)
|
||||
{
|
||||
Weight = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +265,9 @@ namespace Server.Items
|
|||
public override void DisplayTo(Mobile m)
|
||||
{
|
||||
if (DynamicFurniture.Open(this, m))
|
||||
{
|
||||
base.DisplayTo(m);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
|
|
@ -295,7 +299,9 @@ namespace Server.Items
|
|||
public override void DisplayTo(Mobile m)
|
||||
{
|
||||
if (DynamicFurniture.Open(this, m))
|
||||
{
|
||||
base.DisplayTo(m);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
|
|
@ -349,13 +355,13 @@ namespace Server.Items
|
|||
|
||||
public static void Close(Container c)
|
||||
{
|
||||
if (m_Table.TryGetValue(c, out var t))
|
||||
if (m_Table.Remove(c, out var t))
|
||||
{
|
||||
t.Stop();
|
||||
m_Table.Remove(c);
|
||||
}
|
||||
|
||||
if (c is Armoire || c is FancyArmoire)
|
||||
{
|
||||
c.ItemID = c.ItemID switch
|
||||
{
|
||||
0xA4C => 0xA4D,
|
||||
|
|
@ -364,6 +370,7 @@ namespace Server.Items
|
|||
0xA52 => 0xA53,
|
||||
_ => c.ItemID
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +390,9 @@ namespace Server.Items
|
|||
protected override void OnTick()
|
||||
{
|
||||
if (m_Mobile.Map != m_Container.Map || !m_Mobile.InRange(m_Container.GetWorldLocation(), 3))
|
||||
{
|
||||
DynamicFurniture.Close(m_Container);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace Server.Items
|
|||
public override int ComputeItemID()
|
||||
{
|
||||
if (!IsEmpty)
|
||||
{
|
||||
switch (Content)
|
||||
{
|
||||
case BeverageType.Ale: return 0x99F;
|
||||
|
|
@ -61,6 +62,7 @@ namespace Server.Items
|
|||
case BeverageType.Wine: return 0x9C7;
|
||||
case BeverageType.Water: return 0x99B;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -127,7 +129,9 @@ namespace Server.Items
|
|||
public override int ComputeItemID()
|
||||
{
|
||||
if (!IsEmpty)
|
||||
{
|
||||
return 0x9C8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -168,9 +172,14 @@ namespace Server.Items
|
|||
public override int ComputeItemID()
|
||||
{
|
||||
if (ItemID >= 0x995 && ItemID <= 0x999)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
if (ItemID == 0x9CA)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x995;
|
||||
}
|
||||
|
|
@ -211,7 +220,9 @@ namespace Server.Items
|
|||
public override int ComputeItemID()
|
||||
{
|
||||
if (ItemID >= 0xFFF && ItemID <= 0x1002)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0xFFF;
|
||||
}
|
||||
|
|
@ -252,7 +263,9 @@ namespace Server.Items
|
|||
public override int ComputeItemID()
|
||||
{
|
||||
if (ItemID == 0x99A || ItemID == 0x9B3 || ItemID == 0x9BF || ItemID == 0x9CB)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x99A;
|
||||
}
|
||||
|
|
@ -302,7 +315,9 @@ namespace Server.Items
|
|||
public override int ComputeItemID()
|
||||
{
|
||||
if (IsEmpty)
|
||||
{
|
||||
return ItemID >= 0x1F81 && ItemID <= 0x1F84 ? ItemID : 0x1F81;
|
||||
}
|
||||
|
||||
return Content switch
|
||||
{
|
||||
|
|
@ -406,7 +421,9 @@ namespace Server.Items
|
|||
if (IsEmpty)
|
||||
{
|
||||
if (ItemID == 0x9A7 || ItemID == 0xFF7)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0xFF6;
|
||||
}
|
||||
|
|
@ -416,42 +433,54 @@ namespace Server.Items
|
|||
case BeverageType.Ale:
|
||||
{
|
||||
if (ItemID == 0x1F96)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x1F95;
|
||||
}
|
||||
case BeverageType.Cider:
|
||||
{
|
||||
if (ItemID == 0x1F98)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x1F97;
|
||||
}
|
||||
case BeverageType.Liquor:
|
||||
{
|
||||
if (ItemID == 0x1F9A)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x1F99;
|
||||
}
|
||||
case BeverageType.Milk:
|
||||
{
|
||||
if (ItemID == 0x9AD)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x9F0;
|
||||
}
|
||||
case BeverageType.Wine:
|
||||
{
|
||||
if (ItemID == 0x1F9C)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x1F9B;
|
||||
}
|
||||
case BeverageType.Water:
|
||||
{
|
||||
if (ItemID == 0xFF8 || ItemID == 0xFF9 || ItemID == 0x1F9E)
|
||||
{
|
||||
return ItemID;
|
||||
}
|
||||
|
||||
return 0x1F9D;
|
||||
}
|
||||
|
|
@ -470,9 +499,13 @@ namespace Server.Items
|
|||
public override void Deserialize(IGenericReader reader)
|
||||
{
|
||||
if (CheckType("PitcherWater") || CheckType("GlassPitcher"))
|
||||
{
|
||||
InternalDeserialize(reader, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalDeserialize(reader, true);
|
||||
}
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
|
|
@ -565,7 +598,9 @@ namespace Server.Items
|
|||
var num = BaseLabelNumber;
|
||||
|
||||
if (IsEmpty || num == 0)
|
||||
{
|
||||
return EmptyLabelNumber;
|
||||
}
|
||||
|
||||
return BaseLabelNumber + (int)m_Content;
|
||||
}
|
||||
|
|
@ -608,9 +643,13 @@ namespace Server.Items
|
|||
var itemID = ComputeItemID();
|
||||
|
||||
if (itemID > 0)
|
||||
{
|
||||
ItemID = itemID;
|
||||
}
|
||||
else
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -627,9 +666,13 @@ namespace Server.Items
|
|||
var itemID = ComputeItemID();
|
||||
|
||||
if (itemID > 0)
|
||||
{
|
||||
ItemID = itemID;
|
||||
}
|
||||
else
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -640,11 +683,20 @@ namespace Server.Items
|
|||
var perc = m_Quantity * 100 / MaxQuantity;
|
||||
|
||||
if (perc <= 0)
|
||||
{
|
||||
return 1042975; // It's empty.
|
||||
}
|
||||
|
||||
if (perc <= 33)
|
||||
{
|
||||
return 1042974; // It's nearly empty.
|
||||
}
|
||||
|
||||
if (perc <= 66)
|
||||
{
|
||||
return 1042973; // It's half full.
|
||||
}
|
||||
|
||||
return 1042972; // It's full.
|
||||
}
|
||||
|
||||
|
|
@ -653,7 +705,9 @@ namespace Server.Items
|
|||
base.GetProperties(list);
|
||||
|
||||
if (ShowQuantity)
|
||||
{
|
||||
list.Add(GetQuantityDescription());
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
|
|
@ -661,13 +715,17 @@ namespace Server.Items
|
|||
base.OnSingleClick(from);
|
||||
|
||||
if (ShowQuantity)
|
||||
{
|
||||
LabelTo(from, GetQuantityDescription());
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool ValidateUse(Mobile from, bool message)
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Movable && !Fillable)
|
||||
{
|
||||
|
|
@ -676,7 +734,9 @@ namespace Server.Items
|
|||
if (house?.HasLockedDownItem(this) != true)
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
from.SendLocalizedMessage(502946, "", 0x59); // That belongs to someone else.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -685,7 +745,9 @@ namespace Server.Items
|
|||
if (from.Map != Map || !from.InRange(GetWorldLocation(), 2) || !from.InLOS(this))
|
||||
{
|
||||
if (message)
|
||||
{
|
||||
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -696,12 +758,16 @@ namespace Server.Items
|
|||
public virtual void Fill_OnTarget(Mobile from, object targ)
|
||||
{
|
||||
if (!IsEmpty || !Fillable || !ValidateUse(from, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (targ is BaseBeverage bev)
|
||||
{
|
||||
if (bev.IsEmpty || !bev.ValidateUse(from, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Content = bev.Content;
|
||||
Poison = bev.Poison;
|
||||
|
|
@ -739,10 +805,14 @@ namespace Server.Items
|
|||
var src = item as IWaterSource;
|
||||
|
||||
if (src == null && item is AddonComponent component)
|
||||
{
|
||||
src = component.Addon as IWaterSource;
|
||||
}
|
||||
|
||||
if (src == null || src.Quantity <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (from.Map != item.Map || !from.InRange(item.GetWorldLocation(), 2) || !from.InLOS(item))
|
||||
{
|
||||
|
|
@ -785,7 +855,9 @@ namespace Server.Items
|
|||
var qs = player.Quest;
|
||||
|
||||
if (!(qs is WitchApprenticeQuest))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = qs.FindObjective<FindIngredientObjective>();
|
||||
|
||||
|
|
@ -794,7 +866,9 @@ namespace Server.Items
|
|||
var contains = false;
|
||||
|
||||
for (var i = 0; !contains && i < m_SwampTiles.Length; i += 2)
|
||||
{
|
||||
contains = tileID >= m_SwampTiles[i] && tileID <= m_SwampTiles[i + 1];
|
||||
}
|
||||
|
||||
if (contains)
|
||||
{
|
||||
|
|
@ -813,12 +887,16 @@ namespace Server.Items
|
|||
public virtual void Pour_OnTarget(Mobile from, object targ)
|
||||
{
|
||||
if (IsEmpty || !Pourable || !ValidateUse(from, false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (targ is BaseBeverage bev)
|
||||
{
|
||||
if (!bev.ValidateUse(from, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bev.IsFull && bev.Content == Content)
|
||||
{
|
||||
|
|
@ -851,7 +929,9 @@ namespace Server.Items
|
|||
else if (from == targ)
|
||||
{
|
||||
if (from.Thirst < 20)
|
||||
{
|
||||
from.Thirst += 1;
|
||||
}
|
||||
|
||||
if (ContainsAlchohol)
|
||||
{
|
||||
|
|
@ -872,7 +952,9 @@ namespace Server.Items
|
|||
from.PlaySound(Utility.RandomList(0x30, 0x2D6));
|
||||
|
||||
if (Poison != null)
|
||||
{
|
||||
from.ApplyPoison(Poisoner, Poison);
|
||||
}
|
||||
|
||||
--Quantity;
|
||||
}
|
||||
|
|
@ -908,6 +990,7 @@ namespace Server.Items
|
|||
Content == BeverageType.Water)
|
||||
{
|
||||
if (from is PlayerMobile player)
|
||||
{
|
||||
if (player.Quest is SolenMatriarchQuest qs)
|
||||
{
|
||||
QuestObjective obj = qs.FindObjective<GatherWaterObjective>();
|
||||
|
|
@ -934,6 +1017,7 @@ namespace Server.Items
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -946,7 +1030,9 @@ namespace Server.Items
|
|||
if (IsEmpty)
|
||||
{
|
||||
if (!Fillable || !ValidateUse(from, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
from.BeginTarget(-1, true, TargetFlags.None, Fill_OnTarget);
|
||||
SendLocalizedMessageTo(from, 500837); // Fill from what?
|
||||
|
|
@ -969,8 +1055,12 @@ namespace Server.Items
|
|||
var total = 0;
|
||||
|
||||
for (var i = 0; i < items.Length; ++i)
|
||||
{
|
||||
if (items[i] is BaseBeverage bev && bev.Content == content && !bev.IsEmpty)
|
||||
{
|
||||
total += bev.Quantity;
|
||||
}
|
||||
}
|
||||
|
||||
if (total >= quantity)
|
||||
{
|
||||
|
|
@ -981,7 +1071,9 @@ namespace Server.Items
|
|||
for (var i = 0; i < items.Length; ++i)
|
||||
{
|
||||
if (!(items[i] is BaseBeverage bev) || bev.Content != content || bev.IsEmpty)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var theirQuantity = bev.Quantity;
|
||||
|
||||
|
|
@ -1026,7 +1118,9 @@ namespace Server.Items
|
|||
base.Deserialize(reader);
|
||||
|
||||
if (!read)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var version = reader.ReadInt();
|
||||
|
||||
|
|
@ -1062,20 +1156,23 @@ namespace Server.Items
|
|||
if (from.BAC > 0 && from.Map != Map.Internal && !from.Deleted)
|
||||
{
|
||||
if (m_Table.ContainsKey(from))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (from.BAC > 60)
|
||||
{
|
||||
from.BAC = 60;
|
||||
}
|
||||
|
||||
Timer t = new HeaveTimer(from);
|
||||
t.Start();
|
||||
|
||||
m_Table[from] = t;
|
||||
}
|
||||
else if (m_Table.TryGetValue(from, out var t))
|
||||
else if (m_Table.Remove(from, out var t))
|
||||
{
|
||||
t.Stop();
|
||||
m_Table.Remove(from);
|
||||
|
||||
from.SendLocalizedMessage(500850); // You feel sober.
|
||||
}
|
||||
|
|
@ -1103,11 +1200,15 @@ namespace Server.Items
|
|||
else if (m_Drunk.Alive)
|
||||
{
|
||||
if (m_Drunk.BAC > 60)
|
||||
{
|
||||
m_Drunk.BAC = 60;
|
||||
}
|
||||
|
||||
// chance to get sober
|
||||
if (Utility.Random(100) < 10)
|
||||
{
|
||||
--m_Drunk.BAC;
|
||||
}
|
||||
|
||||
// lose some stats
|
||||
m_Drunk.Stam -= 1;
|
||||
|
|
|
|||
|
|
@ -147,7 +147,9 @@ namespace Server.Items
|
|||
}
|
||||
|
||||
if (!isBaseCreature && !info.CriminalAggression)
|
||||
{
|
||||
Aggressors.Add(info.Attacker);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < owner.Aggressed.Count; ++i)
|
||||
|
|
@ -161,7 +163,9 @@ namespace Server.Items
|
|||
}
|
||||
|
||||
if (!isBaseCreature)
|
||||
{
|
||||
Aggressors.Add(info.Defender);
|
||||
}
|
||||
}
|
||||
|
||||
if (isBaseCreature)
|
||||
|
|
@ -170,7 +174,9 @@ namespace Server.Items
|
|||
|
||||
var master = bc.GetMaster();
|
||||
if (master != null)
|
||||
{
|
||||
Aggressors.Add(master);
|
||||
}
|
||||
|
||||
var rights = BaseCreature.GetLootingRights(bc.DamageEntries, bc.HitsMax);
|
||||
for (var i = 0; i < rights.Count; ++i)
|
||||
|
|
@ -178,7 +184,9 @@ namespace Server.Items
|
|||
var ds = rights[i];
|
||||
|
||||
if (ds.m_HasRight)
|
||||
{
|
||||
Aggressors.Add(ds.m_Mobile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -282,9 +290,13 @@ namespace Server.Items
|
|||
if (IsCriminalAction(from) && (Map?.Rules & MapRules.HarmfulRestrictions) != 0)
|
||||
{
|
||||
if (Owner?.Player != true)
|
||||
{
|
||||
from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature!
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010049); // You may not loot this corpse.
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -315,7 +327,9 @@ namespace Server.Items
|
|||
ProcessDelta();
|
||||
|
||||
if (IsCriminalAction(from))
|
||||
{
|
||||
from.CriminalAction(true);
|
||||
}
|
||||
}
|
||||
else if (dead is BaseCreature creature)
|
||||
{
|
||||
|
|
@ -335,7 +349,9 @@ namespace Server.Items
|
|||
private void AssignInstancedLoot()
|
||||
{
|
||||
if (Aggressors.Count == 0 || Items.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_InstancedItems ??= new Dictionary<Item, InstancedItemInfo>();
|
||||
|
||||
|
|
@ -349,9 +365,13 @@ namespace Server.Items
|
|||
if (item.LootType != LootType.Cursed) // Don't have cursed items take up someone's item spot.. (?)
|
||||
{
|
||||
if (item.Stackable)
|
||||
{
|
||||
m_Stackables.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Unstackables.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -392,9 +412,13 @@ namespace Server.Items
|
|||
}
|
||||
|
||||
if (remainder == 0)
|
||||
{
|
||||
m_InstancedItems.Add(item, new InstancedItemInfo(item, attackers[^1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Unstackables.Add(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -427,7 +451,9 @@ namespace Server.Items
|
|||
public void TurnToBones()
|
||||
{
|
||||
if (Deleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ProcessDelta();
|
||||
SendRemovePacket();
|
||||
|
|
@ -481,18 +507,28 @@ namespace Server.Items
|
|||
var item = initialContent[i];
|
||||
|
||||
if (Core.AOS && owner.Player && item.Parent == owner.Backpack)
|
||||
{
|
||||
c.AddItem(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.DropItem(item);
|
||||
}
|
||||
|
||||
if (owner.Player && Core.AOS)
|
||||
{
|
||||
c.SetRestoreInfo(item, item.Location);
|
||||
}
|
||||
}
|
||||
|
||||
if (Core.SE && !owner.Player)
|
||||
{
|
||||
c.AssignInstancedLoot();
|
||||
}
|
||||
else if (Core.AOS && owner is PlayerMobile pm)
|
||||
{
|
||||
c.RestoreEquip = pm.EquipSnapshot;
|
||||
}
|
||||
|
||||
var loc = owner.Location;
|
||||
var map = owner.Map;
|
||||
|
|
@ -539,6 +575,7 @@ namespace Server.Items
|
|||
writer.Write(count);
|
||||
|
||||
if (m_RestoreTable != null)
|
||||
{
|
||||
foreach (var (item, loc) in m_RestoreTable)
|
||||
{
|
||||
writer.Write(item);
|
||||
|
|
@ -553,11 +590,14 @@ namespace Server.Items
|
|||
writer.Write(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.Write(m_DecayTimer != null);
|
||||
|
||||
if (m_DecayTimer != null)
|
||||
{
|
||||
writer.WriteDeltaTime(m_DecayTime);
|
||||
}
|
||||
|
||||
writer.Write(Looters);
|
||||
writer.Write(Killer);
|
||||
|
|
@ -586,7 +626,9 @@ namespace Server.Items
|
|||
case 12:
|
||||
{
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
RestoreEquip = reader.ReadStrongItemList();
|
||||
}
|
||||
|
||||
goto case 11;
|
||||
}
|
||||
|
|
@ -604,13 +646,19 @@ namespace Server.Items
|
|||
var item = reader.ReadItem();
|
||||
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
SetRestoreInfo(item, reader.ReadPoint3D());
|
||||
}
|
||||
else if (item != null)
|
||||
{
|
||||
SetRestoreInfo(item, item.Location);
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow);
|
||||
}
|
||||
|
||||
Looters = reader.ReadStrongMobileList();
|
||||
Killer = reader.ReadMobile();
|
||||
|
|
@ -642,9 +690,13 @@ namespace Server.Items
|
|||
var item = reader.ReadItem();
|
||||
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
SetRestoreInfo(item, reader.ReadPoint3D());
|
||||
}
|
||||
else if (item != null)
|
||||
{
|
||||
SetRestoreInfo(item, item.Location);
|
||||
}
|
||||
}
|
||||
|
||||
goto case 8;
|
||||
|
|
@ -658,7 +710,9 @@ namespace Server.Items
|
|||
case 7:
|
||||
{
|
||||
if (reader.ReadBool())
|
||||
{
|
||||
BeginDecay(reader.ReadDeltaTime() - DateTime.UtcNow);
|
||||
}
|
||||
|
||||
goto case 6;
|
||||
}
|
||||
|
|
@ -702,16 +756,24 @@ namespace Server.Items
|
|||
case 0:
|
||||
{
|
||||
if (version < 10)
|
||||
{
|
||||
TimeOfDeath = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
if (version < 7)
|
||||
{
|
||||
BeginDecay(m_DefaultDecayTime);
|
||||
}
|
||||
|
||||
if (version < 6)
|
||||
{
|
||||
Looters = new List<Mobile>();
|
||||
}
|
||||
|
||||
if (version < 4)
|
||||
{
|
||||
Aggressors = new List<Mobile>();
|
||||
}
|
||||
|
||||
AccessLevel = (AccessLevel)reader.ReadInt();
|
||||
reader.ReadInt(); // guild reserve
|
||||
|
|
@ -729,7 +791,9 @@ namespace Server.Items
|
|||
{
|
||||
if (Devoured || Deleted || Killer?.Deleted != false || !Killer.Alive || !(Killer is IDevourer devourer) ||
|
||||
Owner?.Deleted != false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_Devourer = devourer; // Set the devourer the killer
|
||||
return m_Devourer.Devour(this); // Devour the corpse if it hasn't
|
||||
|
|
@ -740,12 +804,18 @@ namespace Server.Items
|
|||
base.SendInfoTo(state, sendOplPacket);
|
||||
|
||||
if (!(((Body)Amount).IsHuman && ItemID == 0x2006))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.ContainerGridLines)
|
||||
{
|
||||
state.Send(new CorpseContent6017(state.Mobile, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
state.Send(new CorpseContent(state.Mobile, this));
|
||||
}
|
||||
|
||||
state.Send(new CorpseEquip(state.Mobile, this));
|
||||
}
|
||||
|
|
@ -753,7 +823,9 @@ namespace Server.Items
|
|||
public bool IsCriminalAction(Mobile from)
|
||||
{
|
||||
if (from == Owner || from.AccessLevel >= AccessLevel.GameMaster)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var p = Party.Get(Owner);
|
||||
|
||||
|
|
@ -762,7 +834,9 @@ namespace Server.Items
|
|||
var pmi = p[Owner];
|
||||
|
||||
if (pmi?.CanLoot == true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return NotorietyHandlers.CorpseNotoriety(from, this) == Notoriety.Innocent;
|
||||
|
|
@ -779,16 +853,22 @@ namespace Server.Items
|
|||
base.OnItemUsed(from, item);
|
||||
|
||||
if (item is Food)
|
||||
{
|
||||
from.RevealingAction();
|
||||
}
|
||||
|
||||
if (item != this && IsCriminalAction(from))
|
||||
{
|
||||
from.CriminalAction(true);
|
||||
}
|
||||
|
||||
if (!Looters.Contains(from))
|
||||
{
|
||||
Looters.Add(from);
|
||||
}
|
||||
|
||||
m_InstancedItems?.Remove(item);
|
||||
|
||||
if (m_InstancedItems?.ContainsKey(item) == true)
|
||||
m_InstancedItems.Remove(item);
|
||||
}
|
||||
|
||||
public override void OnItemLifted(Mobile from, Item item)
|
||||
|
|
@ -796,16 +876,21 @@ namespace Server.Items
|
|||
base.OnItemLifted(from, item);
|
||||
|
||||
if (item != this && from != Owner)
|
||||
{
|
||||
from.RevealingAction();
|
||||
}
|
||||
|
||||
if (item != this && IsCriminalAction(from))
|
||||
{
|
||||
from.CriminalAction(true);
|
||||
}
|
||||
|
||||
if (!Looters.Contains(from))
|
||||
{
|
||||
Looters.Add(from);
|
||||
}
|
||||
|
||||
if (m_InstancedItems?.ContainsKey(item) == true)
|
||||
m_InstancedItems.Remove(item);
|
||||
m_InstancedItems?.Remove(item);
|
||||
}
|
||||
|
||||
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
|
||||
|
|
@ -813,7 +898,9 @@ namespace Server.Items
|
|||
base.GetContextMenuEntries(from, list);
|
||||
|
||||
if (Core.AOS && Owner == from && from.Alive)
|
||||
{
|
||||
list.Add(new OpenCorpseEntry());
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetRestoreInfo(Item item, ref Point3D loc) =>
|
||||
|
|
@ -822,7 +909,9 @@ namespace Server.Items
|
|||
public void SetRestoreInfo(Item item, Point3D loc)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_RestoreTable ??= new Dictionary<Item, Point3D>();
|
||||
|
||||
|
|
@ -832,12 +921,16 @@ namespace Server.Items
|
|||
public void ClearRestoreInfo(Item item)
|
||||
{
|
||||
if (m_RestoreTable == null || item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_RestoreTable.Remove(item);
|
||||
|
||||
if (m_RestoreTable.Count == 0)
|
||||
{
|
||||
m_RestoreTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanLoot(Mobile from, Item item) =>
|
||||
|
|
@ -848,9 +941,13 @@ namespace Server.Items
|
|||
if (!CanLoot(from, item))
|
||||
{
|
||||
if (Owner?.Player != true)
|
||||
{
|
||||
from.SendLocalizedMessage(1005035); // You did not earn the right to loot this creature!
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1010049); // You may not loot this corpse.
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -858,9 +955,13 @@ namespace Server.Items
|
|||
if (IsCriminalAction(from))
|
||||
{
|
||||
if (Owner?.Player != true)
|
||||
{
|
||||
from.SendLocalizedMessage(1005036); // Looting this monster corpse will be a criminal act!
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(1005038); // Looting this corpse will be a criminal act!
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -898,7 +999,9 @@ namespace Server.Items
|
|||
var packItem = packItems[i];
|
||||
|
||||
if (RestoreEquip.Contains(packItem) && packItem.Movable)
|
||||
{
|
||||
from.EquipItem(packItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -913,7 +1016,9 @@ namespace Server.Items
|
|||
|
||||
if (item.Layer == Layer.Hair || item.Layer == Layer.FacialHair || !item.Movable ||
|
||||
!GetRestoreInfo(item, ref loc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pack?.CheckHold(from, item, false, true) == true)
|
||||
{
|
||||
|
|
@ -921,7 +1026,9 @@ namespace Server.Items
|
|||
pack.AddItem(item);
|
||||
|
||||
if (RestoreEquip?.Contains(item) == true)
|
||||
{
|
||||
from.EquipItem(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -955,9 +1062,14 @@ namespace Server.Items
|
|||
}
|
||||
|
||||
if (!CheckLoot(from, null))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(from is PlayerMobile player)) return;
|
||||
if (!(from is PlayerMobile player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var qs = player.Quest;
|
||||
|
||||
|
|
@ -978,7 +1090,9 @@ namespace Server.Items
|
|||
); // You rummage through the bones and find a Daemon Bone! You quickly place the item in your pack.
|
||||
|
||||
if (!obj.Completed)
|
||||
{
|
||||
obj.Complete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1033,9 +1147,13 @@ namespace Server.Items
|
|||
if (ItemID == 0x2006) // Corpse form
|
||||
{
|
||||
if (m_CorpseName != null)
|
||||
{
|
||||
list.Add(m_CorpseName);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(1046414, Name); // the remains of ~1_NAME~
|
||||
}
|
||||
}
|
||||
else // Bone form
|
||||
{
|
||||
|
|
@ -1049,7 +1167,9 @@ namespace Server.Items
|
|||
var opl = PropertyList;
|
||||
|
||||
if (opl.Header > 0)
|
||||
{
|
||||
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs));
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
|
|
@ -1059,9 +1179,13 @@ namespace Server.Items
|
|||
if (ItemID == 0x2006) // Corpse form
|
||||
{
|
||||
if (m_CorpseName != null)
|
||||
{
|
||||
from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName));
|
||||
}
|
||||
else
|
||||
{
|
||||
from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name));
|
||||
}
|
||||
}
|
||||
else // Bone form
|
||||
{
|
||||
|
|
@ -1085,13 +1209,19 @@ namespace Server.Items
|
|||
public bool IsOwner(Mobile m)
|
||||
{
|
||||
if (m_Item.LootType == LootType.Cursed) // Cursed Items are part of everyone's instanced corpse... (?)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m == null)
|
||||
{
|
||||
return false; // sanity
|
||||
}
|
||||
|
||||
if (m_Mobile == m)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var myParty = Party.Get(m_Mobile);
|
||||
|
||||
|
|
@ -1112,9 +1242,13 @@ namespace Server.Items
|
|||
protected override void OnTick()
|
||||
{
|
||||
if (!m_Corpse.GetFlag(CorpseFlag.NoBones))
|
||||
{
|
||||
m_Corpse.TurnToBones();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Corpse.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1127,7 +1261,9 @@ namespace Server.Items
|
|||
public override void OnClick()
|
||||
{
|
||||
if (Owner.Target is Corpse corpse && Owner.From.CheckAlive())
|
||||
{
|
||||
corpse.Open(Owner.From, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,9 @@ namespace Server.Items
|
|||
public static void RemoveKeys(Mobile m, uint keyValue)
|
||||
{
|
||||
if (keyValue == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveKeys(m.Backpack, keyValue);
|
||||
RemoveKeys(m.BankBox, keyValue);
|
||||
|
|
@ -84,15 +86,20 @@ namespace Server.Items
|
|||
public static void RemoveKeys(Container cont, uint keyValue)
|
||||
{
|
||||
if (cont == null || keyValue == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) });
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is Key key)
|
||||
{
|
||||
if (key.KeyValue == keyValue)
|
||||
{
|
||||
key.Delete();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -100,28 +107,37 @@ namespace Server.Items
|
|||
|
||||
keyRing.RemoveKeys(keyValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ContainsKey(Container cont, uint keyValue)
|
||||
{
|
||||
if (cont == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var items = cont.FindItemsByType(new[] { typeof(Key), typeof(KeyRing) });
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is Key key)
|
||||
{
|
||||
if (key.KeyValue == keyValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var keyRing = (KeyRing)item;
|
||||
|
||||
if (keyRing.ContainsKey(keyValue))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -163,7 +179,9 @@ namespace Server.Items
|
|||
case 0:
|
||||
{
|
||||
if (version < 2 || MaxRange == 0)
|
||||
{
|
||||
MaxRange = 3;
|
||||
}
|
||||
|
||||
m_Description = reader.ReadString();
|
||||
|
||||
|
|
@ -207,12 +225,18 @@ namespace Server.Items
|
|||
string desc;
|
||||
|
||||
if (m_KeyVal == 0)
|
||||
{
|
||||
desc = "(blank)";
|
||||
}
|
||||
else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0)
|
||||
{
|
||||
desc = null;
|
||||
}
|
||||
|
||||
if (desc != null)
|
||||
{
|
||||
list.Add(desc);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnSingleClick(Mobile from)
|
||||
|
|
@ -222,12 +246,18 @@ namespace Server.Items
|
|||
string desc;
|
||||
|
||||
if (m_KeyVal == 0)
|
||||
{
|
||||
desc = "(blank)";
|
||||
}
|
||||
else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0)
|
||||
{
|
||||
desc = "";
|
||||
}
|
||||
|
||||
if (desc.Length > 0)
|
||||
{
|
||||
from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", "", desc));
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseOn(Mobile from, ILockable o)
|
||||
|
|
@ -235,30 +265,44 @@ namespace Server.Items
|
|||
if (o.KeyValue == KeyValue)
|
||||
{
|
||||
if (o is BaseDoor door && !door.UseLocks())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
o.Locked = !o.Locked;
|
||||
|
||||
if (o is LockableContainer cont1)
|
||||
{
|
||||
if (cont1.LockLevel == -255)
|
||||
{
|
||||
cont1.LockLevel = cont1.RequiredSkill - 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (o is Item item)
|
||||
{
|
||||
if (o.Locked)
|
||||
{
|
||||
item.SendLocalizedMessageTo(from, 1048000); // You lock it.
|
||||
}
|
||||
else
|
||||
{
|
||||
item.SendLocalizedMessageTo(from, 1048001); // You unlock it.
|
||||
}
|
||||
|
||||
if (item is LockableContainer cont && cont.TrapType != TrapType.None && cont.TrapOnLockpick)
|
||||
{
|
||||
if (o.Locked)
|
||||
{
|
||||
cont.SendLocalizedMessageTo(from, 501673); // You re-enable the trap.
|
||||
}
|
||||
else
|
||||
{
|
||||
cont.SendLocalizedMessageTo(
|
||||
from,
|
||||
501672
|
||||
); // You disable the trap temporarily. Lock it again to re-enable it.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -315,16 +359,23 @@ namespace Server.Items
|
|||
else if (targeted is ILockable lockable)
|
||||
{
|
||||
if (m_Key.UseOn(from, lockable))
|
||||
{
|
||||
number = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = 501668; // This key doesn't seem to unlock that.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
number = 501666; // You can't unlock that!
|
||||
}
|
||||
|
||||
if (number != -1) from.SendLocalizedMessage(number);
|
||||
if (number != -1)
|
||||
{
|
||||
from.SendLocalizedMessage(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,10 @@ namespace Server.Items
|
|||
{
|
||||
base.OnDelete();
|
||||
|
||||
foreach (var key in Keys) key.Delete();
|
||||
foreach (var key in Keys)
|
||||
{
|
||||
key.Delete();
|
||||
}
|
||||
|
||||
Keys.Clear();
|
||||
}
|
||||
|
|
@ -78,14 +81,18 @@ namespace Server.Items
|
|||
public void Open(Mobile from)
|
||||
{
|
||||
if (!(Parent is Container cont))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = Keys.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var key = Keys[i];
|
||||
|
||||
if (!key.Deleted && !cont.TryDropItem(from, key, true))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Keys.RemoveAt(i);
|
||||
}
|
||||
|
|
@ -112,8 +119,12 @@ namespace Server.Items
|
|||
public bool ContainsKey(uint keyValue)
|
||||
{
|
||||
foreach (var key in Keys)
|
||||
{
|
||||
if (key.KeyValue == keyValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -121,13 +132,21 @@ namespace Server.Items
|
|||
private void UpdateItemID()
|
||||
{
|
||||
if (Keys.Count < 1)
|
||||
{
|
||||
ItemID = 0x1011;
|
||||
}
|
||||
else if (Keys.Count < 3)
|
||||
{
|
||||
ItemID = 0x1769;
|
||||
}
|
||||
else if (Keys.Count < 5)
|
||||
{
|
||||
ItemID = 0x176A;
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemID = 0x176B;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(IGenericWriter writer)
|
||||
|
|
@ -170,8 +189,12 @@ namespace Server.Items
|
|||
else if (targeted is ILockable o)
|
||||
{
|
||||
foreach (var key in m_KeyRing.Keys)
|
||||
{
|
||||
if (key.UseOn(from, o))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(1008140); // You do not have a key for that.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -652,11 +652,10 @@ namespace Server.Items
|
|||
|
||||
public static void EventSink_Logout(Mobile from)
|
||||
{
|
||||
if (from == null || !m_Table.TryGetValue(from, out var info))
|
||||
return;
|
||||
|
||||
info.Timer.Stop();
|
||||
m_Table.Remove(from);
|
||||
if (from != null && m_Table.Remove(from, out var info))
|
||||
{
|
||||
info.Timer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatTime(TimeSpan ts)
|
||||
|
|
@ -802,10 +801,9 @@ namespace Server.Items
|
|||
|
||||
public void StopTimer(Mobile m)
|
||||
{
|
||||
if (m_Teleporting.TryGetValue(m, out var t))
|
||||
if (m_Teleporting.Remove(m, out var t))
|
||||
{
|
||||
t.Stop();
|
||||
m_Teleporting.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,10 +107,9 @@ namespace Server.Items
|
|||
|
||||
public static void EndDelay(Mobile m)
|
||||
{
|
||||
if (m_Delay.TryGetValue(m, out var timer))
|
||||
if (m_Delay.Remove(m, out var timer))
|
||||
{
|
||||
timer.Stop();
|
||||
m_Delay.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,10 +123,9 @@ namespace Server.Items
|
|||
|
||||
public static void EndDelay(Mobile m)
|
||||
{
|
||||
if (m_Delay.TryGetValue(m, out var timer))
|
||||
if (m_Delay.Remove(m, out var timer))
|
||||
{
|
||||
timer.Stop();
|
||||
m_Delay.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,12 +66,14 @@ namespace Server.Items
|
|||
|
||||
public static void RemoveTimer(Mobile m, bool interrupted = false)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out var timer))
|
||||
if (m_Table.Remove(m, out var timer))
|
||||
{
|
||||
if (interrupted)
|
||||
{
|
||||
m.SendLocalizedMessage(1073187); // The invisibility effect is interrupted.
|
||||
}
|
||||
|
||||
timer.Stop();
|
||||
m_Table.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -283,10 +283,9 @@ namespace Server.Items
|
|||
|
||||
public static void RemoveTimer(Mobile m)
|
||||
{
|
||||
if (Timers.TryGetValue(m, out var t))
|
||||
if (Timers.Remove(m, out var t))
|
||||
{
|
||||
t.Stop();
|
||||
Timers.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ namespace Server.Items
|
|||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
|
||||
|
|
@ -73,7 +75,9 @@ namespace Server.Items
|
|||
var damage = Utility.RandomMinMax(level, level * 2);
|
||||
|
||||
if (!m.Player)
|
||||
{
|
||||
damage *= 2;
|
||||
}
|
||||
|
||||
m.PlaySound(0x133);
|
||||
m.Damage(damage, from);
|
||||
|
|
@ -89,14 +93,17 @@ namespace Server.Items
|
|||
|
||||
public static void EndBleed(Mobile m, bool message)
|
||||
{
|
||||
if (!m_Table.TryGetValue(m, out var t))
|
||||
if (!m_Table.Remove(m, out var t))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
t.Stop();
|
||||
m_Table.Remove(m);
|
||||
|
||||
if (message)
|
||||
{
|
||||
m.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding!
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
|
|
@ -117,7 +124,9 @@ namespace Server.Items
|
|||
DoBleed(m_Mobile, m_From, 5 - m_Count);
|
||||
|
||||
if (++m_Count == 5)
|
||||
{
|
||||
EndBleed(m_Mobile, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ namespace Server.Items
|
|||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
|
||||
|
|
@ -49,7 +51,9 @@ namespace Server.Items
|
|||
public static bool GetBonus(Mobile targ, ref int bonus)
|
||||
{
|
||||
if (!m_Table.TryGetValue(targ, out var info))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bonus = info.m_Bonus;
|
||||
return true;
|
||||
|
|
@ -63,11 +67,10 @@ namespace Server.Items
|
|||
|
||||
public static void EndBlock(Mobile m)
|
||||
{
|
||||
if (!m_Table.TryGetValue(m, out var info))
|
||||
return;
|
||||
|
||||
info.m_Timer?.Stop();
|
||||
m_Table.Remove(m);
|
||||
if (m_Table.Remove(m, out var info))
|
||||
{
|
||||
info.m_Timer?.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockInfo
|
||||
|
|
|
|||
|
|
@ -19,7 +19,10 @@ namespace Server.Items
|
|||
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true)) return;
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
|
||||
|
|
@ -31,7 +34,9 @@ namespace Server.Items
|
|||
|
||||
// Do not reset timer if one is already in place.
|
||||
if (!IsWounded(defender))
|
||||
{
|
||||
BeginWound(defender, defender.Player ? PlayerDuration : NPCDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsWounded(Mobile m) => m_Table.ContainsKey(m);
|
||||
|
|
@ -39,7 +44,9 @@ namespace Server.Items
|
|||
public static void BeginWound(Mobile m, TimeSpan duration)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out var timer))
|
||||
{
|
||||
timer?.Stop();
|
||||
}
|
||||
|
||||
m_Table[m] = timer = new InternalTimer(m, duration);
|
||||
timer.Start();
|
||||
|
|
@ -49,10 +56,9 @@ namespace Server.Items
|
|||
|
||||
public static void EndWound(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out var timer))
|
||||
if (m_Table.Remove(m, out var timer))
|
||||
{
|
||||
timer.Stop();
|
||||
m_Table.Remove(m);
|
||||
}
|
||||
|
||||
m.YellowHealthbar = false;
|
||||
|
|
|
|||
|
|
@ -22,17 +22,17 @@ namespace Server.Items
|
|||
{
|
||||
if (!base.CheckSkills( from ))
|
||||
return false;
|
||||
|
||||
|
||||
if (!(from.Weapon is Fists))
|
||||
return true;
|
||||
|
||||
|
||||
Skill skill = from.Skills.Anatomy;
|
||||
|
||||
|
||||
if (skill?.Base >= 80.0)
|
||||
return true;
|
||||
|
||||
|
||||
from.SendLocalizedMessage( 1061811 ); // You lack the required anatomy skill to perform that attack!
|
||||
|
||||
|
||||
return false;
|
||||
}*/
|
||||
|
||||
|
|
@ -91,10 +91,9 @@ namespace Server.Items
|
|||
|
||||
public static void EndImmunity(Mobile m)
|
||||
{
|
||||
if (m_Table.TryGetValue(m, out var timer))
|
||||
if (m_Table.Remove(m, out var timer))
|
||||
{
|
||||
timer?.Stop();
|
||||
m_Table.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -71,11 +71,15 @@ namespace Server.Items
|
|||
canSwing = !attacker.Paralyzed && !attacker.Frozen;
|
||||
|
||||
if (canSwing)
|
||||
{
|
||||
canSwing = !(attacker.Spell is Spell sp) || !sp.IsCasting || !sp.BlocksMovement;
|
||||
}
|
||||
}
|
||||
|
||||
if ((attacker as PlayerMobile)?.DuelContext?.CheckItemEquip(attacker, this) == false)
|
||||
{
|
||||
canSwing = false;
|
||||
}
|
||||
|
||||
if (canSwing && attacker.HarmfulCheck(defender))
|
||||
{
|
||||
|
|
@ -85,9 +89,13 @@ namespace Server.Items
|
|||
if (OnFired(attacker, defender))
|
||||
{
|
||||
if (CheckHit(attacker, defender))
|
||||
{
|
||||
OnHit(attacker, defender);
|
||||
}
|
||||
else
|
||||
{
|
||||
OnMiss(attacker, defender);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +113,9 @@ namespace Server.Items
|
|||
{
|
||||
if (attacker.Player && !defender.Player && (defender.Body.IsAnimal || defender.Body.IsMonster) &&
|
||||
Utility.RandomDouble() <= 0.4)
|
||||
{
|
||||
defender.AddToBackpack(Ammo);
|
||||
}
|
||||
|
||||
if (Core.ML && m_Velocity > 0)
|
||||
{
|
||||
|
|
@ -116,10 +126,14 @@ namespace Server.Items
|
|||
AOS.Damage(defender, attacker, bonus * 3, 100, 0, 0, 0, 0);
|
||||
|
||||
if (attacker.Player)
|
||||
{
|
||||
attacker.SendLocalizedMessage(1072794); // Your arrow hits its mark with velocity!
|
||||
}
|
||||
|
||||
if (defender.Player)
|
||||
{
|
||||
defender.SendLocalizedMessage(1072795); // You have been hit by an arrow with velocity!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,17 +150,17 @@ namespace Server.Items
|
|||
{
|
||||
var ammo = AmmoType;
|
||||
|
||||
if (pm.RecoverableAmmo.ContainsKey(ammo))
|
||||
pm.RecoverableAmmo[ammo]++;
|
||||
else
|
||||
pm.RecoverableAmmo.Add(ammo, 1);
|
||||
pm.RecoverableAmmo.TryGetValue(ammo, out var result);
|
||||
pm.RecoverableAmmo[ammo] = result + 1;
|
||||
|
||||
if (!pm.Warmode)
|
||||
{
|
||||
m_RecoveryTimer ??= Timer.DelayCall(TimeSpan.FromSeconds(10), pm.RecoverAmmo);
|
||||
|
||||
if (!m_RecoveryTimer.Running)
|
||||
{
|
||||
m_RecoveryTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -177,9 +191,13 @@ namespace Server.Items
|
|||
{
|
||||
// consume ammo
|
||||
if (quiver?.ConsumeTotal(AmmoType) == true)
|
||||
{
|
||||
quiver.InvalidateWeight();
|
||||
}
|
||||
else if (pack?.ConsumeTotal(AmmoType) != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (quiver.FindItemByType(AmmoType) == null && pack?.FindItemByType(AmmoType) == null)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue