diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index f65370008..ab09f794e 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"modernuoschemagenerator": {
- "version": "2.6.4",
+ "version": "2.7.2",
"commands": [
"ModernUOSchemaGenerator"
]
diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj
index 8e89619b7..2d8266899 100755
--- a/Projects/Server/Server.csproj
+++ b/Projects/Server/Server.csproj
@@ -38,7 +38,7 @@
-
+
diff --git a/Projects/UOContent/Items/Talismans/BaseTalisman.Migrations.cs b/Projects/UOContent/Items/Talismans/BaseTalisman.Migrations.cs
new file mode 100644
index 000000000..67329d83f
--- /dev/null
+++ b/Projects/UOContent/Items/Talismans/BaseTalisman.Migrations.cs
@@ -0,0 +1,132 @@
+using System;
+
+namespace Server.Items;
+
+public partial class BaseTalisman
+{
+ private void Deserialize(IGenericReader reader, int version)
+ {
+ var flags = (OldSaveFlag)reader.ReadEncodedInt();
+
+ Attributes = new AosAttributes(this);
+ if (GetOldSaveFlag(flags, OldSaveFlag.Attributes))
+ {
+ Attributes.Deserialize(reader);
+ }
+
+ SkillBonuses = new AosSkillBonuses(this);
+ if (GetOldSaveFlag(flags, OldSaveFlag.SkillBonuses))
+ {
+ SkillBonuses.Deserialize(reader);
+ }
+
+ // Backward compatibility
+ if (GetOldSaveFlag(flags, OldSaveFlag.Owner))
+ {
+ BlessedFor = reader.ReadEntity();
+ }
+
+ _protection = new TalismanAttribute();
+ if (GetOldSaveFlag(flags, OldSaveFlag.Protection))
+ {
+ _protection.Deserialize(reader);
+ }
+
+ _killer = new TalismanAttribute();
+ if (GetOldSaveFlag(flags, OldSaveFlag.Killer))
+ {
+ _killer.Deserialize(reader);
+ }
+
+ _summoner = new TalismanAttribute();
+ if (GetOldSaveFlag(flags, OldSaveFlag.Summoner))
+ {
+ _summoner.Deserialize(reader);
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.Removal))
+ {
+ _removal = (TalismanRemoval)reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.OldKarmaLoss))
+ {
+ Attributes.IncreasedKarmaLoss = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.Skill))
+ {
+ _skill = (SkillName)reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.SuccessBonus))
+ {
+ _successBonus = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.ExceptionalBonus))
+ {
+ _exceptionalBonus = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.MaxCharges))
+ {
+ _maxCharges = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.Charges))
+ {
+ _charges = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.MaxChargeTime))
+ {
+ _maxChargeTime = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.ChargeTime))
+ {
+ _chargeTime = reader.ReadEncodedInt();
+ }
+
+ if (GetOldSaveFlag(flags, OldSaveFlag.Slayer))
+ {
+ _slayer = (TalismanSlayerName)reader.ReadEncodedInt();
+ }
+
+ _blessed = GetOldSaveFlag(flags, OldSaveFlag.Blessed);
+ }
+
+ private static void SetOldSaveFlag(ref OldSaveFlag flags, OldSaveFlag toSet, bool setIf)
+ {
+ if (setIf)
+ {
+ flags |= toSet;
+ }
+ }
+
+ private static bool GetOldSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0;
+
+ [Flags]
+ private enum OldSaveFlag
+ {
+ None = 0x00000000,
+ Attributes = 0x00000001,
+ SkillBonuses = 0x00000002,
+ Owner = 0x00000004,
+ Protection = 0x00000008,
+ Killer = 0x00000010,
+ Summoner = 0x00000020,
+ Removal = 0x00000040,
+ OldKarmaLoss = 0x00000080,
+ Skill = 0x00000100,
+ SuccessBonus = 0x00000200,
+ ExceptionalBonus = 0x00000400,
+ MaxCharges = 0x00000800,
+ Charges = 0x00001000,
+ MaxChargeTime = 0x00002000,
+ ChargeTime = 0x00004000,
+ Blessed = 0x00008000,
+ Slayer = 0x00010000
+ }
+}
diff --git a/Projects/UOContent/Items/Talismans/BaseTalisman.cs b/Projects/UOContent/Items/Talismans/BaseTalisman.cs
index a28f9e814..943de5041 100644
--- a/Projects/UOContent/Items/Talismans/BaseTalisman.cs
+++ b/Projects/UOContent/Items/Talismans/BaseTalisman.cs
@@ -1,4 +1,5 @@
using System;
+using ModernUO.Serialization;
using Server.Mobiles;
using Server.Spells.Fifth;
using Server.Spells.First;
@@ -8,520 +9,496 @@ using Server.Spells.Second;
using Server.Targeting;
using Server.Utilities;
-namespace Server.Items
+namespace Server.Items;
+
+public enum TalismanRemoval
{
- public enum TalismanRemoval
+ None = 0,
+ Ward = 390,
+ Damage = 404,
+ Curse = 407,
+ Wildfire = 2843
+}
+
+[SerializationGenerator(1, false)]
+public partial class BaseTalisman : Item, IAosItem
+{
+ private static readonly int[] _itemIDs =
+ {
+ 0x2F58, 0x2F59, 0x2F5A, 0x2F5B
+ };
+
+ private static readonly Type[] _summons =
+ {
+ typeof(SummonedAntLion),
+ typeof(SummonedCow),
+ typeof(SummonedLavaSerpent),
+ typeof(SummonedOrcBrute),
+ typeof(SummonedFrostSpider),
+ typeof(SummonedPanther),
+ typeof(SummonedDoppleganger),
+ typeof(SummonedGreatHart),
+ typeof(SummonedBullFrog),
+ typeof(SummonedArcticOgreLord),
+ typeof(SummonedBogling),
+ typeof(SummonedBakeKitsune),
+ typeof(SummonedSheep),
+ typeof(SummonedSkeletalKnight),
+ typeof(SummonedWailingBanshee),
+ typeof(SummonedChicken),
+ typeof(SummonedVorpalBunny),
+
+ typeof(Board),
+ typeof(IronIngot),
+ typeof(Bandage)
+ };
+
+ private static readonly int[] _summonLabels =
+ {
+ 1075211, // Ant Lion
+ 1072494, // Cow
+ 1072434, // Lava Serpent
+ 1072414, // Orc Brute
+ 1072476, // Frost Spider
+ 1029653, // Panther
+ 1029741, // Doppleganger
+ 1018292, // great hart
+ 1028496, // bullfrog
+ 1018227, // arctic ogre lord
+ 1029735, // Bogling
+ 1030083, // bake-kitsune
+ 1018285, // sheep
+ 1018239, // skeletal knight
+ 1072399, // Wailing Banshee
+ 1072459, // Chicken
+ 1072401, // Vorpal Bunny
+
+ 1015101, // Boards
+ 1044036, // Ingots
+ 1023817 // clean bandage
+ };
+
+ private static readonly Type[] _killers =
+ {
+ typeof(OrcBomber), typeof(OrcBrute), typeof(SewerRat), typeof(Rat), typeof(GiantRat),
+ typeof(Ratman), typeof(RatmanArcher), typeof(GiantSpider), typeof(FrostSpider), typeof(GiantBlackWidow),
+ typeof(DreadSpider), typeof(SilverSerpent), typeof(DeepSeaSerpent), typeof(GiantSerpent), typeof(Snake),
+ typeof(IceSnake), typeof(IceSerpent), typeof(LavaSerpent), typeof(LavaSnake), typeof(Yamandon),
+ typeof(StrongMongbat), typeof(Mongbat), typeof(VampireBat), typeof(Lich), typeof(EvilMage),
+ typeof(LichLord), typeof(EvilMageLord), typeof(SkeletalMage), typeof(KhaldunZealot), typeof(AncientLich),
+ typeof(JukaMage), typeof(MeerMage), typeof(Beetle), typeof(DeathwatchBeetle), typeof(RuneBeetle),
+ typeof(FireBeetle), typeof(DeathwatchBeetleHatchling), typeof(Bird), typeof(Chicken), typeof(Eagle),
+ typeof(TropicalBird), typeof(Phoenix), typeof(DesertOstard), typeof(FrenziedOstard), typeof(ForestOstard),
+ typeof(Crane), typeof(SnowLeopard), typeof(IceFiend), typeof(FrostOoze), typeof(FrostTroll),
+ typeof(IceElemental), typeof(SnowElemental), typeof(GiantIceWorm), typeof(LadyOfTheSnow), typeof(FireElemental),
+ typeof(FireSteed), typeof(HellHound), typeof(HellCat), typeof(PredatorHellCat), typeof(LavaLizard),
+ typeof(FireBeetle), typeof(Cow), typeof(Bull), typeof(Gaman) // , typeof( Minotaur)
+ // TODO Meraktus, Tormented Minotaur, Minotaur
+ };
+
+ private static readonly int[] _killerLabels =
+ {
+ 1072413, 1072414, 1072418, 1072419, 1072420,
+ 1072421, 1072423, 1072424, 1072425, 1072426,
+ 1072427, 1072428, 1072429, 1072430, 1072431,
+ 1072432, 1072433, 1072434, 1072435, 1072438,
+ 1072440, 1072441, 1072443, 1072444, 1072445,
+ 1072446, 1072447, 1072448, 1072449, 1072450,
+ 1072451, 1072452, 1072453, 1072454, 1072455,
+ 1072456, 1072457, 1072458, 1072459, 1072461,
+ 1072462, 1072465, 1072468, 1072469, 1072470,
+ 1072473, 1072474, 1072477, 1072478, 1072479,
+ 1072480, 1072481, 1072483, 1072485, 1072486,
+ 1072487, 1072489, 1072490, 1072491, 1072492,
+ 1072493, 1072494, 1072495, 1072498
+ };
+
+ private static readonly SkillName[] _skills =
+ {
+ SkillName.Alchemy,
+ SkillName.Blacksmith,
+ SkillName.Carpentry,
+ SkillName.Cartography,
+ SkillName.Cooking,
+ SkillName.Fletching,
+ SkillName.Inscribe,
+ SkillName.Tailoring,
+ SkillName.Tinkering
+ };
+
+ [SerializableField(0, setter: "private")]
+ [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)]
+ private AosAttributes _attributes;
+
+ [SerializableFieldSaveFlag(0)]
+ public bool ShouldSerializeAttributes() => !_attributes.IsEmpty;
+
+ [SerializableFieldDefault(0)]
+ private AosAttributes AttributesDefaultValue() => new(this);
+
+ [SerializableField(1, setter: "private")]
+ [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)]
+ private AosSkillBonuses _skillBonuses;
+
+ [SerializableFieldSaveFlag(1)]
+ public bool ShouldSerializeSkillBonuses() => !_skillBonuses.IsEmpty;
+
+ [SerializableFieldDefault(1)]
+ private AosSkillBonuses SkillBonusesDefaultValue() => new(this);
+
+ [InvalidateProperties]
+ [SerializableField(2)]
+ [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)]
+ private TalismanAttribute _protection;
+
+ [SerializableFieldSaveFlag(2)]
+ public bool ShouldSerializeProtection() => !_protection.IsEmpty;
+
+ [SerializableFieldDefault(2)]
+ private TalismanAttribute ProtectionDefaultValue() => new();
+
+ [InvalidateProperties]
+ [SerializableField(3)]
+ [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)]
+ private TalismanAttribute _killer;
+
+ [SerializableFieldSaveFlag(3)]
+ public bool ShouldSerializeKiller() => !_killer.IsEmpty;
+
+ [SerializableFieldDefault(3)]
+ private TalismanAttribute KillerDefaultValue() => new();
+
+ [InvalidateProperties]
+ [SerializableField(4)]
+ [SerializedCommandProperty(AccessLevel.GameMaster, canModify: true)]
+ private TalismanAttribute _summoner;
+
+ [SerializableFieldSaveFlag(4)]
+ public bool ShouldSerializeSummoner() => !_summoner.IsEmpty;
+
+ [SerializableFieldDefault(4)]
+ private TalismanAttribute SummonerDefaultValue() => new();
+
+ [InvalidateProperties]
+ [SerializableField(5)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private TalismanRemoval _removal;
+
+ [SerializableFieldSaveFlag(5)]
+ public bool ShouldSerializeRemoval() => _removal != TalismanRemoval.None;
+
+ [InvalidateProperties]
+ [SerializableField(6)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private SkillName _skill;
+
+ [SerializableFieldSaveFlag(6)]
+ public bool ShouldSerializeSkill() => (int)_skill != 0;
+
+ [EncodedInt]
+ [InvalidateProperties]
+ [SerializableField(7)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private int _successBonus;
+
+ [SerializableFieldSaveFlag(7)]
+ public bool ShouldSerializeSuccessBonus() => _successBonus != 0;
+
+ [EncodedInt]
+ [InvalidateProperties]
+ [SerializableField(8)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private int _exceptionalBonus;
+
+ [SerializableFieldSaveFlag(8)]
+ public bool ShouldSerializeExceptionalBonus() => _exceptionalBonus != 0;
+
+ [EncodedInt]
+ [InvalidateProperties]
+ [SerializableField(9)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private int _maxCharges;
+
+ [SerializableFieldSaveFlag(9)]
+ public bool ShouldSerializeMaxCharges() => _maxCharges != 0;
+
+ [EncodedInt]
+ [InvalidateProperties]
+ [SerializableField(11)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private int _maxChargeTime;
+
+ [SerializableFieldSaveFlag(11)]
+ public bool ShouldSerializeMaxChargeTime() => _maxChargeTime != 0;
+
+ [EncodedInt]
+ [InvalidateProperties]
+ [SerializableField(12)]
+ private int _chargeTime;
+
+ [SerializableFieldSaveFlag(12)]
+ public bool ShouldSerializeChargeTime() => _chargeTime != 0;
+
+ [InvalidateProperties]
+ [SerializableField(13)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private bool _blessed;
+
+ [SerializableFieldSaveFlag(13)]
+ public bool ShouldSerializeBlessed() => _blessed;
+
+ [InvalidateProperties]
+ [SerializableField(14)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private TalismanSlayerName _slayer;
+
+ [SerializableFieldSaveFlag(14)]
+ public bool ShouldSerializeSlayer() => _slayer != TalismanSlayerName.None;
+
+ private Mobile _creature;
+
+
+ private TimerExecutionToken _timerToken;
+
+ public BaseTalisman() : this(GetRandomItemID())
{
- None = 0,
- Ward = 390,
- Damage = 404,
- Curse = 407,
- Wildfire = 2843
}
- public class BaseTalisman : Item, IAosItem
+ public BaseTalisman(int itemID) : base(itemID)
{
- private static readonly int[] m_ItemIDs =
+ Layer = Layer.Talisman;
+ Weight = 1.0;
+
+ _protection = new TalismanAttribute();
+ _killer = new TalismanAttribute();
+ _summoner = new TalismanAttribute();
+ Attributes = new AosAttributes(this);
+ SkillBonuses = new AosSkillBonuses(this);
+ }
+
+ public override int LabelNumber => 1071023; // Talisman
+ public virtual bool ForceShowName => false; // used to override default summoner/removal name
+
+ [SerializableProperty(10)]
+ [CommandProperty(AccessLevel.GameMaster)]
+ public int Charges
+ {
+ get => _charges;
+ set
{
- 0x2F58, 0x2F59, 0x2F5A, 0x2F5B
- };
+ _charges = value;
- private static readonly Type[] m_Summons =
- {
- typeof(SummonedAntLion),
- typeof(SummonedCow),
- typeof(SummonedLavaSerpent),
- typeof(SummonedOrcBrute),
- typeof(SummonedFrostSpider),
- typeof(SummonedPanther),
- typeof(SummonedDoppleganger),
- typeof(SummonedGreatHart),
- typeof(SummonedBullFrog),
- typeof(SummonedArcticOgreLord),
- typeof(SummonedBogling),
- typeof(SummonedBakeKitsune),
- typeof(SummonedSheep),
- typeof(SummonedSkeletalKnight),
- typeof(SummonedWailingBanshee),
- typeof(SummonedChicken),
- typeof(SummonedVorpalBunny),
-
- typeof(Board),
- typeof(IronIngot),
- typeof(Bandage)
- };
-
- private static readonly int[] m_SummonLabels =
- {
- 1075211, // Ant Lion
- 1072494, // Cow
- 1072434, // Lava Serpent
- 1072414, // Orc Brute
- 1072476, // Frost Spider
- 1029653, // Panther
- 1029741, // Doppleganger
- 1018292, // great hart
- 1028496, // bullfrog
- 1018227, // arctic ogre lord
- 1029735, // Bogling
- 1030083, // bake-kitsune
- 1018285, // sheep
- 1018239, // skeletal knight
- 1072399, // Wailing Banshee
- 1072459, // Chicken
- 1072401, // Vorpal Bunny
-
- 1015101, // Boards
- 1044036, // Ingots
- 1023817 // clean bandage
- };
-
- private static readonly Type[] m_Killers =
- {
- typeof(OrcBomber), typeof(OrcBrute), typeof(SewerRat), typeof(Rat), typeof(GiantRat),
- typeof(Ratman), typeof(RatmanArcher), typeof(GiantSpider), typeof(FrostSpider), typeof(GiantBlackWidow),
- typeof(DreadSpider), typeof(SilverSerpent), typeof(DeepSeaSerpent), typeof(GiantSerpent), typeof(Snake),
- typeof(IceSnake), typeof(IceSerpent), typeof(LavaSerpent), typeof(LavaSnake), typeof(Yamandon),
- typeof(StrongMongbat), typeof(Mongbat), typeof(VampireBat), typeof(Lich), typeof(EvilMage),
- typeof(LichLord), typeof(EvilMageLord), typeof(SkeletalMage), typeof(KhaldunZealot), typeof(AncientLich),
- typeof(JukaMage), typeof(MeerMage), typeof(Beetle), typeof(DeathwatchBeetle), typeof(RuneBeetle),
- typeof(FireBeetle), typeof(DeathwatchBeetleHatchling), typeof(Bird), typeof(Chicken), typeof(Eagle),
- typeof(TropicalBird), typeof(Phoenix), typeof(DesertOstard), typeof(FrenziedOstard), typeof(ForestOstard),
- typeof(Crane), typeof(SnowLeopard), typeof(IceFiend), typeof(FrostOoze), typeof(FrostTroll),
- typeof(IceElemental), typeof(SnowElemental), typeof(GiantIceWorm), typeof(LadyOfTheSnow), typeof(FireElemental),
- typeof(FireSteed), typeof(HellHound), typeof(HellCat), typeof(PredatorHellCat), typeof(LavaLizard),
- typeof(FireBeetle), typeof(Cow), typeof(Bull), typeof(Gaman) // , typeof( Minotaur)
- // TODO Meraktus, Tormented Minotaur, Minotaur
- };
-
- private static readonly int[] m_KillerLabels =
- {
- 1072413, 1072414, 1072418, 1072419, 1072420,
- 1072421, 1072423, 1072424, 1072425, 1072426,
- 1072427, 1072428, 1072429, 1072430, 1072431,
- 1072432, 1072433, 1072434, 1072435, 1072438,
- 1072440, 1072441, 1072443, 1072444, 1072445,
- 1072446, 1072447, 1072448, 1072449, 1072450,
- 1072451, 1072452, 1072453, 1072454, 1072455,
- 1072456, 1072457, 1072458, 1072459, 1072461,
- 1072462, 1072465, 1072468, 1072469, 1072470,
- 1072473, 1072474, 1072477, 1072478, 1072479,
- 1072480, 1072481, 1072483, 1072485, 1072486,
- 1072487, 1072489, 1072490, 1072491, 1072492,
- 1072493, 1072494, 1072495, 1072498
- };
-
- private static readonly SkillName[] m_Skills =
- {
- SkillName.Alchemy,
- SkillName.Blacksmith,
- SkillName.Carpentry,
- SkillName.Cartography,
- SkillName.Cooking,
- SkillName.Fletching,
- SkillName.Inscribe,
- SkillName.Tailoring,
- SkillName.Tinkering
- };
-
- private bool m_Blessed;
- private int m_Charges;
- private int m_ChargeTime;
- private Mobile m_Creature;
- private int m_ExceptionalBonus;
- private TalismanAttribute m_Killer;
-
- private int m_MaxCharges;
- private int m_MaxChargeTime;
-
- private TalismanAttribute m_Protection;
- private TalismanRemoval m_Removal;
-
- private SkillName m_Skill;
-
- private TalismanSlayerName m_Slayer;
- private int m_SuccessBonus;
-
- private TalismanAttribute m_Summoner;
-
- private TimerExecutionToken _timerToken;
-
- public BaseTalisman()
- : this(GetRandomItemID())
- {
- }
-
- public BaseTalisman(int itemID)
- : base(itemID)
- {
- Layer = Layer.Talisman;
- Weight = 1.0;
-
- m_Protection = new TalismanAttribute();
- m_Killer = new TalismanAttribute();
- m_Summoner = new TalismanAttribute();
- Attributes = new AosAttributes(this);
- SkillBonuses = new AosSkillBonuses(this);
- }
-
- public BaseTalisman(Serial serial)
- : base(serial)
- {
- }
-
- public override int LabelNumber => 1071023; // Talisman
- public virtual bool ForceShowName => false; // used to override default summoner/removal name
-
- [CommandProperty(AccessLevel.GameMaster)]
- public int MaxCharges
- {
- get => m_MaxCharges;
- set
+ if (_chargeTime > 0)
{
- m_MaxCharges = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public int Charges
- {
- get => m_Charges;
- set
- {
- m_Charges = value;
-
- if (m_ChargeTime > 0)
- {
- StartTimer();
- }
-
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public int MaxChargeTime
- {
- get => m_MaxChargeTime;
- set
- {
- m_MaxChargeTime = value;
- InvalidateProperties();
- }
- }
-
- public int ChargeTime
- {
- get => m_ChargeTime;
- set
- {
- m_ChargeTime = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public bool Blessed
- {
- get => m_Blessed;
- set
- {
- m_Blessed = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public TalismanSlayerName Slayer
- {
- get => m_Slayer;
- set
- {
- m_Slayer = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public TalismanAttribute Summoner
- {
- get => m_Summoner;
- set
- {
- m_Summoner = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public TalismanRemoval Removal
- {
- get => m_Removal;
- set
- {
- m_Removal = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public TalismanAttribute Protection
- {
- get => m_Protection;
- set
- {
- m_Protection = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public TalismanAttribute Killer
- {
- get => m_Killer;
- set
- {
- m_Killer = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public SkillName Skill
- {
- get => m_Skill;
- set
- {
- m_Skill = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public int SuccessBonus
- {
- get => m_SuccessBonus;
- set
- {
- m_SuccessBonus = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public int ExceptionalBonus
- {
- get => m_ExceptionalBonus;
- set
- {
- m_ExceptionalBonus = value;
- InvalidateProperties();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster, canModify: true)]
- public AosAttributes Attributes { get; private set; }
-
- [CommandProperty(AccessLevel.GameMaster, canModify: true)]
- public AosSkillBonuses SkillBonuses { get; private set; }
-
- public static void Initialize()
- {
- CommandSystem.Register("RandomTalisman", AccessLevel.GameMaster, RandomTalisman_OnCommand);
- }
-
- [Usage("RandomTalisman "), Description("Generates random talismans in your backpack.")]
- public static void RandomTalisman_OnCommand(CommandEventArgs e)
- {
- var m = e.Mobile;
- var count = e.GetInt32(0);
-
- for (var i = 0; i < count; i++)
- {
- m.AddToBackpack(Loot.RandomTalisman());
- }
- }
-
- public override void OnAfterDuped(Item newItem)
- {
- if (newItem is not BaseTalisman talisman)
- {
- return;
- }
-
- talisman.m_Summoner = new TalismanAttribute(m_Summoner);
- talisman.m_Protection = new TalismanAttribute(m_Protection);
- talisman.m_Killer = new TalismanAttribute(m_Killer);
- talisman.Attributes = new AosAttributes(newItem, Attributes);
- talisman.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses);
- }
-
- public override bool CanEquip(Mobile from)
- {
- if (BlessedFor != null && BlessedFor != from)
- {
- from.SendLocalizedMessage(1010437); // You are not the owner.
- return false;
- }
-
- return base.CanEquip(from);
- }
-
- public override void OnAdded(IEntity parent)
- {
- if (parent is Mobile from)
- {
- SkillBonuses.AddTo(from);
- Attributes.AddStatBonuses(from);
-
- if (m_Blessed && BlessedFor == null)
- {
- BlessedFor = from;
- LootType = LootType.Blessed;
- }
-
- if (m_ChargeTime > 0)
- {
- m_ChargeTime = m_MaxChargeTime;
- StartTimer();
- }
+ StartTimer();
}
InvalidateProperties();
+ this.MarkDirty();
+ }
+ }
+
+ [SerializableFieldSaveFlag(10)]
+ public bool ShouldSerializeCharges() => _charges != 0;
+
+ public static void Initialize()
+ {
+ CommandSystem.Register("RandomTalisman", AccessLevel.GameMaster, RandomTalisman_OnCommand);
+ }
+
+ [Usage("RandomTalisman "), Description("Generates random talismans in your backpack.")]
+ public static void RandomTalisman_OnCommand(CommandEventArgs e)
+ {
+ var m = e.Mobile;
+ var count = e.GetInt32(0);
+
+ for (var i = 0; i < count; i++)
+ {
+ m.AddToBackpack(Loot.RandomTalisman());
+ }
+ }
+
+ public override void OnAfterDuped(Item newItem)
+ {
+ if (newItem is not BaseTalisman talisman)
+ {
+ return;
}
- public override void OnRemoved(IEntity parent)
- {
- if (parent is Mobile from)
- {
- SkillBonuses.Remove();
- Attributes.RemoveStatBonuses(from);
+ talisman._summoner = new TalismanAttribute(_summoner);
+ talisman._protection = new TalismanAttribute(_protection);
+ talisman._killer = new TalismanAttribute(_killer);
+ talisman.Attributes = new AosAttributes(newItem, Attributes);
+ talisman.SkillBonuses = new AosSkillBonuses(newItem, SkillBonuses);
+ }
- if (m_Creature?.Deleted == false)
+ public override bool CanEquip(Mobile from)
+ {
+ if (BlessedFor != null && BlessedFor != from)
+ {
+ from.SendLocalizedMessage(1010437); // You are not the owner.
+ return false;
+ }
+
+ return base.CanEquip(from);
+ }
+
+ public override void OnAdded(IEntity parent)
+ {
+ if (parent is Mobile from)
+ {
+ SkillBonuses.AddTo(from);
+ Attributes.AddStatBonuses(from);
+
+ if (_blessed && BlessedFor == null)
+ {
+ BlessedFor = from;
+ LootType = LootType.Blessed;
+ }
+
+ if (_chargeTime > 0)
+ {
+ _chargeTime = _maxChargeTime;
+ StartTimer();
+ }
+ }
+
+ InvalidateProperties();
+ }
+
+ public override void OnRemoved(IEntity parent)
+ {
+ if (parent is Mobile from)
+ {
+ SkillBonuses.Remove();
+ Attributes.RemoveStatBonuses(from);
+
+ if (_creature?.Deleted == false)
+ {
+ Effects.SendLocationParticles(
+ EffectItem.Create(_creature.Location, _creature.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 8,
+ 20,
+ 5042
+ );
+ Effects.PlaySound(_creature, 0x201);
+
+ _creature.Delete();
+ }
+
+ StopTimer();
+ }
+
+ InvalidateProperties();
+ }
+
+ public override void OnDoubleClick(Mobile from)
+ {
+ if (from.Talisman != this)
+ {
+ from.SendLocalizedMessage(502641); // You must equip this item to use it.
+ return;
+ }
+
+ if (_chargeTime > 0)
+ {
+ // You must wait ~1_val~ seconds for this to recharge.
+ from.SendLocalizedMessage(1074882, _chargeTime.ToString());
+ return;
+ }
+
+ if (_charges == 0 && _maxCharges > 0)
+ {
+ from.SendLocalizedMessage(1042544); // This item is out of charges.
+ return;
+ }
+
+ var type = GetSummoner();
+
+ if (_summoner?.IsEmpty == false)
+ {
+ type = _summoner.Type;
+ }
+
+ if (type != null)
+ {
+ IEntity entity;
+
+ try
+ {
+ entity = type.CreateInstance();
+ }
+ catch
+ {
+ entity = null;
+ }
+
+ if (entity is Item item)
+ {
+ var count = 1;
+
+ if (_summoner?.Amount > 1)
{
- Effects.SendLocationParticles(
- EffectItem.Create(m_Creature.Location, m_Creature.Map, EffectItem.DefaultDuration),
- 0x3728,
- 8,
- 20,
- 5042
+ if (item.Stackable)
+ {
+ item.Amount = _summoner.Amount;
+ }
+ else
+ {
+ count = _summoner.Amount;
+ }
+ }
+
+ if (from.Backpack == null || count * item.Weight > from.Backpack.MaxWeight ||
+ from.Backpack.Items.Count + count > from.Backpack.MaxItems)
+ {
+ from.SendLocalizedMessage(500720); // You don't have enough room in your backpack!
+ item.Delete();
+ return;
+ }
+
+ for (var i = 0; i < count; i++)
+ {
+ from.PlaceInBackpack(item);
+
+ if (i + 1 < count)
+ {
+ item = type.CreateInstance- ();
+ }
+ }
+
+ if (item is Board)
+ {
+ from.SendLocalizedMessage(1075000); // You have been given some wooden boards.
+ }
+ else if (item is IronIngot)
+ {
+ from.SendLocalizedMessage(1075001); // You have been given some ingots.
+ }
+ else if (item is Bandage)
+ {
+ from.SendLocalizedMessage(1075002); // You have been given some clean bandages.
+ }
+ else if (_summoner?.Name != null)
+ {
+ from.SendLocalizedMessage(
+ 1074853, // You have been given ~1_name~
+ _summoner.Name.Number > 0 ? $"#{_summoner.Name}" : _summoner.Name.String
);
- Effects.PlaySound(m_Creature, 0x201);
-
- m_Creature.Delete();
+ }
+ }
+ else if (entity is BaseCreature mob)
+ {
+ if (_creature?.Deleted == false)
+ {
+ from.SendLocalizedMessage(1074270); // You have too many followers to summon another one.
+ mob.Delete();
+ return;
}
- StopTimer();
- }
-
- InvalidateProperties();
- }
-
- public override void OnDoubleClick(Mobile from)
- {
- if (from.Talisman != this)
- {
- from.SendLocalizedMessage(502641); // You must equip this item to use it.
- return;
- }
-
- if (m_ChargeTime > 0)
- {
- from.SendLocalizedMessage(
- 1074882,
- m_ChargeTime.ToString()
- ); // You must wait ~1_val~ seconds for this to recharge.
- return;
- }
-
- if (m_Charges == 0 && m_MaxCharges > 0)
- {
- from.SendLocalizedMessage(1042544); // This item is out of charges.
- return;
- }
-
- var type = GetSummoner();
-
- if (m_Summoner?.IsEmpty == false)
- {
- type = m_Summoner.Type;
- }
-
- if (type != null)
- {
- IEntity entity;
-
- try
+ if (BaseCreature.Summon(mob, from, from.Location, mob.BaseSoundID, TimeSpan.FromMinutes(10)))
{
- entity = type.CreateInstance();
- }
- catch
- {
- entity = null;
- }
-
- if (entity is Item item)
- {
- var count = 1;
-
- if (m_Summoner?.Amount > 1)
- {
- if (item.Stackable)
- {
- item.Amount = m_Summoner.Amount;
- }
- else
- {
- count = m_Summoner.Amount;
- }
- }
-
- if (from.Backpack == null || count * item.Weight > from.Backpack.MaxWeight ||
- from.Backpack.Items.Count + count > from.Backpack.MaxItems)
- {
- from.SendLocalizedMessage(500720); // You don't have enough room in your backpack!
- item.Delete();
- return;
- }
-
- for (var i = 0; i < count; i++)
- {
- from.PlaceInBackpack(item);
-
- if (i + 1 < count)
- {
- item = type.CreateInstance
- ();
- }
- }
-
- if (item is Board)
- {
- from.SendLocalizedMessage(1075000); // You have been given some wooden boards.
- }
- else if (item is IronIngot)
- {
- from.SendLocalizedMessage(1075001); // You have been given some ingots.
- }
- else if (item is Bandage)
- {
- from.SendLocalizedMessage(1075002); // You have been given some clean bandages.
- }
- else if (m_Summoner?.Name != null)
- {
- from.SendLocalizedMessage(1074853, m_Summoner.Name.ToString()); // You have been given ~1_name~
- }
- }
- else if (entity is BaseCreature mob)
- {
- if (m_Creature?.Deleted == false || from.Followers + mob.ControlSlots > from.FollowersMax)
- {
- from.SendLocalizedMessage(1074270); // You have too many followers to summon another one.
- mob.Delete();
- return;
- }
-
- BaseCreature.Summon(mob, from, from.Location, mob.BaseSoundID, TimeSpan.FromMinutes(10));
Effects.SendLocationParticles(
EffectItem.Create(mob.Location, mob.Map, EffectItem.DefaultDuration),
0x3728,
@@ -533,808 +510,588 @@ namespace Server.Items
mob.Summoned = false;
mob.ControlOrder = OrderType.Friend;
- m_Creature = mob;
+ _creature = mob;
}
- else
- {
- entity?.Delete();
- }
-
- OnAfterUse(from);
- }
-
- if (m_Removal != TalismanRemoval.None)
- {
- from.Target = new TalismanTarget(this);
- }
- }
-
- public override void AddNameProperty(IPropertyList list)
- {
- if (ForceShowName)
- {
- base.AddNameProperty(list);
- }
- else if (m_Summoner?.IsEmpty == false)
- {
- var name = m_Summoner?.Name;
- if (name?.Number > 0)
- {
- list.Add(1072400, name.Number); // Talisman of ~1_name~ Summoning
- }
- else
- {
- list.Add(1072400, name?.String ?? "Unknown"); // Talisman of ~1_name~ Summoning
- }
- }
- else if (m_Removal != TalismanRemoval.None)
- {
- list.AddLocalized(1072389, 1072000 + (int)m_Removal); // Talisman of ~1_name~
}
else
{
- base.AddNameProperty(list);
+ entity?.Delete();
+ }
+
+ OnAfterUse(from);
+ }
+
+ if (_removal != TalismanRemoval.None)
+ {
+ from.Target = new TalismanTarget(this);
+ }
+ }
+
+ public override void AddNameProperty(IPropertyList list)
+ {
+ if (ForceShowName)
+ {
+ base.AddNameProperty(list);
+ }
+ else if (_summoner?.IsEmpty == false)
+ {
+ var name = _summoner?.Name;
+ if (name?.Number > 0)
+ {
+ list.Add(1072400, name.Number); // Talisman of ~1_name~ Summoning
+ }
+ else
+ {
+ list.Add(1072400, name?.String ?? "Unknown"); // Talisman of ~1_name~ Summoning
+ }
+ }
+ else if (_removal != TalismanRemoval.None)
+ {
+ list.AddLocalized(1072389, 1072000 + (int)_removal); // Talisman of ~1_name~
+ }
+ else
+ {
+ base.AddNameProperty(list);
+ }
+ }
+
+ public override void GetProperties(IPropertyList list)
+ {
+ base.GetProperties(list);
+
+ if (Blessed)
+ {
+ if (BlessedFor != null)
+ {
+ // Owned by ~1_name~
+ list.Add(1072304,BlessedFor.Name.DefaultIfNullOrEmpty("Unnamed Warrior"));
+ }
+ else
+ {
+ list.Add(1072304, "Nobody"); // Owned by ~1_name~
}
}
- public override void GetProperties(IPropertyList list)
+ if (Parent is Mobile && _maxChargeTime > 0)
{
- base.GetProperties(list);
-
- if (Blessed)
+ if (_chargeTime > 0)
{
- if (BlessedFor != null)
- {
- list.Add(
- 1072304,
- !string.IsNullOrEmpty(BlessedFor.Name) ? BlessedFor.Name : "Unnamed Warrior"
- ); // Owned by ~1_name~
- }
- else
- {
- list.Add(1072304, "Nobody"); // Owned by ~1_name~
- }
+ list.Add(1074884, _chargeTime); // Charge time left: ~1_val~
}
-
- if (Parent is Mobile && m_MaxChargeTime > 0)
+ else
{
- if (m_ChargeTime > 0)
- {
- list.Add(1074884, m_ChargeTime); // Charge time left: ~1_val~
- }
- else
- {
- list.Add(1074883); // Fully Charged
- }
- }
-
- list.Add(1075085); // Requirement: Mondain's Legacy
-
- if (m_Killer?.IsEmpty == false && m_Killer.Amount > 0)
- {
- list.Add(
- 1072388, // ~1_NAME~ Killer: +~2_val~%
- $"{m_Killer.Name ?? "Unknown"}\t{m_Killer.Amount}"
- );
- }
-
- if (m_Protection?.IsEmpty == false && m_Protection.Amount > 0)
- {
- list.Add(
- 1072387, // ~1_NAME~ Protection: +~2_val~%
- $"{m_Protection.Name ?? "Unknown"}\t{m_Protection.Amount}"
- );
- }
-
- if (m_ExceptionalBonus != 0)
- {
- list.Add(
- 1072395, // ~1_NAME~ Exceptional Bonus: ~2_val~%
- $"{AosSkillBonuses.GetLabel(m_Skill):#}\t{m_ExceptionalBonus}"
- );
- }
-
- if (m_SuccessBonus != 0)
- {
- list.Add(
- 1072394, // ~1_NAME~ Bonus: ~2_val~%
- $"{AosSkillBonuses.GetLabel(m_Skill):#}\t{m_SuccessBonus}"
- );
- }
-
- SkillBonuses.GetProperties(list);
-
- int prop;
-
- if ((prop = Attributes.WeaponDamage) != 0)
- {
- list.Add(1060401, prop); // damage increase ~1_val~%
- }
-
- if ((prop = Attributes.DefendChance) != 0)
- {
- list.Add(1060408, prop); // defense chance increase ~1_val~%
- }
-
- if ((prop = Attributes.BonusDex) != 0)
- {
- list.Add(1060409, prop); // dexterity bonus ~1_val~
- }
-
- if ((prop = Attributes.EnhancePotions) != 0)
- {
- list.Add(1060411, prop); // enhance potions ~1_val~%
- }
-
- if ((prop = Attributes.CastRecovery) != 0)
- {
- list.Add(1060412, prop); // faster cast recovery ~1_val~
- }
-
- if ((prop = Attributes.CastSpeed) != 0)
- {
- list.Add(1060413, prop); // faster casting ~1_val~
- }
-
- if ((prop = Attributes.AttackChance) != 0)
- {
- list.Add(1060415, prop); // hit chance increase ~1_val~%
- }
-
- if ((prop = Attributes.BonusHits) != 0)
- {
- list.Add(1060431, prop); // hit point increase ~1_val~
- }
-
- if ((prop = Attributes.BonusInt) != 0)
- {
- list.Add(1060432, prop); // intelligence bonus ~1_val~
- }
-
- if ((prop = Attributes.LowerManaCost) != 0)
- {
- list.Add(1060433, prop); // lower mana cost ~1_val~%
- }
-
- if ((prop = Attributes.LowerRegCost) != 0)
- {
- list.Add(1060434, prop); // lower reagent cost ~1_val~%
- }
-
- if ((prop = Attributes.Luck) != 0)
- {
- list.Add(1060436, prop); // luck ~1_val~
- }
-
- if ((prop = Attributes.BonusMana) != 0)
- {
- list.Add(1060439, prop); // mana increase ~1_val~
- }
-
- if ((prop = Attributes.RegenMana) != 0)
- {
- list.Add(1060440, prop); // mana regeneration ~1_val~
- }
-
- if (Attributes.NightSight != 0)
- {
- list.Add(1060441); // night sight
- }
-
- if ((prop = Attributes.ReflectPhysical) != 0)
- {
- list.Add(1060442, prop); // reflect physical damage ~1_val~%
- }
-
- if ((prop = Attributes.RegenStam) != 0)
- {
- list.Add(1060443, prop); // stamina regeneration ~1_val~
- }
-
- if ((prop = Attributes.RegenHits) != 0)
- {
- list.Add(1060444, prop); // hit point regeneration ~1_val~
- }
-
- if (Attributes.SpellChanneling != 0)
- {
- list.Add(1060482); // spell channeling
- }
-
- if ((prop = Attributes.SpellDamage) != 0)
- {
- list.Add(1060483, prop); // spell damage increase ~1_val~%
- }
-
- if ((prop = Attributes.BonusStam) != 0)
- {
- list.Add(1060484, prop); // stamina increase ~1_val~
- }
-
- if ((prop = Attributes.BonusStr) != 0)
- {
- list.Add(1060485, prop); // strength bonus ~1_val~
- }
-
- if ((prop = Attributes.WeaponSpeed) != 0)
- {
- list.Add(1060486, prop); // swing speed increase ~1_val~%
- }
-
- if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0)
- {
- list.Add(1075210, prop); // Increased Karma Loss ~1val~%
- }
-
- if (m_MaxCharges > 0)
- {
- list.Add(1060741, m_Charges); // charges: ~1_val~
- }
-
- if (m_Slayer != TalismanSlayerName.None)
- {
- list.Add(1072503 + (int)m_Slayer);
+ list.Add(1074883); // Fully Charged
}
}
- private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf)
+ list.Add(1075085); // Requirement: Mondain's Legacy
+
+ if (_killer?.IsEmpty == false && _killer.Amount > 0)
{
- if (setIf)
- {
- flags |= toSet;
- }
+ // ~1_NAME~ Killer: +~2_val~%
+ list.Add(1072388, $"{_killer.Name ?? "Unknown"}\t{_killer.Amount}");
}
- private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0;
-
- public override void Serialize(IGenericWriter writer)
+ if (_protection?.IsEmpty == false && _protection.Amount > 0)
{
- base.Serialize(writer);
-
- writer.Write(0); // version
-
- var flags = SaveFlag.None;
-
- SetSaveFlag(ref flags, SaveFlag.Attributes, !Attributes.IsEmpty);
- SetSaveFlag(ref flags, SaveFlag.SkillBonuses, !SkillBonuses.IsEmpty);
- SetSaveFlag(ref flags, SaveFlag.Protection, m_Protection?.IsEmpty == false);
- SetSaveFlag(ref flags, SaveFlag.Killer, m_Killer?.IsEmpty == false);
- SetSaveFlag(ref flags, SaveFlag.Summoner, m_Summoner?.IsEmpty == false);
- SetSaveFlag(ref flags, SaveFlag.Removal, m_Removal != TalismanRemoval.None);
- SetSaveFlag(ref flags, SaveFlag.Skill, (int)m_Skill != 0);
- SetSaveFlag(ref flags, SaveFlag.SuccessBonus, m_SuccessBonus != 0);
- SetSaveFlag(ref flags, SaveFlag.ExceptionalBonus, m_ExceptionalBonus != 0);
- SetSaveFlag(ref flags, SaveFlag.MaxCharges, m_MaxCharges != 0);
- SetSaveFlag(ref flags, SaveFlag.Charges, m_Charges != 0);
- SetSaveFlag(ref flags, SaveFlag.MaxChargeTime, m_MaxChargeTime != 0);
- SetSaveFlag(ref flags, SaveFlag.ChargeTime, m_ChargeTime != 0);
- SetSaveFlag(ref flags, SaveFlag.Blessed, m_Blessed);
- SetSaveFlag(ref flags, SaveFlag.Slayer, m_Slayer != TalismanSlayerName.None);
-
- writer.WriteEncodedInt((int)flags);
-
- if (GetSaveFlag(flags, SaveFlag.Attributes))
- {
- Attributes.Serialize(writer);
- }
-
- if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
- {
- SkillBonuses.Serialize(writer);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Protection))
- {
- Protection.Serialize(writer);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Killer))
- {
- Killer.Serialize(writer);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Summoner))
- {
- Summoner.Serialize(writer);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Removal))
- {
- writer.WriteEncodedInt((int)m_Removal);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Skill))
- {
- writer.WriteEncodedInt((int)m_Skill);
- }
-
- if (GetSaveFlag(flags, SaveFlag.SuccessBonus))
- {
- writer.WriteEncodedInt(m_SuccessBonus);
- }
-
- if (GetSaveFlag(flags, SaveFlag.ExceptionalBonus))
- {
- writer.WriteEncodedInt(m_ExceptionalBonus);
- }
-
- if (GetSaveFlag(flags, SaveFlag.MaxCharges))
- {
- writer.WriteEncodedInt(m_MaxCharges);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Charges))
- {
- writer.WriteEncodedInt(m_Charges);
- }
-
- if (GetSaveFlag(flags, SaveFlag.MaxChargeTime))
- {
- writer.WriteEncodedInt(m_MaxChargeTime);
- }
-
- if (GetSaveFlag(flags, SaveFlag.ChargeTime))
- {
- writer.WriteEncodedInt(m_ChargeTime);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Slayer))
- {
- writer.WriteEncodedInt((int)m_Slayer);
- }
+ // ~1_NAME~ Protection: +~2_val~%
+ list.Add(1072387, $"{_protection.Name ?? "Unknown"}\t{_protection.Amount}");
}
- public override void Deserialize(IGenericReader reader)
+ if (_exceptionalBonus != 0)
{
- base.Deserialize(reader);
-
- var version = reader.ReadInt();
-
- var flags = (SaveFlag)reader.ReadEncodedInt();
-
- Attributes = new AosAttributes(this);
- if (GetSaveFlag(flags, SaveFlag.Attributes))
- {
- Attributes.Deserialize(reader);
- }
-
- SkillBonuses = new AosSkillBonuses(this);
- if (GetSaveFlag(flags, SaveFlag.SkillBonuses))
- {
- SkillBonuses.Deserialize(reader);
- }
-
- // Backward compatibility
- if (GetSaveFlag(flags, SaveFlag.Owner))
- {
- BlessedFor = reader.ReadEntity();
- }
-
- m_Protection = GetSaveFlag(flags, SaveFlag.Protection)
- ? new TalismanAttribute(reader)
- : new TalismanAttribute();
- m_Killer = GetSaveFlag(flags, SaveFlag.Killer)
- ? new TalismanAttribute(reader)
- : new TalismanAttribute();
- m_Summoner = GetSaveFlag(flags, SaveFlag.Summoner)
- ? new TalismanAttribute(reader)
- : new TalismanAttribute();
-
- if (GetSaveFlag(flags, SaveFlag.Removal))
- {
- m_Removal = (TalismanRemoval)reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.OldKarmaLoss))
- {
- Attributes.IncreasedKarmaLoss = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.Skill))
- {
- m_Skill = (SkillName)reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.SuccessBonus))
- {
- m_SuccessBonus = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.ExceptionalBonus))
- {
- m_ExceptionalBonus = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.MaxCharges))
- {
- m_MaxCharges = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.Charges))
- {
- m_Charges = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.MaxChargeTime))
- {
- m_MaxChargeTime = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.ChargeTime))
- {
- m_ChargeTime = reader.ReadEncodedInt();
- }
-
- if (GetSaveFlag(flags, SaveFlag.Slayer))
- {
- m_Slayer = (TalismanSlayerName)reader.ReadEncodedInt();
- }
-
- m_Blessed = GetSaveFlag(flags, SaveFlag.Blessed);
-
- if (Parent is Mobile m)
- {
- Attributes.AddStatBonuses(m);
- SkillBonuses.AddTo(m);
-
- if (m_ChargeTime > 0)
- {
- StartTimer();
- }
- }
+ // ~1_NAME~ Exceptional Bonus: ~2_val~%
+ list.Add(1072395,$"{AosSkillBonuses.GetLabel(_skill):#}\t{_exceptionalBonus}");
}
- public virtual void OnAfterUse(Mobile m)
+ if (_successBonus != 0)
{
- m_ChargeTime = m_MaxChargeTime;
+ // ~1_NAME~ Bonus: ~2_val~%
+ list.Add(1072394,$"{AosSkillBonuses.GetLabel(_skill):#}\t{_successBonus}");
+ }
- if (m_Charges > 0 && m_MaxCharges > 0)
- {
- m_Charges -= 1;
- }
+ SkillBonuses.GetProperties(list);
- if (m_ChargeTime > 0)
+ int prop;
+
+ if ((prop = Attributes.WeaponDamage) != 0)
+ {
+ list.Add(1060401, prop); // damage increase ~1_val~%
+ }
+
+ if ((prop = Attributes.DefendChance) != 0)
+ {
+ list.Add(1060408, prop); // defense chance increase ~1_val~%
+ }
+
+ if ((prop = Attributes.BonusDex) != 0)
+ {
+ list.Add(1060409, prop); // dexterity bonus ~1_val~
+ }
+
+ if ((prop = Attributes.EnhancePotions) != 0)
+ {
+ list.Add(1060411, prop); // enhance potions ~1_val~%
+ }
+
+ if ((prop = Attributes.CastRecovery) != 0)
+ {
+ list.Add(1060412, prop); // faster cast recovery ~1_val~
+ }
+
+ if ((prop = Attributes.CastSpeed) != 0)
+ {
+ list.Add(1060413, prop); // faster casting ~1_val~
+ }
+
+ if ((prop = Attributes.AttackChance) != 0)
+ {
+ list.Add(1060415, prop); // hit chance increase ~1_val~%
+ }
+
+ if ((prop = Attributes.BonusHits) != 0)
+ {
+ list.Add(1060431, prop); // hit point increase ~1_val~
+ }
+
+ if ((prop = Attributes.BonusInt) != 0)
+ {
+ list.Add(1060432, prop); // intelligence bonus ~1_val~
+ }
+
+ if ((prop = Attributes.LowerManaCost) != 0)
+ {
+ list.Add(1060433, prop); // lower mana cost ~1_val~%
+ }
+
+ if ((prop = Attributes.LowerRegCost) != 0)
+ {
+ list.Add(1060434, prop); // lower reagent cost ~1_val~%
+ }
+
+ if ((prop = Attributes.Luck) != 0)
+ {
+ list.Add(1060436, prop); // luck ~1_val~
+ }
+
+ if ((prop = Attributes.BonusMana) != 0)
+ {
+ list.Add(1060439, prop); // mana increase ~1_val~
+ }
+
+ if ((prop = Attributes.RegenMana) != 0)
+ {
+ list.Add(1060440, prop); // mana regeneration ~1_val~
+ }
+
+ if (Attributes.NightSight != 0)
+ {
+ list.Add(1060441); // night sight
+ }
+
+ if ((prop = Attributes.ReflectPhysical) != 0)
+ {
+ list.Add(1060442, prop); // reflect physical damage ~1_val~%
+ }
+
+ if ((prop = Attributes.RegenStam) != 0)
+ {
+ list.Add(1060443, prop); // stamina regeneration ~1_val~
+ }
+
+ if ((prop = Attributes.RegenHits) != 0)
+ {
+ list.Add(1060444, prop); // hit point regeneration ~1_val~
+ }
+
+ if (Attributes.SpellChanneling != 0)
+ {
+ list.Add(1060482); // spell channeling
+ }
+
+ if ((prop = Attributes.SpellDamage) != 0)
+ {
+ list.Add(1060483, prop); // spell damage increase ~1_val~%
+ }
+
+ if ((prop = Attributes.BonusStam) != 0)
+ {
+ list.Add(1060484, prop); // stamina increase ~1_val~
+ }
+
+ if ((prop = Attributes.BonusStr) != 0)
+ {
+ list.Add(1060485, prop); // strength bonus ~1_val~
+ }
+
+ if ((prop = Attributes.WeaponSpeed) != 0)
+ {
+ list.Add(1060486, prop); // swing speed increase ~1_val~%
+ }
+
+ if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0)
+ {
+ list.Add(1075210, prop); // Increased Karma Loss ~1val~%
+ }
+
+ if (_maxCharges > 0)
+ {
+ list.Add(1060741, _charges); // charges: ~1_val~
+ }
+
+ if (_slayer != TalismanSlayerName.None)
+ {
+ list.Add(1072503 + (int)_slayer);
+ }
+ }
+
+ [AfterDeserialization]
+ private void AfterDeserialization()
+ {
+ if (Parent is Mobile m)
+ {
+ Attributes.AddStatBonuses(m);
+ SkillBonuses.AddTo(m);
+
+ if (_chargeTime > 0)
{
StartTimer();
}
+ }
+ }
- InvalidateProperties();
+ public override void OnDelete()
+ {
+ _creature?.Delete(); // Will stop the unsummon timer on OnAfterDelete()
+ }
+
+ public virtual void OnAfterUse(Mobile m)
+ {
+ _chargeTime = _maxChargeTime;
+
+ if (_charges > 0 && _maxCharges > 0)
+ {
+ _charges -= 1;
}
- public virtual Type GetSummoner() => null;
-
- public virtual void SetSummoner(Type type, TextDefinition name)
+ if (_chargeTime > 0)
{
- m_Summoner = new TalismanAttribute(type, name);
+ StartTimer();
}
- public virtual void SetProtection(Type type, TextDefinition name, int amount)
+ InvalidateProperties();
+ }
+
+ public virtual Type GetSummoner() => null;
+
+ public virtual void SetSummoner(Type type, TextDefinition name)
+ {
+ _summoner = new TalismanAttribute(type, name);
+ }
+
+ public virtual void SetProtection(Type type, TextDefinition name, int amount)
+ {
+ _protection = new TalismanAttribute(type, name, amount);
+ }
+
+ public virtual void SetKiller(Type type, TextDefinition name, int amount)
+ {
+ _killer = new TalismanAttribute(type, name, amount);
+ }
+
+ public virtual void StartTimer()
+ {
+ if (!_timerToken.Running)
{
- m_Protection = new TalismanAttribute(type, name, amount);
+ Timer.StartTimer(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), Slice, out _timerToken);
+ }
+ }
+
+ public virtual void StopTimer()
+ {
+ _timerToken.Cancel();
+ }
+
+ public virtual void Slice()
+ {
+ if (Deleted)
+ {
+ StopTimer();
+ return;
}
- public virtual void SetKiller(Type type, TextDefinition name, int amount)
+ if (_chargeTime - 10 > 0)
{
- m_Killer = new TalismanAttribute(type, name, amount);
+ _chargeTime -= 10;
+ }
+ else
+ {
+ _chargeTime = 0;
+
+ StopTimer();
}
- public virtual void StartTimer()
+ InvalidateProperties();
+ }
+
+ public static int GetRandomItemID() => _itemIDs.RandomElement();
+
+ public static Type GetRandomSummonType() => _summons.RandomElement();
+
+ public static TalismanAttribute GetRandomSummoner()
+ {
+ if (Utility.RandomDouble() < 0.975)
{
- if (!_timerToken.Running)
+ return new TalismanAttribute();
+ }
+
+ var num = Utility.Random(_summons.Length);
+
+ return num > 14
+ ? new TalismanAttribute(_summons[num], _summonLabels[num], 10)
+ : new TalismanAttribute(_summons[num], _summonLabels[num]);
+ }
+
+ public static TalismanRemoval GetRandomRemoval()
+ {
+ if (Utility.RandomDouble() < 0.65)
+ {
+ return (TalismanRemoval)Utility.RandomList(390, 404, 407);
+ }
+
+ return TalismanRemoval.None;
+ }
+
+ public static TalismanAttribute GetRandomKiller() => GetRandomKiller(true);
+
+ public static TalismanAttribute GetRandomKiller(bool includingNone)
+ {
+ if (includingNone && Utility.RandomBool())
+ {
+ return new TalismanAttribute();
+ }
+
+ var num = Utility.Random(_killers.Length);
+
+ return new TalismanAttribute(_killers[num], _killerLabels[num], Utility.RandomMinMax(10, 100));
+ }
+
+ public static TalismanAttribute GetRandomProtection() => GetRandomProtection(true);
+
+ public static TalismanAttribute GetRandomProtection(bool includingNone)
+ {
+ if (includingNone && Utility.RandomBool())
+ {
+ return new TalismanAttribute();
+ }
+
+ var num = Utility.Random(_killers.Length);
+
+ return new TalismanAttribute(_killers[num], _killerLabels[num], Utility.RandomMinMax(5, 60));
+ }
+
+ public static SkillName GetRandomSkill() => _skills.RandomElement();
+
+ public static int GetRandomExceptional()
+ {
+ if (Utility.RandomDouble() < 0.3)
+ {
+ var num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5;
+
+ return (int)Math.Round(num);
+ }
+
+ return 0;
+ }
+
+ public static int GetRandomSuccessful()
+ {
+ if (Utility.RandomDouble() < 0.75)
+ {
+ var num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5;
+
+ return (int)Math.Round(num);
+ }
+
+ return 0;
+ }
+
+ public static bool GetRandomBlessed() => Utility.RandomDouble() < 0.02;
+
+ public static TalismanSlayerName GetRandomSlayer() => Utility.RandomDouble() < 0.01
+ ? (TalismanSlayerName)Utility.RandomMinMax(1, 9)
+ : TalismanSlayerName.None;
+
+ public static int GetRandomCharges() => Utility.RandomBool() ? Utility.RandomMinMax(10, 50) : 0;
+
+ private class TalismanTarget : Target
+ {
+ private readonly BaseTalisman m_Talisman;
+
+ public TalismanTarget(BaseTalisman talisman)
+ : base(12, false, TargetFlags.Beneficial) =>
+ m_Talisman = talisman;
+
+ protected override void OnTarget(Mobile from, object o)
+ {
+ if (m_Talisman?.Deleted != false)
{
- Timer.StartTimer(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), Slice, out _timerToken);
- }
- }
-
- public virtual void StopTimer()
- {
- _timerToken.Cancel();
- }
-
- public virtual void Slice()
- {
- if (Deleted)
- {
- StopTimer();
return;
}
- if (m_ChargeTime - 10 > 0)
+ if (from.Talisman != m_Talisman)
{
- m_ChargeTime -= 10;
- }
- else
- {
- m_ChargeTime = 0;
-
- StopTimer();
+ from.SendLocalizedMessage(502641); // You must equip this item to use it.
+ return;
}
- InvalidateProperties();
- }
-
- public static int GetRandomItemID() => m_ItemIDs.RandomElement();
-
- public static Type GetRandomSummonType() => m_Summons.RandomElement();
-
- public static TalismanAttribute GetRandomSummoner()
- {
- if (Utility.RandomDouble() < 0.975)
+ if (o is not Mobile target)
{
- return new TalismanAttribute();
+ from.SendLocalizedMessage(1046439); // That is not a valid target.
+ return;
}
- var num = Utility.Random(m_Summons.Length);
-
- return num > 14
- ? new TalismanAttribute(m_Summons[num], m_SummonLabels[num], 10)
- : new TalismanAttribute(m_Summons[num], m_SummonLabels[num]);
- }
-
- public static TalismanRemoval GetRandomRemoval()
- {
- if (Utility.RandomDouble() < 0.65)
+ if (m_Talisman.ChargeTime > 0)
{
- return (TalismanRemoval)Utility.RandomList(390, 404, 407);
+ from.SendLocalizedMessage(
+ 1074882, // You must wait ~1_val~ seconds for this to recharge.
+ m_Talisman.ChargeTime.ToString()
+ );
+ return;
}
- return TalismanRemoval.None;
- }
-
- public static TalismanAttribute GetRandomKiller() => GetRandomKiller(true);
-
- public static TalismanAttribute GetRandomKiller(bool includingNone)
- {
- if (includingNone && Utility.RandomBool())
+ if (m_Talisman.Charges == 0 && m_Talisman.MaxCharges > 0)
{
- return new TalismanAttribute();
+ from.SendLocalizedMessage(1042544); // This item is out of charges.
+ return;
}
- var num = Utility.Random(m_Killers.Length);
-
- return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(10, 100));
- }
-
- public static TalismanAttribute GetRandomProtection() => GetRandomProtection(true);
-
- public static TalismanAttribute GetRandomProtection(bool includingNone)
- {
- if (includingNone && Utility.RandomBool())
+ switch (m_Talisman.Removal)
{
- return new TalismanAttribute();
- }
+ case TalismanRemoval.Curse:
+ target.PlaySound(0xF6);
+ target.PlaySound(0x1F7);
+ target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head);
- var num = Utility.Random(m_Killers.Length);
-
- return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(5, 60));
- }
-
- public static SkillName GetRandomSkill() => m_Skills.RandomElement();
-
- public static int GetRandomExceptional()
- {
- if (Utility.RandomDouble() < 0.3)
- {
- var num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5;
-
- return (int)Math.Round(num);
- }
-
- return 0;
- }
-
- public static int GetRandomSuccessful()
- {
- if (Utility.RandomDouble() < 0.75)
- {
- var num = 40 - Math.Log(Utility.RandomMinMax(7, 403)) * 5;
-
- return (int)Math.Round(num);
- }
-
- return 0;
- }
-
- public static bool GetRandomBlessed() => Utility.RandomDouble() < 0.02;
-
- public static TalismanSlayerName GetRandomSlayer() => Utility.RandomDouble() < 0.01
- ? (TalismanSlayerName)Utility.RandomMinMax(1, 9)
- : TalismanSlayerName.None;
-
- public static int GetRandomCharges() => Utility.RandomBool() ? Utility.RandomMinMax(10, 50) : 0;
-
- [Flags]
- private enum SaveFlag
- {
- None = 0x00000000,
- Attributes = 0x00000001,
- SkillBonuses = 0x00000002,
- Owner = 0x00000004,
- Protection = 0x00000008,
- Killer = 0x00000010,
- Summoner = 0x00000020,
- Removal = 0x00000040,
- OldKarmaLoss = 0x00000080,
- Skill = 0x00000100,
- SuccessBonus = 0x00000200,
- ExceptionalBonus = 0x00000400,
- MaxCharges = 0x00000800,
- Charges = 0x00001000,
- MaxChargeTime = 0x00002000,
- ChargeTime = 0x00004000,
- Blessed = 0x00008000,
- Slayer = 0x00010000
- }
-
- private class TalismanTarget : Target
- {
- private readonly BaseTalisman m_Talisman;
-
- public TalismanTarget(BaseTalisman talisman)
- : base(12, false, TargetFlags.Beneficial) =>
- m_Talisman = talisman;
-
- protected override void OnTarget(Mobile from, object o)
- {
- if (m_Talisman?.Deleted != false)
- {
- return;
- }
-
- if (from.Talisman != m_Talisman)
- {
- from.SendLocalizedMessage(502641); // You must equip this item to use it.
- return;
- }
-
- if (o is not Mobile target)
- {
- from.SendLocalizedMessage(1046439); // That is not a valid target.
- return;
- }
-
- if (m_Talisman.ChargeTime > 0)
- {
- from.SendLocalizedMessage(
- 1074882, // You must wait ~1_val~ seconds for this to recharge.
- m_Talisman.ChargeTime.ToString()
+ IEntity mfrom = new Entity(
+ Serial.Zero,
+ new Point3D(target.X, target.Y, target.Z - 10),
+ from.Map
+ );
+ IEntity mto = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z + 50), from.Map);
+ Effects.SendMovingParticles(
+ mfrom,
+ mto,
+ 0x2255,
+ 1,
+ 0,
+ false,
+ false,
+ 13,
+ 3,
+ 9501,
+ 1,
+ 0,
+ EffectLayer.Head,
+ 0x100
);
- return;
- }
- if (m_Talisman.Charges == 0 && m_Talisman.MaxCharges > 0)
- {
- from.SendLocalizedMessage(1042544); // This item is out of charges.
- return;
- }
+ var mod = target.GetStatMod("[Magic] Str Curse");
+ if (mod?.Offset < 0)
+ {
+ target.RemoveStatMod("[Magic] Str Curse");
+ }
- switch (m_Talisman.Removal)
- {
- case TalismanRemoval.Curse:
- target.PlaySound(0xF6);
- target.PlaySound(0x1F7);
- target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head);
+ mod = target.GetStatMod("[Magic] Dex Curse");
+ if (mod?.Offset < 0)
+ {
+ target.RemoveStatMod("[Magic] Dex Curse");
+ }
- IEntity mfrom = new Entity(
- Serial.Zero,
- new Point3D(target.X, target.Y, target.Z - 10),
- from.Map
- );
- IEntity mto = new Entity(Serial.Zero, new Point3D(target.X, target.Y, target.Z + 50), from.Map);
- Effects.SendMovingParticles(
- mfrom,
- mto,
- 0x2255,
- 1,
- 0,
- false,
- false,
- 13,
- 3,
- 9501,
- 1,
- 0,
- EffectLayer.Head,
- 0x100
- );
+ mod = target.GetStatMod("[Magic] Int Curse");
+ if (mod?.Offset < 0)
+ {
+ target.RemoveStatMod("[Magic] Int Curse");
+ }
- var mod = target.GetStatMod("[Magic] Str Curse");
- if (mod?.Offset < 0)
- {
- target.RemoveStatMod("[Magic] Str Curse");
- }
+ target.Paralyzed = false;
- mod = target.GetStatMod("[Magic] Dex Curse");
- if (mod?.Offset < 0)
- {
- target.RemoveStatMod("[Magic] Dex Curse");
- }
+ EvilOmenSpell.EndEffect(target);
+ StrangleSpell.RemoveCurse(target);
+ CorpseSkinSpell.RemoveCurse(target);
+ CurseSpell.RemoveEffect(target);
- mod = target.GetStatMod("[Magic] Int Curse");
- if (mod?.Offset < 0)
- {
- target.RemoveStatMod("[Magic] Int Curse");
- }
+ BuffInfo.RemoveBuff(target, BuffIcon.Clumsy);
+ BuffInfo.RemoveBuff(target, BuffIcon.FeebleMind);
+ BuffInfo.RemoveBuff(target, BuffIcon.Weaken);
+ BuffInfo.RemoveBuff(target, BuffIcon.MassCurse);
- target.Paralyzed = false;
+ target.SendLocalizedMessage(1072408); // Any curses on you have been lifted
- EvilOmenSpell.EndEffect(target);
- StrangleSpell.RemoveCurse(target);
- CorpseSkinSpell.RemoveCurse(target);
- CurseSpell.RemoveEffect(target);
+ if (target != from)
+ {
+ from.SendLocalizedMessage(1072409); // Your targets curses have been lifted
+ }
- BuffInfo.RemoveBuff(target, BuffIcon.Clumsy);
- BuffInfo.RemoveBuff(target, BuffIcon.FeebleMind);
- BuffInfo.RemoveBuff(target, BuffIcon.Weaken);
- BuffInfo.RemoveBuff(target, BuffIcon.MassCurse);
+ break;
+ case TalismanRemoval.Damage:
+ target.PlaySound(0x201);
+ Effects.SendLocationParticles(
+ EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 1,
+ 13,
+ 0x834,
+ 0,
+ 0x13B2,
+ 0
+ );
- target.SendLocalizedMessage(1072408); // Any curses on you have been lifted
+ BleedAttack.EndBleed(target, true);
+ MortalStrike.EndWound(target);
- if (target != from)
- {
- from.SendLocalizedMessage(1072409); // Your targets curses have been lifted
- }
+ BuffInfo.RemoveBuff(target, BuffIcon.Bleed);
+ BuffInfo.RemoveBuff(target, BuffIcon.MortalStrike);
- break;
- case TalismanRemoval.Damage:
- target.PlaySound(0x201);
- Effects.SendLocationParticles(
- EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
- 0x3728,
- 1,
- 13,
- 0x834,
- 0,
- 0x13B2,
- 0
- );
+ target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed!
- BleedAttack.EndBleed(target, true);
- MortalStrike.EndWound(target);
+ if (target != from)
+ {
+ from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects have been removed!
+ }
- BuffInfo.RemoveBuff(target, BuffIcon.Bleed);
- BuffInfo.RemoveBuff(target, BuffIcon.MortalStrike);
+ break;
+ case TalismanRemoval.Ward:
+ target.PlaySound(0x201);
+ Effects.SendLocationParticles(
+ EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 1,
+ 13,
+ 0x834,
+ 0,
+ 0x13B2,
+ 0
+ );
- target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed!
+ MagicReflectSpell.EndReflect(target);
+ ReactiveArmorSpell.EndArmor(target);
+ ProtectionSpell.EndProtection(target);
- if (target != from)
- {
- from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects have been removed!
- }
+ target.SendLocalizedMessage(1072402); // Your wards have been removed!
- break;
- case TalismanRemoval.Ward:
- target.PlaySound(0x201);
- Effects.SendLocationParticles(
- EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration),
- 0x3728,
- 1,
- 13,
- 0x834,
- 0,
- 0x13B2,
- 0
- );
+ if (target != from)
+ {
+ from.SendLocalizedMessage(1072403); // Your target's wards have been removed!
+ }
- MagicReflectSpell.EndReflect(target);
- ReactiveArmorSpell.EndArmor(target);
- ProtectionSpell.EndProtection(target);
-
- target.SendLocalizedMessage(1072402); // Your wards have been removed!
-
- if (target != from)
- {
- from.SendLocalizedMessage(1072403); // Your target's wards have been removed!
- }
-
- break;
- case TalismanRemoval.Wildfire:
- // TODO
- break;
- }
-
- m_Talisman.OnAfterUse(from);
+ break;
+ case TalismanRemoval.Wildfire:
+ // TODO
+ break;
}
+
+ m_Talisman.OnAfterUse(from);
}
}
}
diff --git a/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs b/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs
index a012f8a29..0258a5feb 100644
--- a/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs
+++ b/Projects/UOContent/Items/Talismans/Items/EnchantedSwitch.cs
@@ -1,28 +1,12 @@
-namespace Server.Items
+using ModernUO.Serialization;
+
+namespace Server.Items;
+
+[SerializationGenerator(0, false)]
+public partial class EnchantedSwitch : Item
{
- public class EnchantedSwitch : Item
- {
- [Constructible]
- public EnchantedSwitch() : base(0x2F5C) => Weight = 1.0;
+ [Constructible]
+ public EnchantedSwitch() : base(0x2F5C) => Weight = 1.0;
- public EnchantedSwitch(Serial serial) : base(serial)
- {
- }
-
- public override int LabelNumber => 1072893; // enchanted switch
-
- 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();
- }
- }
+ public override int LabelNumber => 1072893; // enchanted switch
}
diff --git a/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs b/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs
index f073fb27e..7f58dcfa5 100644
--- a/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs
+++ b/Projects/UOContent/Items/Talismans/Items/HollowPrism.cs
@@ -1,28 +1,12 @@
-namespace Server.Items
+using ModernUO.Serialization;
+
+namespace Server.Items;
+
+[SerializationGenerator(0, false)]
+public partial class HollowPrism : Item
{
- public class HollowPrism : Item
- {
- [Constructible]
- public HollowPrism() : base(0x2F5D) => Weight = 1.0;
+ [Constructible]
+ public HollowPrism() : base(0x2F5D) => Weight = 1.0;
- public HollowPrism(Serial serial) : base(serial)
- {
- }
-
- public override int LabelNumber => 1072895; // hollow prism
-
- 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();
- }
- }
+ public override int LabelNumber => 1072895; // hollow prism
}
diff --git a/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs b/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs
index ebfc68296..8164dc22e 100644
--- a/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs
+++ b/Projects/UOContent/Items/Talismans/Items/JeweledFiligree.cs
@@ -1,28 +1,12 @@
-namespace Server.Items
+using ModernUO.Serialization;
+
+namespace Server.Items;
+
+[SerializationGenerator(0, false)]
+public partial class JeweledFiligree : Item
{
- public class JeweledFiligree : Item
- {
- [Constructible]
- public JeweledFiligree() : base(0x2F5E) => Weight = 1.0;
+ [Constructible]
+ public JeweledFiligree() : base(0x2F5E) => Weight = 1.0;
- public JeweledFiligree(Serial serial) : base(serial)
- {
- }
-
- public override int LabelNumber => 1072894; // jeweled filigree
-
- 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();
- }
- }
+ public override int LabelNumber => 1072894; // jeweled filigree
}
diff --git a/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs b/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs
index 5dde27609..af7429967 100644
--- a/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs
+++ b/Projects/UOContent/Items/Talismans/Items/RunedPrism.cs
@@ -1,28 +1,12 @@
-namespace Server.Items
+using ModernUO.Serialization;
+
+namespace Server.Items;
+
+[SerializationGenerator(0, false)]
+public partial class RunedPrism : Item
{
- public class RunedPrism : Item
- {
- [Constructible]
- public RunedPrism() : base(0x2F57) => Weight = 1.0;
+ [Constructible]
+ public RunedPrism() : base(0x2F57) => Weight = 1.0;
- public RunedPrism(Serial serial) : base(serial)
- {
- }
-
- public override int LabelNumber => 1073465; // runed prism
-
- 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();
- }
- }
+ public override int LabelNumber => 1073465; // runed prism
}
diff --git a/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs b/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs
index c791f8d7e..bc1c741c4 100644
--- a/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs
+++ b/Projects/UOContent/Items/Talismans/Items/RunedSwitch.cs
@@ -1,78 +1,64 @@
+using ModernUO.Serialization;
using Server.Targeting;
-namespace Server.Items
+namespace Server.Items;
+
+[SerializationGenerator(0, false)]
+public partial class RunedSwitch : Item
{
- public class RunedSwitch : Item
+ [Constructible]
+ public RunedSwitch() : base(0x2F61) => Weight = 1.0;
+
+ public RunedSwitch(Serial serial) : base(serial)
{
- [Constructible]
- public RunedSwitch() : base(0x2F61) => Weight = 1.0;
+ }
- public RunedSwitch(Serial serial) : base(serial)
+ public override int LabelNumber => 1072896; // runed switch
+
+ public override void OnDoubleClick(Mobile from)
+ {
+ if (IsChildOf(from.Backpack))
{
+ from.SendLocalizedMessage(1075101); // Please select an item to recharge.
+ from.Target = new InternalTarget(this);
}
-
- public override int LabelNumber => 1072896; // runed switch
-
- public override void OnDoubleClick(Mobile from)
+ else
{
- if (IsChildOf(from.Backpack))
+ from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it.
+ }
+ }
+
+ private class InternalTarget : Target
+ {
+ private readonly RunedSwitch _item;
+
+ public InternalTarget(RunedSwitch item) : base(0, false, TargetFlags.None) => _item = item;
+
+ protected override void OnTarget(Mobile from, object o)
+ {
+ if (_item?.Deleted != false)
{
- from.SendLocalizedMessage(1075101); // Please select an item to recharge.
- from.Target = new InternalTarget(this);
+ return;
}
- else
+
+ if (o is BaseTalisman talisman)
{
- from.SendLocalizedMessage(1060640); // The item must be in your backpack to use it.
- }
- }
-
- 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();
- }
-
- private class InternalTarget : Target
- {
- private readonly RunedSwitch m_Item;
-
- public InternalTarget(RunedSwitch item) : base(0, false, TargetFlags.None) => m_Item = item;
-
- protected override void OnTarget(Mobile from, object o)
- {
- if (m_Item?.Deleted != false)
+ if (talisman.Charges == 0)
{
- return;
- }
-
- if (o is BaseTalisman talisman)
- {
- if (talisman.Charges == 0)
- {
- talisman.Charges = talisman.MaxCharges;
- m_Item.Delete();
- from.SendLocalizedMessage(1075100); // The item has been recharged.
- }
- else
- {
- from.SendLocalizedMessage(
- 1075099
- ); // You cannot recharge that item until all of its current charges have been used.
- }
+ talisman.Charges = talisman.MaxCharges;
+ _item.Delete();
+ from.SendLocalizedMessage(1075100); // The item has been recharged.
}
else
{
- from.SendLocalizedMessage(1046439); // That is not a valid target.
+ // You cannot recharge that item until all of its current charges have been used.
+ from.SendLocalizedMessage(1075099);
}
}
+ else
+ {
+ from.SendLocalizedMessage(1046439); // That is not a valid target.
+ }
}
}
}
diff --git a/Projects/UOContent/Items/Talismans/RandomTalisman.cs b/Projects/UOContent/Items/Talismans/RandomTalisman.cs
index 2d552f45f..95e613363 100644
--- a/Projects/UOContent/Items/Talismans/RandomTalisman.cs
+++ b/Projects/UOContent/Items/Talismans/RandomTalisman.cs
@@ -1,62 +1,61 @@
-namespace Server.Items
+namespace Server.Items;
+
+public class RandomTalisman : BaseTalisman
{
- public class RandomTalisman : BaseTalisman
+ [Constructible]
+ public RandomTalisman() : base(GetRandomItemID())
{
- [Constructible]
- public RandomTalisman() : base(GetRandomItemID())
+ Summoner = GetRandomSummoner();
+
+ if (Summoner.IsEmpty)
{
- Summoner = GetRandomSummoner();
+ Removal = GetRandomRemoval();
- if (Summoner.IsEmpty)
+ if (Removal != TalismanRemoval.None)
{
- Removal = GetRandomRemoval();
+ MaxCharges = GetRandomCharges();
+ MaxChargeTime = 1200;
+ }
+ }
+ else
+ {
+ MaxCharges = Utility.RandomMinMax(10, 50);
- if (Removal != TalismanRemoval.None)
- {
- MaxCharges = GetRandomCharges();
- MaxChargeTime = 1200;
- }
+ if (Summoner.IsItem)
+ {
+ MaxChargeTime = 60;
}
else
{
- MaxCharges = Utility.RandomMinMax(10, 50);
-
- if (Summoner.IsItem)
- {
- MaxChargeTime = 60;
- }
- else
- {
- MaxChargeTime = 1800;
- }
+ MaxChargeTime = 1800;
}
-
- Blessed = GetRandomBlessed();
- Slayer = GetRandomSlayer();
- Protection = GetRandomProtection();
- Killer = GetRandomKiller();
- Skill = GetRandomSkill();
- ExceptionalBonus = GetRandomExceptional();
- SuccessBonus = GetRandomSuccessful();
- Charges = MaxCharges;
}
- public RandomTalisman(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();
- }
+ Blessed = GetRandomBlessed();
+ Slayer = GetRandomSlayer();
+ Protection = GetRandomProtection();
+ Killer = GetRandomKiller();
+ Skill = GetRandomSkill();
+ ExceptionalBonus = GetRandomExceptional();
+ SuccessBonus = GetRandomSuccessful();
+ Charges = MaxCharges;
}
-}
+
+ public RandomTalisman(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();
+ }
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Items/Talismans/TalismanAttribute.cs b/Projects/UOContent/Items/Talismans/TalismanAttribute.cs
index 90871bf11..e1a7ad6ec 100644
--- a/Projects/UOContent/Items/Talismans/TalismanAttribute.cs
+++ b/Projects/UOContent/Items/Talismans/TalismanAttribute.cs
@@ -1,117 +1,72 @@
using System;
+using ModernUO.Serialization;
-namespace Server.Items
+namespace Server.Items;
+
+[PropertyObject]
+[SerializationGenerator(1, false)]
+public partial class TalismanAttribute
{
- [PropertyObject]
- public class TalismanAttribute
+ [SerializableField(0)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private Type _type;
+
+ [SerializableField(1)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private TextDefinition _name;
+
+ [SerializableField(2)]
+ [SerializedCommandProperty(AccessLevel.GameMaster)]
+ private int _amount;
+
+ public TalismanAttribute() : this(null, null)
{
- public TalismanAttribute() : this(null, 0)
+ }
+
+ public TalismanAttribute(TalismanAttribute copy)
+ {
+ if (copy != null)
{
- }
-
- public TalismanAttribute(TalismanAttribute copy)
- {
- if (copy != null)
- {
- Type = copy.Type;
- Name = copy.Name;
- Amount = copy.Amount;
- }
- }
-
- public TalismanAttribute(Type type, TextDefinition name, int amount = 0)
- {
- Type = type;
- Name = name;
- Amount = amount;
- }
-
- public TalismanAttribute(IGenericReader reader)
- {
- var version = reader.ReadInt();
-
- var flags = (SaveFlag)reader.ReadEncodedInt();
-
- if (GetSaveFlag(flags, SaveFlag.Type))
- {
- Type = AssemblyHandler.FindTypeByFullName(reader.ReadString());
- }
-
- if (GetSaveFlag(flags, SaveFlag.Name))
- {
- Name = reader.ReadTextDefinition();
- }
-
- if (GetSaveFlag(flags, SaveFlag.Amount))
- {
- Amount = reader.ReadEncodedInt();
- }
- }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public Type Type { get; set; }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public TextDefinition Name { get; set; }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public int Amount { get; set; }
-
- [CommandProperty(AccessLevel.GameMaster)]
- public bool IsEmpty => Type == null;
-
- [CommandProperty(AccessLevel.GameMaster)]
- public bool IsItem => Type?.Namespace == "Server.Items";
-
- public override string ToString() => Type?.Name ?? "None";
-
- private static void SetSaveFlag(ref SaveFlag flags, SaveFlag toSet, bool setIf)
- {
- if (setIf)
- {
- flags |= toSet;
- }
- }
-
- private static bool GetSaveFlag(SaveFlag flags, SaveFlag toGet) => (flags & toGet) != 0;
-
- public virtual void Serialize(IGenericWriter writer)
- {
- writer.Write(0); // version
-
- var flags = SaveFlag.None;
-
- SetSaveFlag(ref flags, SaveFlag.Type, Type != null);
- SetSaveFlag(ref flags, SaveFlag.Name, Name != null);
- SetSaveFlag(ref flags, SaveFlag.Amount, Amount != 0);
-
- writer.WriteEncodedInt((int)flags);
-
- if (GetSaveFlag(flags, SaveFlag.Type))
- {
- writer.Write(Type!.FullName);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Name))
- {
- writer.Write(Name);
- }
-
- if (GetSaveFlag(flags, SaveFlag.Amount))
- {
- writer.WriteEncodedInt(Amount);
- }
- }
-
- public int DamageBonus(Mobile to) => to?.GetType() == Type ? Amount : 0;
-
- [Flags]
- private enum SaveFlag
- {
- None = 0x00000000,
- Type = 0x00000001,
- Name = 0x00000002,
- Amount = 0x00000004
+ _type = copy.Type;
+ _name = copy.Name;
+ _amount = copy.Amount;
}
}
+
+ public TalismanAttribute(Type type, TextDefinition name, int amount = 0)
+ {
+ _type = type;
+ _name = name;
+ _amount = amount;
+ }
+
+ private void Deserialize(IGenericReader reader, int version)
+ {
+ var flags = reader.ReadEncodedInt();
+
+ if ((flags & 0x1) != 0)
+ {
+ _type = AssemblyHandler.FindTypeByFullName(reader.ReadString());
+ }
+
+ if ((flags & 0x2) != 0)
+ {
+ _name = reader.ReadTextDefinition();
+ }
+
+ if ((flags & 0x4) != 0)
+ {
+ _amount = reader.ReadEncodedInt();
+ }
+ }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public bool IsEmpty => _type == null;
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public bool IsItem => _type.IsAssignableTo(typeof(Item));
+
+ public override string ToString() => _type?.Name ?? "None";
+
+ public int DamageBonus(Mobile to) => to?.GetType() == _type ? _amount : 0;
}
diff --git a/Projects/UOContent/Items/Talismans/TalismanSlayer.cs b/Projects/UOContent/Items/Talismans/TalismanSlayer.cs
index 7456ec9b9..2d1611ba8 100644
--- a/Projects/UOContent/Items/Talismans/TalismanSlayer.cs
+++ b/Projects/UOContent/Items/Talismans/TalismanSlayer.cs
@@ -2,106 +2,105 @@ using System;
using System.Collections.Generic;
using Server.Mobiles;
-namespace Server.Items
+namespace Server.Items;
+
+public enum TalismanSlayerName
{
- public enum TalismanSlayerName
+ None,
+ Bear,
+ Vermin,
+ Bat,
+ Mage,
+ Beetle,
+ Bird,
+ Ice,
+ Flame,
+ Bovine
+}
+
+public static class TalismanSlayer
+{
+ private static Dictionary m_Table;
+
+ public static void Initialize()
{
- None,
- Bear,
- Vermin,
- Bat,
- Mage,
- Beetle,
- Bird,
- Ice,
- Flame,
- Bovine
+ m_Table = new Dictionary
+ {
+ [TalismanSlayerName.Bear] = new[]
+ {
+ typeof(GrizzlyBear), typeof(BlackBear), typeof(BrownBear), typeof(PolarBear) // , typeof( Grobu )
+ },
+ [TalismanSlayerName.Vermin] = new[]
+ {
+ typeof(RatmanMage), typeof(RatmanMage), typeof(RatmanArcher), typeof(Barracoon), typeof(Ratman),
+ typeof(SewerRat),
+ typeof(Rat), typeof(GiantRat) // , typeof( Chiikkaha )
+ },
+ [TalismanSlayerName.Bat] = new[] { typeof(Mongbat), typeof(StrongMongbat), typeof(VampireBat) },
+ [TalismanSlayerName.Mage] =
+ new[]
+ {
+ typeof(EvilMage), typeof(EvilMageLord), typeof(AncientLich), typeof(Lich), typeof(LichLord),
+ typeof(SkeletalMage), typeof(BoneMagi), typeof(OrcishMage), typeof(KhaldunZealot), typeof(JukaMage)
+ },
+ [TalismanSlayerName.Beetle] =
+ new[]
+ {
+ typeof(Beetle), typeof(RuneBeetle), typeof(FireBeetle), typeof(DeathwatchBeetle),
+ typeof(DeathwatchBeetleHatchling)
+ },
+ [TalismanSlayerName.Bird] = new[]
+ {
+ typeof(Bird), typeof(TropicalBird), typeof(Chicken), typeof(Crane), typeof(DesertOstard), typeof(Eagle),
+ typeof(ForestOstard), typeof(FrenziedOstard),
+ typeof(Phoenix), /*typeof( Pyre ), typeof( Swoop ), typeof( Saliva ),*/ typeof(Harpy),
+ typeof(StoneHarpy) // ?????
+ },
+ [TalismanSlayerName.Ice] = new[]
+ {
+ typeof(ArcticOgreLord), typeof(IceElemental), typeof(SnowElemental), typeof(FrostOoze),
+ typeof(IceFiend), /*typeof( UnfrozenMummy ),*/ typeof(FrostSpider), typeof(LadyOfTheSnow),
+ typeof(FrostTroll),
+
+ // TODO WinterReaper, check
+ typeof(IceSnake), typeof(SnowLeopard), typeof(PolarBear), typeof(IceSerpent), typeof(GiantIceWorm)
+ },
+ [TalismanSlayerName.Flame] = new[]
+ {
+ typeof(FireBeetle), typeof(HellHound), typeof(LavaSerpent), typeof(FireElemental),
+ typeof(PredatorHellCat),
+ typeof(Phoenix), typeof(FireGargoyle), typeof(HellCat),
+ /*typeof( Pyre ),*/ typeof(FireSteed), typeof(LavaLizard),
+
+ // TODO check
+ typeof(LavaSnake)
+ },
+ [TalismanSlayerName.Bovine] = new[]
+ {
+ typeof(Cow), typeof(Bull),
+ typeof(Gaman) /*, typeof( MinotaurCaptain ), typeof( MinotaurScout ), typeof( Minotaur ) */
+ // TODO TormentedMinotaur
+ }
+ };
}
- public static class TalismanSlayer
+ public static bool Slays(TalismanSlayerName name, Mobile m)
{
- private static Dictionary m_Table;
-
- public static void Initialize()
+ if (m == null || !m_Table.TryGetValue(name, out var types) || types == null)
{
- m_Table = new Dictionary
- {
- [TalismanSlayerName.Bear] = new[]
- {
- typeof(GrizzlyBear), typeof(BlackBear), typeof(BrownBear), typeof(PolarBear) // , typeof( Grobu )
- },
- [TalismanSlayerName.Vermin] = new[]
- {
- typeof(RatmanMage), typeof(RatmanMage), typeof(RatmanArcher), typeof(Barracoon), typeof(Ratman),
- typeof(SewerRat),
- typeof(Rat), typeof(GiantRat) // , typeof( Chiikkaha )
- },
- [TalismanSlayerName.Bat] = new[] { typeof(Mongbat), typeof(StrongMongbat), typeof(VampireBat) },
- [TalismanSlayerName.Mage] =
- new[]
- {
- typeof(EvilMage), typeof(EvilMageLord), typeof(AncientLich), typeof(Lich), typeof(LichLord),
- typeof(SkeletalMage), typeof(BoneMagi), typeof(OrcishMage), typeof(KhaldunZealot), typeof(JukaMage)
- },
- [TalismanSlayerName.Beetle] =
- new[]
- {
- typeof(Beetle), typeof(RuneBeetle), typeof(FireBeetle), typeof(DeathwatchBeetle),
- typeof(DeathwatchBeetleHatchling)
- },
- [TalismanSlayerName.Bird] = new[]
- {
- typeof(Bird), typeof(TropicalBird), typeof(Chicken), typeof(Crane), typeof(DesertOstard), typeof(Eagle),
- typeof(ForestOstard), typeof(FrenziedOstard),
- typeof(Phoenix), /*typeof( Pyre ), typeof( Swoop ), typeof( Saliva ),*/ typeof(Harpy),
- typeof(StoneHarpy) // ?????
- },
- [TalismanSlayerName.Ice] = new[]
- {
- typeof(ArcticOgreLord), typeof(IceElemental), typeof(SnowElemental), typeof(FrostOoze),
- typeof(IceFiend), /*typeof( UnfrozenMummy ),*/ typeof(FrostSpider), typeof(LadyOfTheSnow),
- typeof(FrostTroll),
-
- // TODO WinterReaper, check
- typeof(IceSnake), typeof(SnowLeopard), typeof(PolarBear), typeof(IceSerpent), typeof(GiantIceWorm)
- },
- [TalismanSlayerName.Flame] = new[]
- {
- typeof(FireBeetle), typeof(HellHound), typeof(LavaSerpent), typeof(FireElemental),
- typeof(PredatorHellCat),
- typeof(Phoenix), typeof(FireGargoyle), typeof(HellCat),
- /*typeof( Pyre ),*/ typeof(FireSteed), typeof(LavaLizard),
-
- // TODO check
- typeof(LavaSnake)
- },
- [TalismanSlayerName.Bovine] = new[]
- {
- typeof(Cow), typeof(Bull),
- typeof(Gaman) /*, typeof( MinotaurCaptain ), typeof( MinotaurScout ), typeof( Minotaur ) */
- // TODO TormentedMinotaur
- }
- };
- }
-
- public static bool Slays(TalismanSlayerName name, Mobile m)
- {
- if (m == null || !m_Table.TryGetValue(name, out var types) || types == null)
- {
- return false;
- }
-
- var type = m.GetType();
-
- for (var i = 0; i < types.Length; i++)
- {
- if (types[i].IsAssignableFrom(type))
- {
- return true;
- }
- }
-
return false;
}
+
+ var type = m.GetType();
+
+ for (var i = 0; i < types.Length; i++)
+ {
+ if (types[i].IsAssignableFrom(type))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
-}
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Items/Talismans/TalismanSummons.cs b/Projects/UOContent/Items/Talismans/TalismanSummons.cs
index fc74d6fed..9ca06f0d9 100644
--- a/Projects/UOContent/Items/Talismans/TalismanSummons.cs
+++ b/Projects/UOContent/Items/Talismans/TalismanSummons.cs
@@ -1,644 +1,339 @@
using System;
using System.Collections.Generic;
+using ModernUO.Serialization;
using Server.ContextMenus;
using Server.Items;
-namespace Server.Mobiles
+namespace Server.Mobiles;
+
+[SerializationGenerator(0)]
+public partial class BaseTalismanSummon : BaseCreature
{
- public class BaseTalismanSummon : BaseCreature
+ // public override bool IsInvulnerable => true; // TODO: Wailing banshees are NOT invulnerable, are any of the others?
+
+ public BaseTalismanSummon() : base(AIType.AI_Melee, FightMode.None)
{
- // public override bool IsInvulnerable => true; // TODO: Wailing banshees are NOT invulnerable, are any of the others?
+ // TODO: Stats/skills
+ }
- public BaseTalismanSummon() : base(AIType.AI_Melee, FightMode.None)
+ public override bool Commandable => false;
+ public override bool InitialInnocent => true;
+
+ public override void AddCustomContextEntries(Mobile from, List list)
+ {
+ if (from.Alive && ControlMaster == from)
{
- // TODO: Stats/skills
- }
-
- public BaseTalismanSummon(Serial serial) : base(serial)
- {
- }
-
- public override bool Commandable => false;
- public override bool InitialInnocent => true;
-
- public override void AddCustomContextEntries(Mobile from, List list)
- {
- if (from.Alive && ControlMaster == from)
- {
- list.Add(new TalismanReleaseEntry(this));
- }
- }
-
- 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 TalismanReleaseEntry : ContextMenuEntry
- {
- private readonly Mobile m_Mobile;
-
- public TalismanReleaseEntry(Mobile m) : base(6118, 3) => m_Mobile = m;
-
- public override void OnClick()
- {
- Effects.SendLocationParticles(
- EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration),
- 0x3728,
- 8,
- 20,
- 5042
- );
-
- Effects.PlaySound(m_Mobile,0x201);
-
- m_Mobile.Delete();
- }
+ list.Add(new TalismanReleaseEntry(this));
}
}
- public class SummonedAntLion : BaseTalismanSummon
+ private class TalismanReleaseEntry : ContextMenuEntry
{
- [Constructible]
- public SummonedAntLion()
- {
- Body = 787;
- BaseSoundID = 1006;
- }
-
- public SummonedAntLion(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "an ant lion";
-
- 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();
- }
- }
-
- public class SummonedArcticOgreLord : BaseTalismanSummon
- {
- [Constructible]
- public SummonedArcticOgreLord()
- {
- Body = 135;
- BaseSoundID = 427;
- }
-
- public SummonedArcticOgreLord(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "an arctic ogre lord";
-
- 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();
- }
- }
-
- public class SummonedBakeKitsune : BaseTalismanSummon
- {
- [Constructible]
- public SummonedBakeKitsune()
- {
- Body = 246;
- BaseSoundID = 0x4DD;
- }
-
- public SummonedBakeKitsune(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a bake kitsune";
-
- 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();
- }
- }
-
- public class SummonedBogling : BaseTalismanSummon
- {
- [Constructible]
- public SummonedBogling()
- {
- Body = 779;
- BaseSoundID = 422;
- }
-
- public SummonedBogling(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a bogling";
-
- 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();
- }
- }
-
- public class SummonedBullFrog : BaseTalismanSummon
- {
- [Constructible]
- public SummonedBullFrog()
- {
- Body = 81;
- Hue = Utility.RandomList(0x5AC, 0x5A3, 0x59A, 0x591, 0x588, 0x57F);
- BaseSoundID = 0x266;
- }
-
- public SummonedBullFrog(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a bull frog";
-
- public override void Serialize(IGenericWriter writer)
- {
- base.Serialize(writer);
+ private readonly Mobile m_Mobile;
- writer.WriteEncodedInt(0); // version
- }
-
- public override void Deserialize(IGenericReader reader)
- {
- base.Deserialize(reader);
-
- var version = reader.ReadEncodedInt();
- }
- }
-
- public class SummonedChicken : BaseTalismanSummon
- {
- [Constructible]
- public SummonedChicken()
- {
- Body = 0xD0;
- BaseSoundID = 0x6E;
- }
-
- public SummonedChicken(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a chicken";
-
- 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();
- }
- }
-
- public class SummonedCow : BaseTalismanSummon
- {
- [Constructible]
- public SummonedCow()
- {
- Body = Utility.RandomList(0xD8, 0xE7);
- BaseSoundID = 0x78;
- }
-
- public SummonedCow(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a cow";
-
- 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();
- }
- }
-
- public class SummonedDoppleganger : BaseTalismanSummon
- {
- [Constructible]
- public SummonedDoppleganger()
- {
- Body = 0x309;
- BaseSoundID = 0x451;
- }
-
- public SummonedDoppleganger(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a doppleganger";
-
- 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();
- }
- }
-
- public class SummonedFrostSpider : BaseTalismanSummon
- {
- [Constructible]
- public SummonedFrostSpider()
- {
- Body = 20;
- BaseSoundID = 0x388;
- }
-
- public SummonedFrostSpider(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a frost spider";
-
- 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();
- }
- }
-
- public class SummonedGreatHart : BaseTalismanSummon
- {
- [Constructible]
- public SummonedGreatHart()
- {
- Body = 0xEA;
- BaseSoundID = 0x82;
- }
+ public TalismanReleaseEntry(Mobile m) : base(6118, 3) => m_Mobile = m;
- public SummonedGreatHart(Serial serial) : base(serial)
+ public override void OnClick()
{
- }
+ Effects.SendLocationParticles(
+ EffectItem.Create(m_Mobile.Location, m_Mobile.Map, EffectItem.DefaultDuration),
+ 0x3728,
+ 8,
+ 20,
+ 5042
+ );
- public override string DefaultName => "a great hart";
-
- 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();
- }
- }
-
- public class SummonedLavaSerpent : BaseTalismanSummon
- {
- [Constructible]
- public SummonedLavaSerpent()
- {
- Body = 90;
- BaseSoundID = 219;
- }
-
- public SummonedLavaSerpent(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a lava serpent";
-
- public override void OnThink()
- {
- /*
- if (m_NextWave < Core.Now)
- AreaHeatDamage();
- */
- }
-
- 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();
- }
-
- /*
- // An area attack that only damages staff, wtf?
-
- private DateTime m_NextWave;
-
- public void AreaHeatDamage()
- {
- Mobile mob = ControlMaster;
-
- if (mob != null)
- {
- if (mob.InRange( Location, 2 ))
- {
- if (mob.AccessLevel != AccessLevel.Player)
- {
- AOS.Damage( mob, Utility.Random( 2, 3 ), 0, 100, 0, 0, 0 );
- mob.SendLocalizedMessage( 1008112 ); // The intense heat is damaging you!
- }
- }
-
- GuardedRegion r = Region as GuardedRegion;
-
- if (r != null && mob.Alive)
- {
- foreach ( Mobile m in GetMobilesInRange( 2 ) )
- {
- if (!mob.CanBeHarmful( m ))
- mob.CriminalAction( false );
- }
- }
- }
-
- m_NextWave = Core.Now + TimeSpan.FromSeconds( 3 );
- }
- */
- }
-
- public class SummonedOrcBrute : BaseTalismanSummon
- {
- [Constructible]
- public SummonedOrcBrute()
- {
- Body = 189;
- BaseSoundID = 0x45A;
- }
-
- public SummonedOrcBrute(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "an orc brute";
-
- 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();
- }
- }
-
- public class SummonedPanther : BaseTalismanSummon
- {
- [Constructible]
- public SummonedPanther()
- {
- Body = 0xD6;
- Hue = 0x901;
- BaseSoundID = 0x462;
- }
-
- public SummonedPanther(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a panther";
-
- 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();
- }
- }
-
- public class SummonedSheep : BaseTalismanSummon
- {
- [Constructible]
- public SummonedSheep()
- {
- Body = 0xCF;
- BaseSoundID = 0xD6;
- }
-
- public SummonedSheep(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a sheep";
-
- 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();
- }
- }
-
- public class SummonedSkeletalKnight : BaseTalismanSummon
- {
- [Constructible]
- public SummonedSkeletalKnight()
- {
- Body = 147;
- BaseSoundID = 451;
- }
-
- public SummonedSkeletalKnight(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a skeletal knight";
-
- 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();
- }
- }
-
- public class SummonedVorpalBunny : BaseTalismanSummon
- {
- [Constructible]
- public SummonedVorpalBunny()
- {
- Body = 205;
- Hue = 0x480;
- BaseSoundID = 0xC9;
-
- Timer.StartTimer(TimeSpan.FromMinutes(30.0), BeginTunnel);
- }
-
- public SummonedVorpalBunny(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a vorpal bunny";
-
- public virtual void BeginTunnel()
- {
- if (Deleted)
- {
- return;
- }
-
- new VorpalBunny.BunnyHole().MoveToWorld(Location, Map);
- Frozen = true;
-
- // * The bunny begins to dig a tunnel back to its underground lair *
- Say(1114450);
- PlaySound(0x247);
-
- Timer.StartTimer(TimeSpan.FromSeconds(5.0), Delete);
- }
-
- 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();
- }
- }
-
- public class SummonedWailingBanshee : BaseTalismanSummon
- {
- [Constructible]
- public SummonedWailingBanshee()
- {
- Body = 310;
- BaseSoundID = 0x482;
- }
-
- public SummonedWailingBanshee(Serial serial) : base(serial)
- {
- }
-
- public override string DefaultName => "a wailing banshee";
-
- public override void Serialize(IGenericWriter writer)
- {
- base.Serialize(writer);
-
- writer.WriteEncodedInt(0); // version
- }
-
- public override void Deserialize(IGenericReader reader)
- {
- base.Deserialize(reader);
+ Effects.PlaySound(m_Mobile,0x201);
- var version = reader.ReadEncodedInt();
+ m_Mobile.Delete();
}
}
}
+
+[SerializationGenerator(0)]
+public partial class SummonedAntLion : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedAntLion()
+ {
+ Body = 787;
+ BaseSoundID = 1006;
+ }
+
+ public override string DefaultName => "an ant lion";
+}
+
+
+[SerializationGenerator(0)]
+public partial class SummonedArcticOgreLord : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedArcticOgreLord()
+ {
+ Body = 135;
+ BaseSoundID = 427;
+ }
+
+ public override string DefaultName => "an arctic ogre lord";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedBakeKitsune : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedBakeKitsune()
+ {
+ Body = 246;
+ BaseSoundID = 0x4DD;
+ }
+
+ public override string DefaultName => "a bake kitsune";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedBogling : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedBogling()
+ {
+ Body = 779;
+ BaseSoundID = 422;
+ }
+
+ public override string DefaultName => "a bogling";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedBullFrog : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedBullFrog()
+ {
+ Body = 81;
+ Hue = Utility.RandomList(0x5AC, 0x5A3, 0x59A, 0x591, 0x588, 0x57F);
+ BaseSoundID = 0x266;
+ }
+
+ public override string DefaultName => "a bull frog";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedChicken : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedChicken()
+ {
+ Body = 0xD0;
+ BaseSoundID = 0x6E;
+ }
+
+ public override string DefaultName => "a chicken";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedCow : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedCow()
+ {
+ Body = Utility.RandomList(0xD8, 0xE7);
+ BaseSoundID = 0x78;
+ }
+
+ public override string DefaultName => "a cow";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedDoppleganger : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedDoppleganger()
+ {
+ Body = 0x309;
+ BaseSoundID = 0x451;
+ }
+
+ public override string DefaultName => "a doppleganger";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedFrostSpider : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedFrostSpider()
+ {
+ Body = 20;
+ BaseSoundID = 0x388;
+ }
+
+ public override string DefaultName => "a frost spider";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedGreatHart : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedGreatHart()
+ {
+ Body = 0xEA;
+ BaseSoundID = 0x82;
+ }
+
+ public override string DefaultName => "a great hart";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedLavaSerpent : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedLavaSerpent()
+ {
+ Body = 90;
+ BaseSoundID = 219;
+ }
+
+ public override string DefaultName => "a lava serpent";
+
+ public override void OnThink()
+ {
+ /*
+ if (m_NextWave < Core.Now)
+ AreaHeatDamage();
+ */
+ }
+
+ /*
+ // An area attack that only damages staff, wtf?
+
+ private DateTime m_NextWave;
+
+ public void AreaHeatDamage()
+ {
+ Mobile mob = ControlMaster;
+
+ if (mob != null)
+ {
+ if (mob.InRange( Location, 2 ))
+ {
+ if (mob.AccessLevel != AccessLevel.Player)
+ {
+ AOS.Damage( mob, Utility.Random( 2, 3 ), 0, 100, 0, 0, 0 );
+ mob.SendLocalizedMessage( 1008112 ); // The intense heat is damaging you!
+ }
+ }
+
+ GuardedRegion r = Region as GuardedRegion;
+
+ if (r != null && mob.Alive)
+ {
+ foreach ( Mobile m in GetMobilesInRange( 2 ) )
+ {
+ if (!mob.CanBeHarmful( m ))
+ mob.CriminalAction( false );
+ }
+ }
+ }
+
+ m_NextWave = Core.Now + TimeSpan.FromSeconds( 3 );
+ }
+ */
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedOrcBrute : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedOrcBrute()
+ {
+ Body = 189;
+ BaseSoundID = 0x45A;
+ }
+
+ public override string DefaultName => "an orc brute";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedPanther : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedPanther()
+ {
+ Body = 0xD6;
+ Hue = 0x901;
+ BaseSoundID = 0x462;
+ }
+
+ public override string DefaultName => "a panther";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedSheep : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedSheep()
+ {
+ Body = 0xCF;
+ BaseSoundID = 0xD6;
+ }
+
+ public override string DefaultName => "a sheep";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedSkeletalKnight : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedSkeletalKnight()
+ {
+ Body = 147;
+ BaseSoundID = 451;
+ }
+
+ public override string DefaultName => "a skeletal knight";
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedVorpalBunny : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedVorpalBunny()
+ {
+ Body = 205;
+ Hue = 0x480;
+ BaseSoundID = 0xC9;
+
+ Timer.StartTimer(TimeSpan.FromMinutes(30.0), BeginTunnel);
+ }
+
+ public override string DefaultName => "a vorpal bunny";
+
+ public virtual void BeginTunnel()
+ {
+ if (Deleted)
+ {
+ return;
+ }
+
+ new VorpalBunny.BunnyHole().MoveToWorld(Location, Map);
+ Frozen = true;
+
+ // * The bunny begins to dig a tunnel back to its underground lair *
+ Say(1114450);
+ PlaySound(0x247);
+
+ Timer.StartTimer(TimeSpan.FromSeconds(5.0), Delete);
+ }
+}
+
+[SerializationGenerator(0)]
+public partial class SummonedWailingBanshee : BaseTalismanSummon
+{
+ [Constructible]
+ public SummonedWailingBanshee()
+ {
+ Body = 310;
+ BaseSoundID = 0x482;
+ }
+
+ public override string DefaultName => "a wailing banshee";
+}
diff --git a/Projects/UOContent/Migrations/Server.Items.BaseTalisman.v1.json b/Projects/UOContent/Migrations/Server.Items.BaseTalisman.v1.json
new file mode 100644
index 000000000..958652db9
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.BaseTalisman.v1.json
@@ -0,0 +1,132 @@
+{
+ "version": 1,
+ "type": "Server.Items.BaseTalisman",
+ "properties": [
+ {
+ "name": "Attributes",
+ "type": "Server.AosAttributes",
+ "usesSaveFlag": true,
+ "rule": "RawSerializableMigrationRule",
+ "ruleArguments": [
+ "DeserializationRequiresParent"
+ ]
+ },
+ {
+ "name": "SkillBonuses",
+ "type": "Server.AosSkillBonuses",
+ "usesSaveFlag": true,
+ "rule": "RawSerializableMigrationRule",
+ "ruleArguments": [
+ "DeserializationRequiresParent"
+ ]
+ },
+ {
+ "name": "Protection",
+ "type": "Server.Items.TalismanAttribute",
+ "usesSaveFlag": true,
+ "rule": "RawSerializableMigrationRule",
+ "ruleArguments": [
+ ""
+ ]
+ },
+ {
+ "name": "Killer",
+ "type": "Server.Items.TalismanAttribute",
+ "usesSaveFlag": true,
+ "rule": "RawSerializableMigrationRule",
+ "ruleArguments": [
+ ""
+ ]
+ },
+ {
+ "name": "Summoner",
+ "type": "Server.Items.TalismanAttribute",
+ "usesSaveFlag": true,
+ "rule": "RawSerializableMigrationRule",
+ "ruleArguments": [
+ ""
+ ]
+ },
+ {
+ "name": "Removal",
+ "type": "Server.Items.TalismanRemoval",
+ "usesSaveFlag": true,
+ "rule": "EnumMigrationRule"
+ },
+ {
+ "name": "Skill",
+ "type": "Server.SkillName",
+ "usesSaveFlag": true,
+ "rule": "EnumMigrationRule"
+ },
+ {
+ "name": "SuccessBonus",
+ "type": "int",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ "EncodedInt"
+ ]
+ },
+ {
+ "name": "ExceptionalBonus",
+ "type": "int",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ "EncodedInt"
+ ]
+ },
+ {
+ "name": "MaxCharges",
+ "type": "int",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ "EncodedInt"
+ ]
+ },
+ {
+ "name": "Charges",
+ "type": "int",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ ""
+ ]
+ },
+ {
+ "name": "MaxChargeTime",
+ "type": "int",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ "EncodedInt"
+ ]
+ },
+ {
+ "name": "ChargeTime",
+ "type": "int",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ "EncodedInt"
+ ]
+ },
+ {
+ "name": "Blessed",
+ "type": "bool",
+ "usesSaveFlag": true,
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ ""
+ ]
+ },
+ {
+ "name": "Slayer",
+ "type": "Server.Items.TalismanSlayerName",
+ "usesSaveFlag": true,
+ "rule": "EnumMigrationRule"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Items.EnchantedSwitch.v0.json b/Projects/UOContent/Migrations/Server.Items.EnchantedSwitch.v0.json
new file mode 100644
index 000000000..e9195676d
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.EnchantedSwitch.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Items.EnchantedSwitch"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Items.HollowPrism.v0.json b/Projects/UOContent/Migrations/Server.Items.HollowPrism.v0.json
new file mode 100644
index 000000000..d9f0dd2ad
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.HollowPrism.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Items.HollowPrism"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Items.JeweledFiligree.v0.json b/Projects/UOContent/Migrations/Server.Items.JeweledFiligree.v0.json
new file mode 100644
index 000000000..1093f0971
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.JeweledFiligree.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Items.JeweledFiligree"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Items.RunedPrism.v0.json b/Projects/UOContent/Migrations/Server.Items.RunedPrism.v0.json
new file mode 100644
index 000000000..cce7ff6a7
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.RunedPrism.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Items.RunedPrism"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Items.RunedSwitch.v0.json b/Projects/UOContent/Migrations/Server.Items.RunedSwitch.v0.json
new file mode 100644
index 000000000..b258cff0f
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.RunedSwitch.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Items.RunedSwitch"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Items.TalismanAttribute.v1.json b/Projects/UOContent/Migrations/Server.Items.TalismanAttribute.v1.json
new file mode 100644
index 000000000..7fda238bd
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Items.TalismanAttribute.v1.json
@@ -0,0 +1,27 @@
+{
+ "version": 1,
+ "type": "Server.Items.TalismanAttribute",
+ "properties": [
+ {
+ "name": "Type",
+ "type": "System.Type",
+ "rule": "PrimitiveTypeMigrationRule"
+ },
+ {
+ "name": "Name",
+ "type": "Server.TextDefinition",
+ "rule": "PrimitiveUOTypeMigrationRule",
+ "ruleArguments": [
+ "TextDefinition"
+ ]
+ },
+ {
+ "name": "Amount",
+ "type": "int",
+ "rule": "PrimitiveTypeMigrationRule",
+ "ruleArguments": [
+ ""
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.BaseTalismanSummon.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.BaseTalismanSummon.v0.json
new file mode 100644
index 000000000..ad0cd092f
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.BaseTalismanSummon.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.BaseTalismanSummon"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedAntLion.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedAntLion.v0.json
new file mode 100644
index 000000000..d66bd920f
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedAntLion.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedAntLion"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedArcticOgreLord.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedArcticOgreLord.v0.json
new file mode 100644
index 000000000..8c890ef68
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedArcticOgreLord.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedArcticOgreLord"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedBakeKitsune.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedBakeKitsune.v0.json
new file mode 100644
index 000000000..136150103
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedBakeKitsune.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedBakeKitsune"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedBogling.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedBogling.v0.json
new file mode 100644
index 000000000..576812fef
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedBogling.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedBogling"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedBullFrog.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedBullFrog.v0.json
new file mode 100644
index 000000000..627ecd768
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedBullFrog.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedBullFrog"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedChicken.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedChicken.v0.json
new file mode 100644
index 000000000..d5f80998f
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedChicken.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedChicken"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedCow.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedCow.v0.json
new file mode 100644
index 000000000..21cb9943e
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedCow.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedCow"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedDoppleganger.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedDoppleganger.v0.json
new file mode 100644
index 000000000..82bd2ab1e
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedDoppleganger.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedDoppleganger"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedFrostSpider.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedFrostSpider.v0.json
new file mode 100644
index 000000000..962965c49
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedFrostSpider.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedFrostSpider"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedGreatHart.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedGreatHart.v0.json
new file mode 100644
index 000000000..e0ad895a7
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedGreatHart.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedGreatHart"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedLavaSerpent.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedLavaSerpent.v0.json
new file mode 100644
index 000000000..40a2faa8d
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedLavaSerpent.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedLavaSerpent"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedOrcBrute.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedOrcBrute.v0.json
new file mode 100644
index 000000000..cbe7f4051
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedOrcBrute.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedOrcBrute"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedPanther.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedPanther.v0.json
new file mode 100644
index 000000000..eef43e5ab
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedPanther.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedPanther"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedSheep.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedSheep.v0.json
new file mode 100644
index 000000000..8dddbbe9f
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedSheep.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedSheep"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedSkeletalKnight.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedSkeletalKnight.v0.json
new file mode 100644
index 000000000..19d4a61df
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedSkeletalKnight.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedSkeletalKnight"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedVorpalBunny.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedVorpalBunny.v0.json
new file mode 100644
index 000000000..c5eb201f7
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedVorpalBunny.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedVorpalBunny"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Migrations/Server.Mobiles.SummonedWailingBanshee.v0.json b/Projects/UOContent/Migrations/Server.Mobiles.SummonedWailingBanshee.v0.json
new file mode 100644
index 000000000..3be95d281
--- /dev/null
+++ b/Projects/UOContent/Migrations/Server.Mobiles.SummonedWailingBanshee.v0.json
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "type": "Server.Mobiles.SummonedWailingBanshee"
+}
\ No newline at end of file
diff --git a/Projects/UOContent/Mobiles/BaseCreature.cs b/Projects/UOContent/Mobiles/BaseCreature.cs
index 18a62c945..ffc515223 100644
--- a/Projects/UOContent/Mobiles/BaseCreature.cs
+++ b/Projects/UOContent/Mobiles/BaseCreature.cs
@@ -3515,11 +3515,21 @@ namespace Server.Mobiles
}
public static bool Summon(BaseCreature creature, Mobile caster, Point3D p, int sound, TimeSpan duration) =>
- Summon(creature, true, caster, p, sound, duration);
+ Summon(creature, true, caster, p, sound, duration, null);
+
+ public static bool Summon(
+ BaseCreature creature, Mobile caster, Point3D p, int sound, TimeSpan duration,
+ Action onUnsummon
+ ) => Summon(creature, true, caster, p, sound, duration, onUnsummon);
public static bool Summon(
BaseCreature creature, bool controlled, Mobile caster, Point3D p, int sound,
TimeSpan duration
+ ) => Summon(creature, controlled, caster, p, sound, duration, null);
+
+ public static bool Summon(
+ BaseCreature creature, bool controlled, Mobile caster, Point3D p, int sound,
+ TimeSpan duration, Action onUnsummon
)
{
if (caster.Followers + creature.ControlSlots > caster.FollowersMax)
@@ -3556,7 +3566,7 @@ namespace Server.Mobiles
}
}
- new UnsummonTimer(creature, duration).Start();
+ new UnsummonTimer(creature, duration, onUnsummon).Start();
creature.SummonEnd = Core.Now + duration;
creature.MoveToWorld(p, caster.Map);
diff --git a/Projects/UOContent/Spells/UnsummonTimer.cs b/Projects/UOContent/Spells/UnsummonTimer.cs
index e34623a9f..18e1c96be 100644
--- a/Projects/UOContent/Spells/UnsummonTimer.cs
+++ b/Projects/UOContent/Spells/UnsummonTimer.cs
@@ -10,6 +10,7 @@ public class UnsummonTimer : Timer
// Track timers since some of them are really long and might hold references to long dead/deleted mobs
private static readonly Dictionary _timers = new();
private BaseCreature _creature;
+ private Action _onUnsummon;
public static void StopTimer(BaseCreature creature)
{
@@ -19,8 +20,9 @@ public class UnsummonTimer : Timer
}
}
- public UnsummonTimer(BaseCreature creature, TimeSpan delay) : base(delay)
+ public UnsummonTimer(BaseCreature creature, TimeSpan delay, Action onUnsummon = null) : base(delay)
{
+ _onUnsummon = onUnsummon;
_creature = creature;
ref var timer = ref CollectionsMarshal.GetValueRefOrAddDefault(_timers, creature, out bool exists);
@@ -36,5 +38,6 @@ public class UnsummonTimer : Timer
{
// BaseCreature.OnAfterDelete will remove the creature from the timers table
_creature?.Delete();
+ _onUnsummon?.Invoke();
}
}
diff --git a/Projects/UOContent/UOContent.csproj b/Projects/UOContent/UOContent.csproj
index dd16d48b3..e664a7d8c 100755
--- a/Projects/UOContent/UOContent.csproj
+++ b/Projects/UOContent/UOContent.csproj
@@ -39,7 +39,7 @@
-
+