ModernUO/Projects/UOContent/Items/Talismans/BaseTalisman.cs
2020-08-01 08:40:06 -07:00

1084 lines
33 KiB
C#

using System;
using Server.Mobiles;
using Server.Spells.Fifth;
using Server.Spells.First;
using Server.Spells.Fourth;
using Server.Spells.Necromancy;
using Server.Spells.Second;
using Server.Targeting;
using Server.Utilities;
namespace Server.Items
{
public enum TalismanRemoval
{
None = 0,
Ward = 390,
Damage = 404,
Curse = 407,
Wildfire = 2843
}
public class BaseTalisman : Item
{
private bool m_Blessed;
private int m_Charges;
private int m_ChargeTime;
private int m_MaxCharges;
private int m_MaxChargeTime;
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
{
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();
}
}
public static void Initialize()
{
CommandSystem.Register("RandomTalisman", AccessLevel.GameMaster, RandomTalisman_OnCommand);
}
[Usage("RandomTalisman <count>")]
[Description("Generates random talismans in your backpack.")]
public static void RandomTalisman_OnCommand(CommandEventArgs e)
{
Mobile m = e.Mobile;
int count = e.GetInt32(0);
for (int i = 0; i < count; i++)
m.AddToBackpack(Loot.RandomTalisman());
}
public override void OnAfterDuped(Item newItem)
{
if (!(newItem is 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();
}
}
InvalidateProperties();
}
public override void OnRemoved(IEntity parent)
{
if (parent is Mobile from)
{
SkillBonuses.Remove();
Attributes.RemoveStatBonuses(from);
if (m_Creature?.Deleted == false)
{
Effects.SendLocationParticles(
EffectItem.Create(m_Creature.Location, m_Creature.Map, EffectItem.DefaultDuration), 0x3728, 8, 20,
5042);
Effects.PlaySound(m_Creature, m_Creature.Map, 0x201);
m_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 (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;
}
Type type = GetSummoner();
if (m_Summoner?.IsEmpty == false)
type = m_Summoner.Type;
if (type != null)
{
object obj;
try
{
obj = ActivatorUtil.CreateInstance(type);
}
catch
{
obj = null;
}
if (obj is Item item)
{
int 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 (int i = 0; i < count; i++)
{
from.PlaceInBackpack(item);
if (i + 1 < count)
item = ActivatorUtil.CreateInstance(type) as Item;
}
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 (obj 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, 1, 10, 0x26B6);
mob.Summoned = false;
mob.ControlOrder = OrderType.Friend;
m_Creature = mob;
}
OnAfterUse(from);
}
if (m_Removal != TalismanRemoval.None)
from.Target = new TalismanTarget(this);
}
public override void AddNameProperty(ObjectPropertyList list)
{
if (ForceShowName)
base.AddNameProperty(list);
else if (m_Summoner?.IsEmpty == false)
list.Add(1072400,
m_Summoner?.Name ?? "Unknown"); // Talisman of ~1_name~ Summoning
else if (m_Removal != TalismanRemoval.None)
list.Add(1072389, $"#{1072000 + (int)m_Removal}"); // Talisman of ~1_name~
else
base.AddNameProperty(list);
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties(list);
if (Blessed)
{
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~
}
if (Parent is Mobile && m_MaxChargeTime > 0)
{
if (m_ChargeTime > 0)
list.Add(1074884, m_ChargeTime.ToString()); // 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, "{0}\t{1}", m_Killer.Name?.ToString() ?? "Unknown",
m_Killer.Amount); // ~1_NAME~ Killer: +~2_val~%
if (m_Protection?.IsEmpty == false && m_Protection.Amount > 0)
list.Add(1072387, "{0}\t{1}", m_Protection.Name?.ToString() ?? "Unknown",
m_Protection.Amount); // ~1_NAME~ Protection: +~2_val~%
if (m_ExceptionalBonus != 0)
list.Add(1072395, "#{0}\t{1}", AosSkillBonuses.GetLabel(m_Skill),
m_ExceptionalBonus); // ~1_NAME~ Exceptional Bonus: ~2_val~%
if (m_SuccessBonus != 0)
list.Add(1072394, "#{0}\t{1}", AosSkillBonuses.GetLabel(m_Skill),
m_SuccessBonus); // ~1_NAME~ Bonus: ~2_val~%
SkillBonuses.GetProperties(list);
int prop;
if ((prop = Attributes.WeaponDamage) != 0)
list.Add(1060401, prop.ToString()); // damage increase ~1_val~%
if ((prop = Attributes.DefendChance) != 0)
list.Add(1060408, prop.ToString()); // defense chance increase ~1_val~%
if ((prop = Attributes.BonusDex) != 0)
list.Add(1060409, prop.ToString()); // dexterity bonus ~1_val~
if ((prop = Attributes.EnhancePotions) != 0)
list.Add(1060411, prop.ToString()); // enhance potions ~1_val~%
if ((prop = Attributes.CastRecovery) != 0)
list.Add(1060412, prop.ToString()); // faster cast recovery ~1_val~
if ((prop = Attributes.CastSpeed) != 0)
list.Add(1060413, prop.ToString()); // faster casting ~1_val~
if ((prop = Attributes.AttackChance) != 0)
list.Add(1060415, prop.ToString()); // hit chance increase ~1_val~%
if ((prop = Attributes.BonusHits) != 0)
list.Add(1060431, prop.ToString()); // hit point increase ~1_val~
if ((prop = Attributes.BonusInt) != 0)
list.Add(1060432, prop.ToString()); // intelligence bonus ~1_val~
if ((prop = Attributes.LowerManaCost) != 0)
list.Add(1060433, prop.ToString()); // lower mana cost ~1_val~%
if ((prop = Attributes.LowerRegCost) != 0)
list.Add(1060434, prop.ToString()); // lower reagent cost ~1_val~%
if ((prop = Attributes.Luck) != 0)
list.Add(1060436, prop.ToString()); // luck ~1_val~
if ((prop = Attributes.BonusMana) != 0)
list.Add(1060439, prop.ToString()); // mana increase ~1_val~
if ((prop = Attributes.RegenMana) != 0)
list.Add(1060440, prop.ToString()); // mana regeneration ~1_val~
if (Attributes.NightSight != 0)
list.Add(1060441); // night sight
if ((prop = Attributes.ReflectPhysical) != 0)
list.Add(1060442, prop.ToString()); // reflect physical damage ~1_val~%
if ((prop = Attributes.RegenStam) != 0)
list.Add(1060443, prop.ToString()); // stamina regeneration ~1_val~
if ((prop = Attributes.RegenHits) != 0)
list.Add(1060444, prop.ToString()); // hit point regeneration ~1_val~
if (Attributes.SpellChanneling != 0)
list.Add(1060482); // spell channeling
if ((prop = Attributes.SpellDamage) != 0)
list.Add(1060483, prop.ToString()); // spell damage increase ~1_val~%
if ((prop = Attributes.BonusStam) != 0)
list.Add(1060484, prop.ToString()); // stamina increase ~1_val~
if ((prop = Attributes.BonusStr) != 0)
list.Add(1060485, prop.ToString()); // strength bonus ~1_val~
if ((prop = Attributes.WeaponSpeed) != 0)
list.Add(1060486, prop.ToString()); // swing speed increase ~1_val~%
if (Core.ML && (prop = Attributes.IncreasedKarmaLoss) != 0)
list.Add(1075210, prop.ToString()); // Increased Karma Loss ~1val~%
if (m_MaxCharges > 0)
list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~
if (m_Slayer != TalismanSlayerName.None)
list.Add(1072503 + (int)m_Slayer);
}
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 override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
SaveFlag 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);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
SaveFlag flags = (SaveFlag)reader.ReadEncodedInt();
Attributes = GetSaveFlag(flags, SaveFlag.Attributes) ? new AosAttributes(this, reader) : new AosAttributes(this);
SkillBonuses = GetSaveFlag(flags, SaveFlag.SkillBonuses)
? new AosSkillBonuses(this, reader)
: new AosSkillBonuses(this);
// Backward compatibility
if (GetSaveFlag(flags, SaveFlag.Owner))
BlessedFor = reader.ReadMobile();
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);
break;
}
}
if (Parent is Mobile m)
{
Attributes.AddStatBonuses(m);
SkillBonuses.AddTo(m);
if (m_ChargeTime > 0)
StartTimer();
}
}
public virtual void OnAfterUse(Mobile m)
{
m_ChargeTime = m_MaxChargeTime;
if (m_Charges > 0 && m_MaxCharges > 0)
m_Charges -= 1;
if (m_ChargeTime > 0)
StartTimer();
InvalidateProperties();
}
public virtual Type GetSummoner() => null;
public virtual void SetSummoner(Type type, TextDefinition name)
{
m_Summoner = new TalismanAttribute(type, name);
}
public virtual void SetProtection(Type type, TextDefinition name, int amount)
{
m_Protection = new TalismanAttribute(type, name, amount);
}
public virtual void SetKiller(Type type, TextDefinition name, int amount)
{
m_Killer = new TalismanAttribute(type, name, amount);
}
[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 Mobile target))
{
from.SendLocalizedMessage(1046439); // That is not a valid target.
return;
}
if (m_Talisman.ChargeTime > 0)
{
from.SendLocalizedMessage(1074882,
m_Talisman.ChargeTime.ToString()); // You must wait ~1_val~ seconds for this to recharge.
return;
}
if (m_Talisman.Charges == 0 && m_Talisman.MaxCharges > 0)
{
from.SendLocalizedMessage(1042544); // This item is out of charges.
return;
}
switch (m_Talisman.Removal)
{
case TalismanRemoval.Curse:
target.PlaySound(0xF6);
target.PlaySound(0x1F7);
target.FixedParticles(0x3709, 1, 30, 9963, 13, 3, EffectLayer.Head);
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);
StatMod mod;
mod = target.GetStatMod("[Magic] Str Offset");
if (mod?.Offset < 0)
target.RemoveStatMod("[Magic] Str Offset");
mod = target.GetStatMod("[Magic] Dex Offset");
if (mod?.Offset < 0)
target.RemoveStatMod("[Magic] Dex Offset");
mod = target.GetStatMod("[Magic] Int Offset");
if (mod?.Offset < 0)
target.RemoveStatMod("[Magic] Int Offset");
target.Paralyzed = false;
EvilOmenSpell.TryEndEffect(target);
StrangleSpell.RemoveCurse(target);
CorpseSkinSpell.RemoveCurse(target);
CurseSpell.RemoveEffect(target);
BuffInfo.RemoveBuff(target, BuffIcon.Clumsy);
BuffInfo.RemoveBuff(target, BuffIcon.FeebleMind);
BuffInfo.RemoveBuff(target, BuffIcon.Weaken);
BuffInfo.RemoveBuff(target, BuffIcon.MassCurse);
target.SendLocalizedMessage(1072408); // Any curses on you have been lifted
if (target != from)
from.SendLocalizedMessage(1072409); // Your targets curses have been lifted
break;
case TalismanRemoval.Damage:
target.PlaySound(0x201);
Effects.SendLocationParticles(
EffectItem.Create(target.Location, target.Map, EffectItem.DefaultDuration), 0x3728, 1, 13,
0x834, 0, 0x13B2, 0);
BleedAttack.EndBleed(target, true);
MortalStrike.EndWound(target);
BuffInfo.RemoveBuff(target, BuffIcon.Bleed);
BuffInfo.RemoveBuff(target, BuffIcon.MortalStrike);
target.SendLocalizedMessage(1072405); // Your lasting damage effects have been removed!
if (target != from)
from.SendLocalizedMessage(1072406); // Your Targets lasting damage effects 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);
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);
}
}
private TalismanSlayerName m_Slayer;
[CommandProperty(AccessLevel.GameMaster)]
public TalismanSlayerName Slayer
{
get => m_Slayer;
set
{
m_Slayer = value;
InvalidateProperties();
}
}
private TalismanAttribute m_Summoner;
private TalismanRemoval m_Removal;
private Mobile m_Creature;
[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();
}
}
private TalismanAttribute m_Protection;
private TalismanAttribute m_Killer;
[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();
}
}
private SkillName m_Skill;
private int m_SuccessBonus;
private int m_ExceptionalBonus;
[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)]
public AosAttributes Attributes { get; private set; }
[CommandProperty(AccessLevel.GameMaster)]
public AosSkillBonuses SkillBonuses { get; private set; }
private Timer m_Timer;
public virtual void StartTimer()
{
if (m_Timer?.Running != true)
m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10), Slice);
}
public virtual void StopTimer()
{
m_Timer?.Stop();
m_Timer = null;
}
public virtual void Slice()
{
if (m_ChargeTime - 10 > 0)
{
m_ChargeTime -= 10;
}
else
{
m_ChargeTime = 0;
StopTimer();
}
InvalidateProperties();
}
private static readonly int[] m_ItemIDs =
{
0x2F58, 0x2F59, 0x2F5A, 0x2F5B
};
public static int GetRandomItemID() => Utility.RandomList(m_ItemIDs);
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
};
public static Type GetRandomSummonType() => m_Summons[Utility.Random(m_Summons.Length)];
public static TalismanAttribute GetRandomSummoner()
{
if (Utility.RandomDouble() >= 0.025)
return new TalismanAttribute();
int 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)
return (TalismanRemoval)Utility.RandomList(390, 404, 407);
return TalismanRemoval.None;
}
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
};
public static TalismanAttribute GetRandomKiller() => GetRandomKiller(true);
public static TalismanAttribute GetRandomKiller(bool includingNone)
{
if (includingNone && Utility.RandomBool())
return new TalismanAttribute();
int 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())
return new TalismanAttribute();
int num = Utility.Random(m_Killers.Length);
return new TalismanAttribute(m_Killers[num], m_KillerLabels[num], Utility.RandomMinMax(5, 60));
}
private static readonly SkillName[] m_Skills =
{
SkillName.Alchemy,
SkillName.Blacksmith,
SkillName.Carpentry,
SkillName.Cartography,
SkillName.Cooking,
SkillName.Fletching,
SkillName.Inscribe,
SkillName.Tailoring,
SkillName.Tinkering
};
public static SkillName GetRandomSkill() => m_Skills[Utility.Random(m_Skills.Length)];
public static int GetRandomExceptional()
{
if (Utility.RandomDouble() < 0.3)
{
double 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)
{
double 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.RandomDouble() < 0.5 ? Utility.RandomMinMax(10, 50) : 0;
}
}