fix: Codegens blacksmith, camping, and carpenter skill items (#1278)

This commit is contained in:
Kamron Batman 2022-11-24 00:57:23 -08:00 • committed by GitHub
parent 9c74276240
commit b006501535
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1272 additions and 1551 deletions

View file

@ -1,137 +1,120 @@
using System;
using ModernUO.Serialization;
using Server.Gumps;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
namespace Server.Items;
[Flippable(0xA57, 0xA58, 0xA59)]
[SerializationGenerator(0)]
public partial class Bedroll : Item
{
[Flippable(0xA57, 0xA58, 0xA59)]
public class Bedroll : Item
[Constructible]
public Bedroll() : base(0xA57) => Weight = 5.0;
public override void OnDoubleClick(Mobile from)
{
[Constructible]
public Bedroll() : base(0xA57) => Weight = 5.0;
public Bedroll(Serial serial) : base(serial)
if (Parent != null || !VerifyMove(from))
{
return;
}
public override void OnDoubleClick(Mobile from)
if (!from.InRange(this, 2))
{
if (Parent != null || !VerifyMove(from))
{
return;
}
if (!from.InRange(this, 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
return;
}
if (ItemID == 0xA57) // rolled
{
var dir = PlayerMobile.GetDirection4(from.Location, Location);
if (dir is Direction.North or Direction.South)
{
ItemID = 0xA55;
}
else
{
ItemID = 0xA56;
}
}
else // unrolled
{
ItemID = 0xA57;
if (!from.HasGump<LogoutGump>())
{
var entry = Campfire.GetEntry(from);
if (entry?.Safe == true)
{
from.SendGump(new LogoutGump(entry, this));
}
}
}
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
return;
}
public override void Serialize(IGenericWriter writer)
if (ItemID == 0xA57) // rolled
{
base.Serialize(writer);
var dir = PlayerMobile.GetDirection4(from.Location, Location);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadEncodedInt();
}
private class LogoutGump : Gump
{
private readonly Bedroll m_Bedroll;
private TimerExecutionToken _closeTimerToken;
private readonly CampfireEntry m_Entry;
public LogoutGump(CampfireEntry entry, Bedroll bedroll) : base(100, 0)
if (dir is Direction.North or Direction.South)
{
m_Entry = entry;
m_Bedroll = bedroll;
Timer.StartTimer(TimeSpan.FromSeconds(10.0), CloseGump, out _closeTimerToken);
AddBackground(0, 0, 400, 350, 0xA28);
AddHtmlLocalized(100, 20, 200, 35, 1011015); // <center>Logging out via camping</center>
/* Using a bedroll in the safety of a camp will log you out of the game safely.
* If this is what you wish to do choose CONTINUE and you will be logged out.
* Otherwise, select the CANCEL button to avoid logging out at this time.
* The camp will remain secure for 10 seconds at which time this window will close
* and you not be logged out.
*/
AddHtmlLocalized(50, 55, 300, 140, 1011016, true, true);
AddButton(45, 298, 0xFA5, 0xFA7, 1);
AddHtmlLocalized(80, 300, 110, 35, 1011011); // CONTINUE
AddButton(200, 298, 0xFA5, 0xFA7, 0);
AddHtmlLocalized(235, 300, 110, 35, 1011012); // CANCEL
ItemID = 0xA55;
}
public override void OnResponse(NetState sender, RelayInfo info)
else
{
var pm = m_Entry.Player;
_closeTimerToken.Cancel();
if (Campfire.GetEntry(pm) != m_Entry)
{
return;
}
if (info.ButtonID == 1 && m_Entry.Safe && m_Bedroll.Parent == null && m_Bedroll.IsAccessibleTo(pm)
&& m_Bedroll.VerifyMove(pm) && m_Bedroll.Map == pm.Map && pm.InRange(m_Bedroll, 2))
{
pm.PlaceInBackpack(m_Bedroll);
pm.BedrollLogout = true;
sender.Disconnect("Used a bedroll to log out.");
}
Campfire.RemoveEntry(m_Entry);
ItemID = 0xA56;
}
}
else // unrolled
{
ItemID = 0xA57;
private void CloseGump()
if (!from.HasGump<LogoutGump>())
{
Campfire.RemoveEntry(m_Entry);
m_Entry.Player.CloseGump<LogoutGump>();
var entry = Campfire.GetEntry(from);
if (entry?.Safe == true)
{
from.SendGump(new LogoutGump(entry, this));
}
}
}
}
private class LogoutGump : Gump
{
private Bedroll _dedroll;
private TimerExecutionToken _closeTimerToken;
private CampfireEntry _entry;
public LogoutGump(CampfireEntry entry, Bedroll bedroll) : base(100, 0)
{
_entry = entry;
_dedroll = bedroll;
Timer.StartTimer(TimeSpan.FromSeconds(10.0), CloseGump, out _closeTimerToken);
AddBackground(0, 0, 400, 350, 0xA28);
AddHtmlLocalized(100, 20, 200, 35, 1011015); // <center>Logging out via camping</center>
/* Using a bedroll in the safety of a camp will log you out of the game safely.
* If this is what you wish to do choose CONTINUE and you will be logged out.
* Otherwise, select the CANCEL button to avoid logging out at this time.
* The camp will remain secure for 10 seconds at which time this window will close
* and you not be logged out.
*/
AddHtmlLocalized(50, 55, 300, 140, 1011016, true, true);
AddButton(45, 298, 0xFA5, 0xFA7, 1);
AddHtmlLocalized(80, 300, 110, 35, 1011011); // CONTINUE
AddButton(200, 298, 0xFA5, 0xFA7, 0);
AddHtmlLocalized(235, 300, 110, 35, 1011012); // CANCEL
}
public override void OnResponse(NetState sender, RelayInfo info)
{
var pm = _entry.Player;
_closeTimerToken.Cancel();
if (Campfire.GetEntry(pm) != _entry)
{
return;
}
if (info.ButtonID == 1 && _entry.Safe && _dedroll.Parent == null && _dedroll.IsAccessibleTo(pm)
&& _dedroll.VerifyMove(pm) && _dedroll.Map == pm.Map && pm.InRange(_dedroll, 2))
{
pm.PlaceInBackpack(_dedroll);
pm.BedrollLogout = true;
sender.Disconnect("Used a bedroll to log out.");
}
Campfire.RemoveEntry(_entry);
}
private void CloseGump()
{
Campfire.RemoveEntry(_entry);
_entry.Player.CloseGump<LogoutGump>();
}
}
}

View file

@ -1,219 +1,204 @@
using System;
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Mobiles;
namespace Server.Items
namespace Server.Items;
public enum CampfireStatus
{
public enum CampfireStatus
Burning,
Extinguishing,
Off
}
[SerializationGenerator(0, false)]
public partial class Campfire : Item
{
public static readonly int SecureRange = 7;
private static readonly Dictionary<Mobile, CampfireEntry> m_Table = new();
private readonly List<CampfireEntry> m_Entries;
private TimerExecutionToken _timerToken;
public Campfire() : base(0xDE3)
{
Burning,
Extinguishing,
Off
Movable = false;
Light = LightType.Circle300;
m_Entries = new List<CampfireEntry>();
Timer.StartTimer(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), OnTick, out _timerToken);
}
public class Campfire : Item
[CommandProperty(AccessLevel.GameMaster)]
public CampfireStatus Status
{
public static readonly int SecureRange = 7;
private static readonly Dictionary<Mobile, CampfireEntry> m_Table = new();
private readonly List<CampfireEntry> m_Entries;
private TimerExecutionToken _timerToken;
public Campfire() : base(0xDE3)
get
{
Movable = false;
Light = LightType.Circle300;
m_Entries = new List<CampfireEntry>();
Timer.StartTimer(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0), OnTick, out _timerToken);
}
public Campfire(Serial serial) : base(serial)
{
}
[CommandProperty(AccessLevel.GameMaster)]
public CampfireStatus Status
{
get
return ItemID switch
{
return ItemID switch
{
0xDE3 => CampfireStatus.Burning,
0xDE9 => CampfireStatus.Extinguishing,
_ => CampfireStatus.Off
};
}
set
{
if (Status == value)
{
return;
}
switch (value)
{
case CampfireStatus.Burning:
{
ItemID = 0xDE3;
Light = LightType.Circle300;
break;
}
case CampfireStatus.Extinguishing:
{
ItemID = 0xDE9;
Light = LightType.Circle150;
break;
}
default:
{
ItemID = 0xDEA;
Light = LightType.ArchedWindowEast;
ClearEntries();
break;
}
}
}
0xDE3 => CampfireStatus.Burning,
0xDE9 => CampfireStatus.Extinguishing,
_ => CampfireStatus.Off
};
}
public static CampfireEntry GetEntry(Mobile player)
set
{
m_Table.TryGetValue(player, out var value);
return value;
}
public static void RemoveEntry(CampfireEntry entry)
{
m_Table.Remove(entry.Player);
entry.Fire.m_Entries.Remove(entry);
}
private void OnTick()
{
var now = Core.Now;
var age = now - Created;
if (age >= TimeSpan.FromSeconds(100.0))
{
Delete();
}
else if (age >= TimeSpan.FromSeconds(90.0))
{
Status = CampfireStatus.Off;
}
else if (age >= TimeSpan.FromSeconds(60.0))
{
Status = CampfireStatus.Extinguishing;
}
if (Status == CampfireStatus.Off || Deleted)
if (Status == value)
{
return;
}
for (var i = m_Entries.Count - 1; i >= 0; i--)
switch (value)
{
var entry = m_Entries[i];
case CampfireStatus.Burning:
{
ItemID = 0xDE3;
Light = LightType.Circle300;
break;
}
if (!entry.Valid || entry.Player.NetState == null)
{
RemoveEntry(entry);
}
else if (!entry.Safe && now - entry.Start >= TimeSpan.FromSeconds(30.0))
{
entry.Safe = true;
entry.Player.SendLocalizedMessage(500621); // The camp is now secure.
}
case CampfireStatus.Extinguishing:
{
ItemID = 0xDE9;
Light = LightType.Circle150;
break;
}
default:
{
ItemID = 0xDEA;
Light = LightType.ArchedWindowEast;
ClearEntries();
break;
}
}
var eable = GetClientsInRange(SecureRange);
foreach (var state in eable)
{
if (state.Mobile is PlayerMobile pm && GetEntry(pm) == null)
{
var entry = new CampfireEntry(pm, this);
m_Table[pm] = entry;
m_Entries.Add(entry);
pm.SendLocalizedMessage(500620); // You feel it would take a few moments to secure your camp.
}
}
eable.Free();
}
}
private void ClearEntries()
public static CampfireEntry GetEntry(Mobile player)
{
m_Table.TryGetValue(player, out var value);
return value;
}
public static void RemoveEntry(CampfireEntry entry)
{
m_Table.Remove(entry.Player);
entry.Fire.m_Entries.Remove(entry);
}
private void OnTick()
{
var now = Core.Now;
var age = now - Created;
if (age >= TimeSpan.FromSeconds(100.0))
{
if (m_Entries == null)
{
return;
}
foreach (var entry in m_Entries)
{
m_Table.Remove(entry.Player);
}
m_Entries.Clear();
m_Entries.TrimExcess();
}
public override void OnAfterDelete()
{
_timerToken.Cancel();
ClearEntries();
}
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();
Delete();
}
else if (age >= TimeSpan.FromSeconds(90.0))
{
Status = CampfireStatus.Off;
}
else if (age >= TimeSpan.FromSeconds(60.0))
{
Status = CampfireStatus.Extinguishing;
}
if (Status == CampfireStatus.Off || Deleted)
{
return;
}
for (var i = m_Entries.Count - 1; i >= 0; i--)
{
var entry = m_Entries[i];
if (!entry.Valid || entry.Player.NetState == null)
{
RemoveEntry(entry);
}
else if (!entry.Safe && now - entry.Start >= TimeSpan.FromSeconds(30.0))
{
entry.Safe = true;
entry.Player.SendLocalizedMessage(500621); // The camp is now secure.
}
}
var eable = GetClientsInRange(SecureRange);
foreach (var state in eable)
{
if (state.Mobile is PlayerMobile pm && GetEntry(pm) == null)
{
var entry = new CampfireEntry(pm, this);
m_Table[pm] = entry;
m_Entries.Add(entry);
pm.SendLocalizedMessage(500620); // You feel it would take a few moments to secure your camp.
}
}
eable.Free();
}
public class CampfireEntry
private void ClearEntries()
{
private bool m_Safe;
public CampfireEntry(PlayerMobile player, Campfire fire)
if (m_Entries == null)
{
Player = player;
Fire = fire;
Start = Core.Now;
m_Safe = false;
return;
}
public PlayerMobile Player { get; }
public Campfire Fire { get; }
public DateTime Start { get; }
public bool Valid => !Fire.Deleted && Fire.Status != CampfireStatus.Off && Player.Map == Fire.Map &&
Player.InRange(Fire, Campfire.SecureRange);
public bool Safe
foreach (var entry in m_Entries)
{
get => Valid && m_Safe;
set => m_Safe = value;
m_Table.Remove(entry.Player);
}
m_Entries.Clear();
m_Entries.TrimExcess();
}
public override void OnAfterDelete()
{
_timerToken.Cancel();
ClearEntries();
}
[AfterDeserialization(false)]
private void AfterDeserialization()
{
Delete();
}
}
public class CampfireEntry
{
private bool _safe;
public CampfireEntry(PlayerMobile player, Campfire fire)
{
Player = player;
Fire = fire;
Start = Core.Now;
_safe = false;
}
public PlayerMobile Player { get; }
public Campfire Fire { get; }
public DateTime Start { get; }
public bool Valid => !Fire.Deleted && Fire.Status != CampfireStatus.Off && Player.Map == Fire.Map &&
Player.InRange(Fire, Campfire.SecureRange);
public bool Safe
{
get => Valid && _safe;
set => _safe = value;
}
}

View file

@ -1,122 +1,105 @@
using System.Collections.Generic;
using ModernUO.Serialization;
using Server.Network;
using Server.Regions;
namespace Server.Items
namespace Server.Items;
[SerializationGenerator(0, false)]
public partial class Kindling : Item
{
public class Kindling : Item
[Constructible]
public Kindling(int amount = 1) : base(0xDE1)
{
[Constructible]
public Kindling(int amount = 1) : base(0xDE1)
Stackable = true;
Weight = 5.0;
Amount = amount;
}
public override void OnDoubleClick(Mobile from)
{
if (!VerifyMove(from))
{
Stackable = true;
Weight = 5.0;
Amount = amount;
return;
}
public Kindling(Serial serial) : base(serial)
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
return;
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
var fireLocation = GetFireLocation(from);
writer.Write(0); // version
if (fireLocation == Point3D.Zero)
{
from.SendLocalizedMessage(501695); // There is not a spot nearby to place your campfire.
}
else if (!from.CheckSkill(SkillName.Camping, 0.0, 100.0))
{
from.SendLocalizedMessage(501696); // You fail to ignite the campfire.
}
else
{
Consume();
if (!Deleted && Parent == null)
{
from.PlaceInBackpack(this);
}
new Campfire().MoveToWorld(fireLocation, from.Map);
}
}
private Point3D GetFireLocation(Mobile from)
{
if (from.Region.IsPartOf<DungeonRegion>())
{
return Point3D.Zero;
}
public override void Deserialize(IGenericReader reader)
if (Parent == null)
{
base.Deserialize(reader);
var version = reader.ReadInt();
return Location;
}
public override void OnDoubleClick(Mobile from)
var list = new List<Point3D>(4);
AddOffsetLocation(from, 0, -1, list);
AddOffsetLocation(from, -1, 0, list);
AddOffsetLocation(from, 0, 1, list);
AddOffsetLocation(from, 1, 0, list);
if (list.Count == 0)
{
if (!VerifyMove(from))
{
return;
}
if (!from.InRange(GetWorldLocation(), 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
return;
}
var fireLocation = GetFireLocation(from);
if (fireLocation == Point3D.Zero)
{
from.SendLocalizedMessage(501695); // There is not a spot nearby to place your campfire.
}
else if (!from.CheckSkill(SkillName.Camping, 0.0, 100.0))
{
from.SendLocalizedMessage(501696); // You fail to ignite the campfire.
}
else
{
Consume();
if (!Deleted && Parent == null)
{
from.PlaceInBackpack(this);
}
new Campfire().MoveToWorld(fireLocation, from.Map);
}
return Point3D.Zero;
}
private Point3D GetFireLocation(Mobile from)
return list.RandomElement();
}
private static void AddOffsetLocation(Mobile from, int offsetX, int offsetY, List<Point3D> list)
{
var map = from.Map;
var x = from.X + offsetX;
var y = from.Y + offsetY;
var loc = new Point3D(x, y, from.Z);
if (map.CanFit(loc, 1) && from.InLOS(loc))
{
if (from.Region.IsPartOf<DungeonRegion>())
{
return Point3D.Zero;
}
if (Parent == null)
{
return Location;
}
var list = new List<Point3D>(4);
AddOffsetLocation(from, 0, -1, list);
AddOffsetLocation(from, -1, 0, list);
AddOffsetLocation(from, 0, 1, list);
AddOffsetLocation(from, 1, 0, list);
if (list.Count == 0)
{
return Point3D.Zero;
}
return list.RandomElement();
list.Add(loc);
}
private void AddOffsetLocation(Mobile from, int offsetX, int offsetY, List<Point3D> list)
else
{
var map = from.Map;
var x = from.X + offsetX;
var y = from.Y + offsetY;
var loc = new Point3D(x, y, from.Z);
loc = new Point3D(x, y, map.GetAverageZ(x, y));
if (map.CanFit(loc, 1) && from.InLOS(loc))
{
list.Add(loc);
}
else
{
loc = new Point3D(x, y, map.GetAverageZ(x, y));
if (map.CanFit(loc, 1) && from.InLOS(loc))
{
list.Add(loc);
}
}
}
}
}