Reorganizes Project (#41)

This commit is contained in:
Kamron Batman 2019-08-02 18:13:40 -07:00 committed by GitHub
parent 08bf44af9a
commit 3614a66aee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3499 changed files with 79 additions and 55 deletions

View file

@ -0,0 +1,28 @@
namespace Server.Items
{
/// <summary>
/// This special move allows the skilled warrior to bypass his target's physical resistance, for one shot only.
/// The Armor Ignore shot does slightly less damage than normal.
/// Against a heavily armored opponent, this ability is a big win, but when used against a very lightly armored foe, it might
/// be better to use a standard strike!
/// </summary>
public class ArmorIgnore : WeaponAbility
{
public override int BaseMana => 30;
public override double DamageScalar => 0.9;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060076); // Your attack penetrates their armor!
defender.SendLocalizedMessage(1060077); // The blow penetrated your armor!
defender.PlaySound(0x56);
defender.FixedParticles(0x3728, 200, 25, 9942, EffectLayer.Waist);
}
}
}

View file

@ -0,0 +1,39 @@
namespace Server.Items
{
/// <summary>
/// Strike your opponent with great force, partially bypassing their armor and inflicting greater damage. Requires either
/// Bushido or Ninjitsu skill
/// </summary>
public class ArmorPierce : WeaponAbility
{
public override int BaseMana => 30;
public override double DamageScalar => 1.5;
public override bool RequiresSE => true;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1063347,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063350); // You pierce your opponent's armor!
defender.SendLocalizedMessage(1063351); // Your attacker pierced your armor!
defender.FixedParticles(0x3728, 1, 26, 0x26D6, 0, 0, EffectLayer.Waist);
}
}
}

View file

@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;
using Server.Mobiles;
using Server.Network;
using Server.Spells;
using Server.Spells.Necromancy;
namespace Server.Items
{
/// <summary>
/// Make your opponent bleed profusely with this wicked use of your weapon.
/// When successful, the target will bleed for several seconds, taking damage as time passes for up to ten seconds.
/// The rate of damage slows down as time passes, and the blood loss can be completely staunched with the use of bandages.
/// </summary>
public class BleedAttack : WeaponAbility
{
private static Dictionary<Mobile, Timer> m_Table = new Dictionary<Mobile, Timer>();
public override int BaseMana => 30;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
// Necromancers under Lich or Wraith Form are immune to Bleed Attacks.
TransformContext context = TransformationSpellHelper.GetContext(defender);
if (context != null && (context.Type == typeof(LichFormSpell) || context.Type == typeof(WraithFormSpell)) ||
defender is BaseCreature creature && creature.BleedImmune)
{
attacker.SendLocalizedMessage(1062052); // Your target is not affected by the bleed attack!
return;
}
attacker.SendLocalizedMessage(1060159); // Your target is bleeding!
defender.SendLocalizedMessage(1060160); // You are bleeding!
if (defender is PlayerMobile)
{
defender.LocalOverheadMessage(MessageType.Regular, 0x21, 1060757); // You are bleeding profusely
defender.NonlocalOverheadMessage(MessageType.Regular, 0x21, 1060758,
defender.Name); // ~1_NAME~ is bleeding profusely
}
defender.PlaySound(0x133);
defender.FixedParticles(0x377A, 244, 25, 9950, 31, 0, EffectLayer.Waist);
BeginBleed(defender, attacker);
}
public static bool IsBleeding(Mobile m)
{
return m_Table.ContainsKey(m);
}
public static void BeginBleed(Mobile m, Mobile from)
{
m_Table.TryGetValue(m, out Timer t);
t?.Stop();
m_Table[m] = t = new InternalTimer(from, m);
t.Start();
}
public static void DoBleed(Mobile m, Mobile from, int level)
{
if (m.Alive)
{
int damage = Utility.RandomMinMax(level, level * 2);
if (!m.Player)
damage *= 2;
m.PlaySound(0x133);
m.Damage(damage, from);
Blood blood = new Blood { ItemID = Utility.Random(0x122A, 5) };
blood.MoveToWorld(m.Location, m.Map);
}
else
{
EndBleed(m, false);
}
}
public static void EndBleed(Mobile m, bool message)
{
if (!m_Table.TryGetValue(m, out Timer t))
return;
t.Stop();
m_Table.Remove(m);
if (message)
m.SendLocalizedMessage(1060167); // The bleeding wounds have healed, you are no longer bleeding!
}
private class InternalTimer : Timer
{
private int m_Count;
private Mobile m_From;
private Mobile m_Mobile;
public InternalTimer(Mobile from, Mobile m) : base(TimeSpan.FromSeconds(2.0), TimeSpan.FromSeconds(2.0))
{
m_From = from;
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
DoBleed(m_Mobile, m_From, 5 - m_Count);
if (++m_Count == 5)
EndBleed(m_Mobile, true);
}
}
}
}

View file

@ -0,0 +1,97 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// Raises your defenses for a short time. Requires Bushido or Ninjitsu skill.
/// </summary>
public class Block : WeaponAbility
{
private static Dictionary<Mobile, BlockInfo> m_Table = new Dictionary<Mobile, BlockInfo>();
public override int BaseMana => 30;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1063347,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063345); // You block an attack!
defender.SendLocalizedMessage(1063346); // Your attack was blocked!
attacker.FixedParticles(0x37C4, 1, 16, 0x251D, 0x39D, 0x3, EffectLayer.RightHand);
int bonus = (int)(10.0 * ((Math.Max(attacker.Skills.Bushido.Value,
attacker.Skills.Ninjitsu.Value) - 50.0) / 70.0 + 5));
BeginBlock(attacker, bonus);
}
public static bool GetBonus(Mobile targ, ref int bonus)
{
if (!m_Table.TryGetValue(targ, out BlockInfo info))
return false;
bonus = info.m_Bonus;
return true;
}
public static void BeginBlock(Mobile m, int bonus)
{
EndBlock(m);
m_Table[m] = new BlockInfo(m, bonus);
}
public static void EndBlock(Mobile m)
{
if (!m_Table.TryGetValue(m, out BlockInfo info))
return;
info.m_Timer?.Stop();
m_Table.Remove(m);
}
private class BlockInfo
{
public int m_Bonus;
public Timer m_Timer;
public BlockInfo(Mobile target, int bonus)
{
m_Bonus = bonus;
m_Timer = new InternalTimer(target);
}
}
private class InternalTimer : Timer
{
private Mobile m_Mobile;
public InternalTimer(Mobile m) : base(TimeSpan.FromSeconds(6.0))
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
EndBlock(m_Mobile);
}
}
}
}

View file

@ -0,0 +1,52 @@
using System;
namespace Server.Items
{
/// <summary>
/// This devastating strike is most effective against those who are in good health and whose reserves of mana are low, or vice
/// versa.
/// </summary>
public class ConcussionBlow : WeaponAbility
{
public override int BaseMana => 25;
public override bool OnBeforeDamage(Mobile attacker, Mobile defender)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return false;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060165); // You have delivered a concussion!
defender.SendLocalizedMessage(1060166); // You feel disoriented!
defender.PlaySound(0x213);
defender.FixedParticles(0x377A, 1, 32, 9949, 1153, 0, EffectLayer.Head);
Effects.SendMovingParticles(
new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 10), defender.Map),
new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 20), defender.Map), 0x36FE, 1, 0,
false, false, 1133, 3, 9501, 1, 0, EffectLayer.Waist, 0x100);
int damage = 10; // Base damage is 10.
if (defender.HitsMax > 0)
{
double hitsPercent = defender.Hits / (double)defender.HitsMax * 100.0;
double manaPercent = 0;
if (defender.ManaMax > 0)
manaPercent = defender.Mana / (double)defender.ManaMax * 100.0;
damage += Math.Min((int)(Math.Abs(hitsPercent - manaPercent) / 4), 20);
}
// Total damage is 10 + (0~20) = 10~30, physical, non-resistable.
defender.Damage(damage, attacker);
return true;
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
/// <summary>
/// Also known as the Haymaker, this attack dramatically increases the damage done by a weapon reaching its mark.
/// </summary>
public class CrushingBlow : WeaponAbility
{
public override int BaseMana => 25;
public override double DamageScalar => 1.5;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060090); // You have delivered a crushing blow!
defender.SendLocalizedMessage(1060091); // You take extra damage from the crushing attack!
defender.PlaySound(0x1E1);
defender.FixedParticles(0, 1, 0, 9946, EffectLayer.Head);
Effects.SendMovingParticles(
new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 50), defender.Map),
new Entity(Serial.Zero, new Point3D(defender.X, defender.Y, defender.Z + 20), defender.Map), 0xFB4, 1, 0,
false, false, 0, 3, 9501, 1, 0, EffectLayer.Head, 0x100);
}
}
}

View file

@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// Raises your physical resistance for a short time while lowering your ability to inflict damage. Requires Bushido or
/// Ninjitsu skill.
/// </summary>
public class DefenseMastery : WeaponAbility
{
private static Dictionary<Mobile, DefenseMasteryInfo> m_Table = new Dictionary<Mobile, DefenseMasteryInfo>();
public override int BaseMana => 30;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1063347,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063353); // You perform a masterful defense!
attacker.FixedParticles(0x375A, 1, 17, 0x7F2, 0x3E8, 0x3, EffectLayer.Waist);
int modifier =
(int)(30.0 *
((Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value) -
50.0) / 70.0));
if (m_Table.TryGetValue(attacker, out DefenseMasteryInfo info))
EndDefense(info);
ResistanceMod mod = new ResistanceMod(ResistanceType.Physical, 50 + modifier);
attacker.AddResistanceMod(mod);
info = new DefenseMasteryInfo(attacker, 80 - modifier, mod);
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(3.0), EndDefense, info);
m_Table[attacker] = info;
attacker.Delta(MobileDelta.WeaponDamage);
}
public static bool GetMalus(Mobile targ, ref int damageMalus)
{
if (!m_Table.TryGetValue(targ, out DefenseMasteryInfo info))
return false;
damageMalus = info.m_DamageMalus;
return true;
}
private static void EndDefense(DefenseMasteryInfo info)
{
if (info.m_Mod != null)
info.m_From.RemoveResistanceMod(info.m_Mod);
info.m_Timer?.Stop();
// No message is sent to the player.
m_Table.Remove(info.m_From);
info.m_From.Delta(MobileDelta.WeaponDamage);
}
private class DefenseMasteryInfo
{
public int m_DamageMalus;
public Mobile m_From;
public ResistanceMod m_Mod;
public Timer m_Timer;
public DefenseMasteryInfo(Mobile from, int damageMalus, ResistanceMod mod)
{
m_From = from;
m_DamageMalus = damageMalus;
m_Mod = mod;
}
}
}
}

View file

@ -0,0 +1,78 @@
using System;
namespace Server.Items
{
/// <summary>
/// This attack allows you to disarm your foe.
/// Now in Age of Shadows, a successful Disarm leaves the victim unable to re-arm another weapon for several seconds.
/// </summary>
public class Disarm : WeaponAbility
{
public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds(5.0);
public override int BaseMana => 20;
// No longer active in pub21:
/*public override bool CheckSkills( Mobile from )
{
if ( !base.CheckSkills( from ) )
return false;
if ( !(from.Weapon is Fists) )
return true;
Skill skill = from.Skills.ArmsLore;
if ( skill?.Base >= 80.0 )
return true;
from.SendLocalizedMessage( 1061812 ); // You lack the required skill in armslore to perform that attack!
return false;
}*/
public override bool RequiresTactics(Mobile from)
{
if (!(from.Weapon is BaseWeapon weapon))
return false;
return weapon.Skill != SkillName.Wrestling;
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
return;
ClearCurrentAbility(attacker);
Item toDisarm = defender.FindItemOnLayer(Layer.OneHanded);
if (toDisarm?.Movable == false)
toDisarm = defender.FindItemOnLayer(Layer.TwoHanded);
Container pack = defender.Backpack;
if (pack == null || toDisarm?.Movable == false)
{
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
}
else if (!Core.ML && toDisarm == null || toDisarm is BaseShield || toDisarm is Spellbook)
{
attacker.SendLocalizedMessage(1060849); // Your target is already unarmed!
}
else if (CheckMana(attacker, true))
{
attacker.SendLocalizedMessage(1060092); // You disarm their weapon!
defender.SendLocalizedMessage(1060093); // Your weapon has been disarmed!
defender.PlaySound(0x3B9);
defender.FixedParticles(0x37BE, 232, 25, 9948, EffectLayer.LeftHand);
pack.DropItem(toDisarm);
BaseWeapon.BlockEquip(defender, BlockEquipDuration);
}
}
}
}

View file

@ -0,0 +1,94 @@
using System;
using Server.Mobiles;
using Server.Spells.Ninjitsu;
namespace Server.Items
{
/// <summary>
/// Perfect for the foot-soldier, the Dismount special attack can unseat a mounted opponent.
/// The fighter using this ability must be on his own two feet and not in the saddle of a steed
/// (with one exception: players may use a lance to dismount other players while mounted).
/// If it works, the target will be knocked off his own mount and will take some extra damage from the fall!
/// </summary>
public class Dismount : WeaponAbility
{
public static readonly TimeSpan RemountDelay = TimeSpan.FromSeconds(10.0);
public override int BaseMana => 20;
public override bool Validate(Mobile from)
{
if (!base.Validate(from))
return false;
if (from.Mounted && !(from.Weapon is Lance))
{
from.SendLocalizedMessage(1061283); // You cannot perform that attack while mounted!
return false;
}
return true;
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
return;
if (defender is ChaosDragoon || defender is ChaosDragoonElite)
return;
if (attacker.Mounted && (!(attacker.Weapon is Lance) || !(defender.Weapon is Lance))
) // TODO: Should there be a message here?
return;
ClearCurrentAbility(attacker);
IMount mount = defender.Mount;
if (mount == null && !AnimalForm.UnderTransformation(defender))
{
attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets
return;
}
if (!CheckMana(attacker, true))
return;
if (Core.ML && attacker is LesserHiryu && 0.8 >= Utility.RandomDouble())
return; //Lesser Hiryu have an 80% chance of missing this attack
attacker.SendLocalizedMessage(1060082); // The force of your attack has dislodged them from their mount!
if (attacker.Mounted)
defender.SendLocalizedMessage(1062315); // You fall off your mount!
else
defender.SendLocalizedMessage(1060083); // You fall off of your mount and take damage!
defender.PlaySound(0x140);
defender.FixedParticles(0x3728, 10, 15, 9955, EffectLayer.Waist);
if (defender is PlayerMobile mobile)
{
if (AnimalForm.UnderTransformation(mobile))
mobile.SendLocalizedMessage(1114066, attacker.Name); // ~1_NAME~ knocked you out of animal form!
else if (mobile.Mounted) mobile.SendLocalizedMessage(1040023); // You have been knocked off of your mount!
mobile.SetMountBlock(BlockMountType.Dazed, TimeSpan.FromSeconds(10), true);
}
else
{
defender.Mount.Rider = null;
}
if (attacker is PlayerMobile playerMobile)
playerMobile.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, true);
else if (Core.ML && attacker is BaseCreature bc)
if (bc.ControlMaster is PlayerMobile pm)
pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false);
if (!attacker.Mounted)
AOS.Damage(defender, attacker, Utility.RandomMinMax(15, 25), 100, 0, 0, 0, 0);
}
}
}

View file

@ -0,0 +1,45 @@
using System;
namespace Server.Items
{
/// <summary>
/// This attack allows you to disrobe your foe.
/// </summary>
public class Disrobe : WeaponAbility
{
public static readonly TimeSpan BlockEquipDuration = TimeSpan.FromSeconds(5.0);
public override int BaseMana => 20; // Not Sure what amount of mana a creature uses.
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
return;
ClearCurrentAbility(attacker);
Item toDisrobe = defender.FindItemOnLayer(Layer.InnerTorso);
if (toDisrobe?.Movable == false)
toDisrobe = defender.FindItemOnLayer(Layer.OuterTorso);
Container pack = defender.Backpack;
if (pack == null || toDisrobe?.Movable == false)
{
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
}
else if (CheckMana(attacker, true))
{
//attacker.SendLocalizedMessage( 1060092 ); // You disarm their weapon!
defender.SendLocalizedMessage(1062002); // You can no longer wear your ~1_ARMOR~
defender.PlaySound(0x3B9);
//defender.FixedParticles( 0x37BE, 232, 25, 9948, EffectLayer.InnerTorso );
pack.DropItem(toDisrobe);
BaseWeapon.BlockEquip(defender, BlockEquipDuration);
}
}
}
}

View file

@ -0,0 +1,60 @@
namespace Server.Items
{
/// <summary>
/// Send two arrows flying at your opponent if you're mounted. Requires Bushido or Ninjitsu skill.
/// </summary>
public class DoubleShot : WeaponAbility
{
public override int BaseMana => 30;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1063347,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
Use(attacker, defender);
}
public override void OnMiss(Mobile attacker, Mobile defender)
{
Use(attacker, defender);
}
public override bool Validate(Mobile from)
{
if (base.Validate(from))
{
if (from.Mounted)
return true;
from.SendLocalizedMessage(1070770); // You can only execute this attack while mounted!
ClearCurrentAbility(from);
}
return false;
}
public void Use(Mobile attacker, Mobile defender)
{
if (!Validate(attacker) || !CheckMana(attacker, true) || attacker.Weapon == null) //sanity
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063348); // You launch two shots at once!
defender.SendLocalizedMessage(1063349); // You're attacked with a barrage of shots!
defender.FixedParticles(0x37B9, 1, 19, 0x251D, EffectLayer.Waist);
attacker.Weapon.OnSwing(attacker, defender);
}
}
}

View file

@ -0,0 +1,46 @@
namespace Server.Items
{
/// <summary>
/// The highly skilled warrior can use this special attack to make two quick swings in succession.
/// Landing both blows would be devastating!
/// </summary>
public class DoubleStrike : WeaponAbility
{
public override int BaseMana => 30;
public override double DamageScalar => 0.9;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060084); // You attack with lightning speed!
defender.SendLocalizedMessage(1060085); // Your attacker strikes with lightning speed!
defender.PlaySound(0x3BB);
defender.FixedEffect(0x37B9, 244, 25);
// Swing again:
// If no combatant, wrong map, one of us is a ghost, or cannot see, or deleted, then stop combat
if (defender.Deleted || attacker.Deleted || defender.Map != attacker.Map ||
!defender.Alive || !attacker.Alive || !attacker.CanSee(defender))
{
attacker.Combatant = null;
return;
}
IWeapon weapon = attacker.Weapon;
if (!(weapon != null && attacker.InRange(defender, weapon.MaxRange) &&attacker.InLOS(defender)))
return;
BaseWeapon.InDoubleStrike = true;
attacker.RevealingAction();
attacker.NextCombatTime = Core.TickCount + (int)weapon.OnSwing(attacker, defender).TotalMilliseconds;
BaseWeapon.InDoubleStrike = false;
}
}
}

View file

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// Attack faster as you swing with both weapons.
/// </summary>
public class DualWield : WeaponAbility
{
public static Dictionary<Mobile, DualWieldTimer> Registry{ get; } = new Dictionary<Mobile, DualWieldTimer>();
public override int BaseMana => 30;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0)
{
from.SendLocalizedMessage(1063352,
"50"); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
if (Registry.TryGetValue(attacker, out DualWieldTimer timer))
{
timer.Stop();
Registry.Remove(attacker);
}
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063362); // You dually wield for increased speed!
attacker.FixedParticles(0x3779, 1, 15, 0x7F6, 0x3E8, 3, EffectLayer.LeftHand);
timer = new DualWieldTimer(attacker,
(int)(20.0 + 3.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 7.0)); //20-50 % increase
timer.Start();
Registry.Add(attacker, timer);
}
public class DualWieldTimer : Timer
{
private Mobile m_Owner;
public DualWieldTimer(Mobile owner, int bonusSwingSpeed)
: base(TimeSpan.FromSeconds(6.0))
{
m_Owner = owner;
BonusSwingSpeed = bonusSwingSpeed;
Priority = TimerPriority.FiftyMS;
}
public int BonusSwingSpeed{ get; }
protected override void OnTick()
{
Registry.Remove(m_Owner);
}
}
}
}

View file

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// Gain a defensive advantage over your primary opponent for a short time.
/// </summary>
public class Feint : WeaponAbility
{
public static Dictionary<Mobile, FeintTimer> Registry{ get; } = new Dictionary<Mobile, FeintTimer>();
public override int BaseMana => 30;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1063347,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
if (Registry.TryGetValue(defender, out FeintTimer timer))
{
timer.Stop();
Registry.Remove(defender);
}
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063360); // You baffle your target with a feint!
defender.SendLocalizedMessage(1063361); // You were deceived by an attacker's feint!
attacker.FixedParticles(0x3728, 1, 13, 0x7F3, 0x962, 0, EffectLayer.Waist);
timer = new FeintTimer(defender,
(int)(20.0 + 3.0 * (Math.Max(attacker.Skills.Ninjitsu.Value,
attacker.Skills.Bushido.Value) - 50.0) / 7.0)); //20-50 % decrease
timer.Start();
Registry.Add(defender, timer);
}
public class FeintTimer : Timer
{
private Mobile m_Defender;
public FeintTimer(Mobile defender, int swingSpeedReduction)
: base(TimeSpan.FromSeconds(6.0))
{
m_Defender = defender;
SwingSpeedReduction = swingSpeedReduction;
Priority = TimerPriority.FiftyMS;
}
public int SwingSpeedReduction{ get; }
protected override void OnTick()
{
Registry.Remove(m_Defender);
}
}
}
}

View file

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Spells;
namespace Server.Items
{
/// <summary>
/// A quick attack to all enemies in range of your weapon that causes damage over time. Requires Bushido or Ninjitsu skill.
/// </summary>
public class FrenziedWhirlwind : WeaponAbility
{
public override int BaseMana => 30;
public static Dictionary<Mobile, FrenziedWirlwindTimer> Registry{ get; } = new Dictionary<Mobile, FrenziedWirlwindTimer>();
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1063347,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker)) //Mana check after check that there are targets
return;
ClearCurrentAbility(attacker);
Map map = attacker.Map;
if (!(map != null && attacker.Weapon is BaseWeapon weapon))
return;
List<Mobile> targets = attacker.GetMobilesInRange(1).Where(m =>
m?.Deleted == false && m != defender && m != attacker && SpellHelper.ValidIndirectTarget(attacker, m) &&
m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) &&
attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m)).ToList();
if (targets.Count == 0 || !CheckMana(attacker, true))
return;
attacker.FixedEffect(0x3728, 10, 15);
attacker.PlaySound(0x2A1);
// 5-15 damage
int amount = (int)(10.0 * ((Math.Max(attacker.Skills.Bushido.Value,
attacker.Skills.Ninjitsu.Value) - 50.0) / 70.0 + 5));
for (int i = 0; i < targets.Count; ++i)
{
Mobile m = targets[i];
attacker.DoHarmful(m, true);
if (Registry.TryGetValue(m, out FrenziedWirlwindTimer timer))
{
timer.Stop();
Registry.Remove(m);
}
timer = new FrenziedWirlwindTimer(attacker, m, amount);
timer.Start();
Registry.Add(m, timer);
}
Timer.DelayCall(TimeSpan.FromSeconds(2.0), RepeatEffect, attacker);
}
private void RepeatEffect(Mobile attacker)
{
attacker.FixedEffect(0x3728, 10, 15);
attacker.PlaySound(0x2A1);
}
public class FrenziedWirlwindTimer : Timer
{
private readonly double DamagePerTick;
private Mobile m_Attacker;
private double m_DamageRemaining;
private double m_DamageToDo;
private Mobile m_Defender;
public FrenziedWirlwindTimer(Mobile attacker, Mobile defender, int totalDamage)
: base(TimeSpan.Zero, TimeSpan.FromSeconds(0.25),
12) // 3 seconds at .25 seconds apart = 12. Confirm delay in between of .25 each.
{
m_Attacker = attacker;
m_Defender = defender;
m_DamageRemaining = totalDamage;
DamagePerTick = (double)totalDamage / 12 + 0.01;
Priority = TimerPriority.TwentyFiveMS;
}
protected override void OnTick()
{
if (!m_Defender.Alive || m_DamageRemaining <= 0)
{
Stop();
Registry.Remove(m_Defender);
return;
}
m_DamageRemaining -= DamagePerTick;
m_DamageToDo += DamagePerTick;
if (m_DamageRemaining <= 0 && m_DamageToDo < 1)
m_DamageToDo = 1.0; //Confirm this 'round up' at the end
int damage = (int)m_DamageToDo;
if (damage > 0)
{
m_Defender.Damage(damage, m_Attacker);
m_DamageToDo -= damage;
}
if (!m_Defender.Alive || m_DamageRemaining <= 0)
{
Stop();
Registry.Remove(m_Defender);
}
}
}
}
}

View file

@ -0,0 +1,78 @@
namespace Server.Items
{
/// <summary>
/// This special move represents a significant change to the use of poisons in Age of Shadows.
/// Now, only certain weapon types <20> those that have Infectious Strike as an available special move <20> will be able to be
/// poisoned.
/// Targets will no longer be poisoned at random when hit by poisoned weapons.
/// Instead, the wielder must use this ability to deliver the venom.
/// While no skill in Poisoning is directly required to use this ability, being knowledgeable in the application and use of
/// toxins
/// will allow a character to use Infectious Strike at reduced mana cost and with a chance to inflict more deadly poison on
/// his victim.
/// With this change, weapons will no longer be corroded by poison.
/// Level 5 poison will be possible when using this special move.
/// </summary>
public class InfectiousStrike : WeaponAbility
{
public override int BaseMana => 15;
public override bool RequiresTactics(Mobile from)
{
return false;
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
return;
ClearCurrentAbility(attacker);
if (!(attacker.Weapon is BaseWeapon weapon))
return;
Poison p = weapon.Poison;
if (p == null || weapon.PoisonCharges <= 0)
{
attacker.SendLocalizedMessage(
1061141); // Your weapon must have a dose of poison to perform an infectious strike!
return;
}
if (!CheckMana(attacker, true))
return;
--weapon.PoisonCharges;
// Infectious strike special move now uses poisoning skill to help determine potency
int maxLevel = attacker.Skills.Poisoning.Fixed / 200;
if (maxLevel < 0) maxLevel = 0;
if (p.Level > maxLevel) p = Poison.GetPoison(maxLevel);
if (attacker.Skills.Poisoning.Value / 100.0 > Utility.RandomDouble())
{
int level = p.Level + 1;
Poison newPoison = Poison.GetPoison(level);
if (newPoison != null)
{
p = newPoison;
attacker.SendLocalizedMessage(1060080); // Your precise strike has increased the level of the poison by 1
defender.SendLocalizedMessage(1060081); // The poison seems extra effective!
}
}
defender.PlaySound(0xDD);
defender.FixedParticles(0x3728, 244, 25, 9941, 1266, 0, EffectLayer.Waist);
if (defender.ApplyPoison(attacker, p) != ApplyPoisonResult.Immune)
{
attacker.SendLocalizedMessage(1008096, true, defender.Name); // You have poisoned your target :
defender.SendLocalizedMessage(1008097, false, attacker.Name); // : poisoned you!
}
}
}
}

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// The assassin's friend.
/// A successful Mortal Strike will render its victim unable to heal any damage for several seconds.
/// Use a gruesome follow-up to finish off your foe.
/// </summary>
public class MortalStrike : WeaponAbility
{
public static readonly TimeSpan PlayerDuration = TimeSpan.FromSeconds(6.0);
public static readonly TimeSpan NPCDuration = TimeSpan.FromSeconds(12.0);
private static Dictionary<Mobile, InternalTimer> m_Table = new Dictionary<Mobile, InternalTimer>();
public override int BaseMana => 30;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true)) return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060086); // You deliver a mortal wound!
defender.SendLocalizedMessage(1060087); // You have been mortally wounded!
defender.PlaySound(0x1E1);
defender.FixedParticles(0x37B9, 244, 25, 9944, 31, 0, EffectLayer.Waist);
// Do not reset timer if one is already in place.
if (!IsWounded(defender))
BeginWound(defender, defender.Player ? PlayerDuration : NPCDuration);
}
public static bool IsWounded(Mobile m)
{
return m_Table.ContainsKey(m);
}
public static void BeginWound(Mobile m, TimeSpan duration)
{
if (m_Table.TryGetValue(m, out InternalTimer timer))
timer?.Stop();
m_Table[m] = timer = new InternalTimer(m, duration);
timer.Start();
m.YellowHealthbar = true;
}
public static void EndWound(Mobile m)
{
if (m_Table.TryGetValue(m, out InternalTimer timer))
{
timer.Stop();
m_Table.Remove(m);
}
m.YellowHealthbar = false;
m.SendLocalizedMessage(1060208); // You are no longer mortally wounded.
}
private class InternalTimer : Timer
{
private Mobile m_Mobile;
public InternalTimer(Mobile m, TimeSpan duration) : base(duration)
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
EndWound(m_Mobile);
}
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
/// <summary>
/// Available on some crossbows, this special move allows archers to fire while on the move.
/// This shot is somewhat less accurate than normal, but the ability to fire while running is a clear advantage.
/// </summary>
public class MovingShot : WeaponAbility
{
public override int BaseMana => 15;
public override int AccuracyBonus => -25;
public override bool ValidatesDuringHit => false;
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
{
return Validate(attacker) && CheckMana(attacker, true);
}
public override void OnMiss(Mobile attacker, Mobile defender)
{
//Validates in OnSwing for accuracy scalar
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060089); // You fail to execute your special move
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
//Validates in OnSwing for accuracy scalar
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060216); // Your shot was successful
}
}
}

View file

@ -0,0 +1,81 @@
using System;
namespace Server.Items
{
/// <summary>
/// Does damage and paralyses your opponent for a short time.
/// </summary>
public class NerveStrike : WeaponAbility
{
public override int BaseMana => 30;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1070768,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
{
if (defender.Paralyzed)
{
attacker.SendLocalizedMessage(1061923); // The target is already frozen.
return false;
}
return true;
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
bool cantpara = Items.ParalyzingBlow.IsImmune(defender);
if (cantpara)
{
attacker.SendLocalizedMessage(1070804); // Your target resists paralysis.
defender.SendLocalizedMessage(1070813); // You resist paralysis.
}
else
{
attacker.SendLocalizedMessage(1063356); // You cripple your target with a nerve strike!
defender.SendLocalizedMessage(1063357); // Your attacker dealt a crippling nerve strike!
}
attacker.PlaySound(0x204);
defender.FixedEffect(0x376A, 9, 32);
defender.FixedParticles(0x37C4, 1, 8, 0x13AF, 0, 0, EffectLayer.Waist);
if (Core.ML)
{
AOS.Damage(defender, attacker,
(int)(15.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + Utility.Random(10)), true, 100,
0, 0, 0, 0); //0-25
if (!cantpara && (150.0 / 7.0 + 4.0 * attacker.Skills.Bushido.Value / 7.0) / 100.0 >
Utility.RandomDouble())
{
defender.Paralyze(TimeSpan.FromSeconds(2.0));
Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration);
}
}
else if (!cantpara)
{
AOS.Damage(defender, attacker, (int)(15.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 10),
true, 100, 0, 0, 0, 0); //10-25
defender.Freeze(TimeSpan.FromSeconds(2.0));
Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration);
}
}
}
}

View file

@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// A successful Paralyzing Blow will leave the target stunned, unable to move, attack, or cast spells, for a few seconds.
/// </summary>
public class ParalyzingBlow : WeaponAbility
{
public static readonly TimeSpan PlayerFreezeDuration = TimeSpan.FromSeconds(3.0);
public static readonly TimeSpan NPCFreezeDuration = TimeSpan.FromSeconds(6.0);
public static readonly TimeSpan FreezeDelayDuration = TimeSpan.FromSeconds(8.0);
private static Dictionary<Mobile, InternalTimer> m_Table = new Dictionary<Mobile, InternalTimer>();
public override int BaseMana => 30;
// No longer active in pub21:
/*public override bool CheckSkills( Mobile from )
{
if ( !base.CheckSkills( from ) )
return false;
if ( !(from.Weapon is Fists) )
return true;
Skill skill = from.Skills.Anatomy;
if ( skill?.Base >= 80.0 )
return true;
from.SendLocalizedMessage( 1061811 ); // You lack the required anatomy skill to perform that attack!
return false;
}*/
public override bool RequiresTactics(Mobile from)
{
return !(from.Weapon is BaseWeapon weapon && weapon.Skill == SkillName.Wrestling);
}
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
{
if (defender.Paralyzed)
{
attacker.SendLocalizedMessage(1061923); // The target is already frozen.
return false;
}
return true;
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
if (IsImmune(defender)) //Intentionally going after Mana consumption
{
attacker.SendLocalizedMessage(1070804); // Your target resists paralysis.
defender.SendLocalizedMessage(1070813); // You resist paralysis.
return;
}
defender.FixedEffect(0x376A, 9, 32);
defender.PlaySound(0x204);
attacker.SendLocalizedMessage(1060163); // You deliver a paralyzing blow!
defender.SendLocalizedMessage(1060164); // The attack has temporarily paralyzed you!
TimeSpan duration = defender.Player ? PlayerFreezeDuration : NPCFreezeDuration;
// Treat it as paralyze not as freeze, effect must be removed when damaged.
defender.Paralyze(duration);
BeginImmunity(defender, duration + FreezeDelayDuration);
}
public static bool IsImmune(Mobile m)
{
return m_Table.ContainsKey(m);
}
public static void BeginImmunity(Mobile m, TimeSpan duration)
{
if (m_Table.TryGetValue(m, out InternalTimer timer))
timer?.Stop();
m_Table[m] = timer = new InternalTimer(m, duration);
timer.Start();
}
public static void EndImmunity(Mobile m)
{
if (m_Table.TryGetValue(m, out InternalTimer timer))
{
timer?.Stop();
m_Table.Remove(m);
}
}
private class InternalTimer : Timer
{
private Mobile m_Mobile;
public InternalTimer(Mobile m, TimeSpan duration) : base(duration)
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
EndImmunity(m_Mobile);
}
}
}
}

View file

@ -0,0 +1,77 @@
using System;
using Server.Mobiles;
namespace Server.Items
{
/// <summary>
/// If you are on foot, dismounts your opponent and damage the ethereal's rider or the
/// living mount(which must be healed before ridden again). If you are mounted, damages
/// and stuns the mounted opponent.
/// </summary>
public class RidingSwipe : WeaponAbility
{
public override int BaseMana => 30;
public override bool RequiresSE => true;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Bushido) < 50.0)
{
from.SendLocalizedMessage(1070768,
"50"); // You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!defender.Mounted)
{
attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets
ClearCurrentAbility(attacker);
return;
}
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
if (!attacker.Mounted)
{
Mobile mount = defender.Mount as Mobile;
BaseMount.Dismount(defender);
if (mount != null) //Ethy mounts don't take damage
{
int amount = 10 + (int)(10.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 5);
AOS.Damage(mount, null, amount, 100, 0, 0, 0,
0); //The mount just takes damage, there's no flagging as if it was attacking the mount directly
//TODO: Mount prevention until mount healed
}
}
else
{
int amount = 10 + (int)(10.0 * (attacker.Skills.Bushido.Value - 50.0) / 70.0 + 5);
AOS.Damage(defender, attacker, amount, 100, 0, 0, 0, 0);
if (Items.ParalyzingBlow.IsImmune(defender)) //Does it still do damage?
{
attacker.SendLocalizedMessage(1070804); // Your target resists paralysis.
defender.SendLocalizedMessage(1070813); // You resist paralysis.
}
else
{
defender.Paralyze(TimeSpan.FromSeconds(3.0));
Items.ParalyzingBlow.BeginImmunity(defender, Items.ParalyzingBlow.FreezeDelayDuration);
}
}
}
}
}

View file

@ -0,0 +1,54 @@
namespace Server.Items
{
/// <summary>
/// This powerful ability requires secondary skills to activate.
/// Successful use of Shadowstrike deals extra damage to the target <20> and renders the attacker invisible!
/// Only those who are adept at the art of stealth will be able to use this ability.
/// </summary>
public class ShadowStrike : WeaponAbility
{
public override int BaseMana => 20;
public override double DamageScalar => 1.25;
public override bool RequiresTactics(Mobile from)
{
return false;
}
public override bool CheckSkills(Mobile from)
{
if (!base.CheckSkills(from))
return false;
Skill skill = from.Skills.Stealth;
if (skill?.Value >= 80.0)
return true;
from.SendLocalizedMessage(1060183); // You lack the required stealth to perform that attack
return false;
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1060078); // You strike and hide in the shadows!
defender.SendLocalizedMessage(1060079); // You are dazed by the attack and your attacker vanishes!
Effects.SendLocationParticles(EffectItem.Create(attacker.Location, attacker.Map, EffectItem.DefaultDuration),
0x376A, 8, 12, 9943);
attacker.PlaySound(0x482);
defender.FixedEffect(0x37BE, 20, 25);
attacker.Combatant = null;
attacker.Warmode = false;
attacker.Hidden = true;
}
}
}

View file

@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
/// <summary>
/// Attack with increased damage with additional damage over time.
/// </summary>
public class TalonStrike : WeaponAbility
{
private static HashSet<Mobile> m_Table = new HashSet<Mobile>();
public override int BaseMana => 30;
public override double DamageScalar => 1.2;
public override bool CheckSkills(Mobile from)
{
if (GetSkill(from, SkillName.Ninjitsu) < 50.0)
{
from.SendLocalizedMessage(1063352,
"50"); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
return false;
}
return base.CheckSkills(from);
}
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (m_Table.Contains(defender) || !Validate(attacker) || !CheckMana(attacker, true))
return;
ClearCurrentAbility(attacker);
attacker.SendLocalizedMessage(1063358); // You deliver a talon strike!
defender.SendLocalizedMessage(1063359); // Your attacker delivers a talon strike!
defender.FixedParticles(0x373A, 1, 17, 0x26BC, 0x662, 0, EffectLayer.Waist);
InternalTimer timer = new InternalTimer(defender,
(int)(10.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 70.0 + 5)); //5 - 15 damage
timer.Start();
m_Table.Add(defender);
}
private class InternalTimer : Timer
{
private readonly double DamagePerTick;
private double m_DamageRemaining;
private double m_DamageToDo;
private Mobile m_Defender;
public InternalTimer(Mobile defender, int totalDamage)
: base(TimeSpan.Zero, TimeSpan.FromSeconds(0.25),
12) // 3 seconds at .25 seconds apart = 12. Confirm delay inbetween of .25 each.
{
m_Defender = defender;
m_DamageRemaining = totalDamage;
Priority = TimerPriority.TwentyFiveMS;
DamagePerTick = (double)totalDamage / 12 + .01;
}
protected override void OnTick()
{
if (!m_Defender.Alive || m_DamageRemaining <= 0)
{
Stop();
m_Table.Remove(m_Defender);
return;
}
m_DamageRemaining -= DamagePerTick;
m_DamageToDo += DamagePerTick;
if (m_DamageRemaining <= 0 && m_DamageToDo < 1)
m_DamageToDo = 1.0; //Confirm this 'round up' at the end
int damage = (int)m_DamageToDo;
if (damage > 0)
{
//m_Defender.Damage( damage, m_Attacker, false );
m_Defender.Hits -= damage; //Don't show damage, don't disrupt
m_DamageToDo -= damage;
}
if (!m_Defender.Alive || m_DamageRemaining <= 0)
{
Stop();
m_Table.Remove(m_Defender);
}
}
}
}
}

View file

@ -0,0 +1,470 @@
using System;
using System.Collections.Generic;
using Server.Engines.ConPVP;
using Server.Mobiles;
using Server.Network;
using Server.Spells;
using Server.Spells.Bushido;
using Server.Spells.Necromancy;
using Server.Spells.Ninjitsu;
namespace Server.Items
{
public abstract class WeaponAbility
{
public static WeaponAbility[] Abilities{ get; } = {
null,
new ArmorIgnore(),
new BleedAttack(),
new ConcussionBlow(),
new CrushingBlow(),
new Disarm(),
new Dismount(),
new DoubleStrike(),
new InfectiousStrike(),
new MortalStrike(),
new MovingShot(),
new ParalyzingBlow(),
new ShadowStrike(),
new WhirlwindAttack(),
new RidingSwipe(),
new FrenziedWhirlwind(),
new Block(),
new DefenseMastery(),
new NerveStrike(),
new TalonStrike(),
new Feint(),
new DualWield(),
new DoubleShot(),
new ArmorPierce(),
null,
null,
null,
null,
null,
null,
new Disrobe()
};
public static readonly WeaponAbility ArmorIgnore = Abilities[1];
public static readonly WeaponAbility BleedAttack = Abilities[2];
public static readonly WeaponAbility ConcussionBlow = Abilities[3];
public static readonly WeaponAbility CrushingBlow = Abilities[4];
public static readonly WeaponAbility Disarm = Abilities[5];
public static readonly WeaponAbility Dismount = Abilities[6];
public static readonly WeaponAbility DoubleStrike = Abilities[7];
public static readonly WeaponAbility InfectiousStrike = Abilities[8];
public static readonly WeaponAbility MortalStrike = Abilities[9];
public static readonly WeaponAbility MovingShot = Abilities[10];
public static readonly WeaponAbility ParalyzingBlow = Abilities[11];
public static readonly WeaponAbility ShadowStrike = Abilities[12];
public static readonly WeaponAbility WhirlwindAttack = Abilities[13];
public static readonly WeaponAbility RidingSwipe = Abilities[14];
public static readonly WeaponAbility FrenziedWhirlwind = Abilities[15];
public static readonly WeaponAbility Block = Abilities[16];
public static readonly WeaponAbility DefenseMastery = Abilities[17];
public static readonly WeaponAbility NerveStrike = Abilities[18];
public static readonly WeaponAbility TalonStrike = Abilities[19];
public static readonly WeaponAbility Feint = Abilities[20];
public static readonly WeaponAbility DualWield = Abilities[21];
public static readonly WeaponAbility DoubleShot = Abilities[22];
public static readonly WeaponAbility ArmorPierce = Abilities[23];
public static readonly WeaponAbility Bladeweave = Abilities[24];
public static readonly WeaponAbility ForceArrow = Abilities[25];
public static readonly WeaponAbility LightningArrow = Abilities[26];
public static readonly WeaponAbility PsychicAttack = Abilities[27];
public static readonly WeaponAbility SerpentArrow = Abilities[28];
public static readonly WeaponAbility ForceOfNature = Abilities[29];
public static readonly WeaponAbility Disrobe = Abilities[30];
private static Dictionary<Mobile, WeaponAbilityContext> m_PlayersTable = new Dictionary<Mobile, WeaponAbilityContext>();
public virtual int BaseMana => 0;
public virtual int AccuracyBonus => 0;
public virtual double DamageScalar => 1.0;
public virtual bool RequiresSE => false;
public static Dictionary<Mobile, WeaponAbility> Table{ get; } = new Dictionary<Mobile, WeaponAbility>();
public virtual bool ValidatesDuringHit => true;
public virtual void OnHit(Mobile attacker, Mobile defender, int damage)
{
}
public virtual void OnMiss(Mobile attacker, Mobile defender)
{
}
public virtual bool OnBeforeSwing(Mobile attacker, Mobile defender)
{
// Here because you must be sure you can use the skill before calling CheckHit if the ability has a HCI bonus for example
return true;
}
public virtual bool OnBeforeDamage(Mobile attacker, Mobile defender)
{
return true;
}
public virtual bool RequiresTactics(Mobile from)
{
return true;
}
public virtual double GetRequiredSkill(Mobile from)
{
if (from.Weapon is BaseWeapon weapon)
{
if (weapon.PrimaryAbility == this)
return 70.0;
if (weapon.SecondaryAbility == this)
return 90.0;
}
return 200.0;
}
public virtual int CalculateMana(Mobile from)
{
int mana = BaseMana;
double skillTotal = GetSkill(from, SkillName.Swords) + GetSkill(from, SkillName.Macing)
+ GetSkill(from, SkillName.Fencing) +
GetSkill(from, SkillName.Archery) +
GetSkill(from, SkillName.Parry)
+ GetSkill(from, SkillName.Lumberjacking) +
GetSkill(from, SkillName.Stealth)
+ GetSkill(from, SkillName.Poisoning) +
GetSkill(from, SkillName.Bushido) +
GetSkill(from, SkillName.Ninjitsu);
if (skillTotal >= 300.0)
mana -= 10;
else if (skillTotal >= 200.0)
mana -= 5;
double scalar = 1.0;
if (!MindRotSpell.GetMindRotScalar(from, ref scalar))
scalar = 1.0;
// Lower Mana Cost = 40%
int lmc = Math.Min(AosAttributes.GetValue(from, AosAttribute.LowerManaCost), 40);
scalar -= (double)lmc / 100;
mana = (int)(mana * scalar);
// Using a special move within 3 seconds of the previous special move costs double mana
if (GetContext(from) != null)
mana *= 2;
return mana;
}
public virtual bool CheckWeaponSkill(Mobile from)
{
if (!(from.Weapon is BaseWeapon weapon))
return false;
Skill skill = from.Skills[weapon.Skill];
double reqSkill = GetRequiredSkill(from);
bool reqTactics = Core.ML && RequiresTactics(from);
if (Core.ML && reqTactics && from.Skills.Tactics.Base < reqSkill)
{
from.SendLocalizedMessage(1079308,
reqSkill.ToString()); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
return false;
}
if (skill?.Base >= reqSkill)
return true;
/* <UBWS> */
if (weapon.WeaponAttributes.UseBestSkill > 0 && (from.Skills.Swords.Base >= reqSkill ||
from.Skills.Macing.Base >= reqSkill ||
from.Skills.Fencing.Base >= reqSkill))
return true;
/* </UBWS> */
if (reqTactics)
from.SendLocalizedMessage(1079308,
reqSkill.ToString()); // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
else
from.SendLocalizedMessage(1060182,
reqSkill.ToString()); // You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
return false;
}
public virtual bool CheckSkills(Mobile from)
{
return CheckWeaponSkill(from);
}
public virtual double GetSkill(Mobile from, SkillName skillName) => from.Skills[skillName]?.Value ?? 0.0;
public virtual bool CheckMana(Mobile from, bool consume)
{
int mana = CalculateMana(from);
if (from.Mana < mana)
{
if (from is BaseCreature creature && creature.HasManaOveride) return true;
from.SendLocalizedMessage(1060181,
mana.ToString()); // You need ~1_MANA_REQUIREMENT~ mana to perform that attack
return false;
}
if (consume)
{
if (GetContext(from) == null)
{
Timer timer = new WeaponAbilityTimer(from);
timer.Start();
AddContext(from, new WeaponAbilityContext(timer));
}
from.Mana -= mana;
}
return true;
}
public virtual bool Validate(Mobile from)
{
if (!from.Player)
return true;
NetState state = from.NetState;
if (state == null)
return false;
if (RequiresSE && !state.SupportsExpansion(Expansion.SE))
{
from.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability.
return false;
}
if (HonorableExecution.IsUnderPenalty(from) || AnimalForm.UnderTransformation(from))
{
from.SendLocalizedMessage(1063024); // You cannot perform this special move right now.
return false;
}
if (Core.ML && from.Spell != null)
{
from.SendLocalizedMessage(1063024); // You cannot perform this special move right now.
return false;
}
#region Dueling
string option = null;
if (this is ArmorIgnore)
option = "Armor Ignore";
else if (this is BleedAttack)
option = "Bleed Attack";
else if (this is ConcussionBlow)
option = "Concussion Blow";
else if (this is CrushingBlow)
option = "Crushing Blow";
else if (this is Disarm)
option = "Disarm";
else if (this is Dismount)
option = "Dismount";
else if (this is DoubleStrike)
option = "Double Strike";
else if (this is InfectiousStrike)
option = "Infectious Strike";
else if (this is MortalStrike)
option = "Mortal Strike";
else if (this is MovingShot)
option = "Moving Shot";
else if (this is ParalyzingBlow)
option = "Paralyzing Blow";
else if (this is ShadowStrike)
option = "Shadow Strike";
else if (this is WhirlwindAttack)
option = "Whirlwind Attack";
else if (this is RidingSwipe)
option = "Riding Swipe";
else if (this is FrenziedWhirlwind)
option = "Frenzied Whirlwind";
else if (this is Block)
option = "Block";
else if (this is DefenseMastery)
option = "Defense Mastery";
else if (this is NerveStrike)
option = "Nerve Strike";
else if (this is TalonStrike)
option = "Talon Strike";
else if (this is Feint)
option = "Feint";
else if (this is DualWield)
option = "Dual Wield";
else if (this is DoubleShot)
option = "Double Shot";
else if (this is ArmorPierce)
option = "Armor Pierce";
if (option != null && !DuelContext.AllowSpecialAbility(from, option, true))
return false;
#endregion
return CheckSkills(from) && CheckMana(from, false);
}
public static bool IsWeaponAbility(Mobile m, WeaponAbility a)
{
return a == null || !m.Player || m.Weapon is BaseWeapon weapon &&
(weapon.PrimaryAbility == a || weapon.SecondaryAbility == a);
}
public static WeaponAbility GetCurrentAbility(Mobile m)
{
if (!Core.AOS)
{
ClearCurrentAbility(m);
return null;
}
Table.TryGetValue(m, out WeaponAbility a);
if (!IsWeaponAbility(m, a))
{
ClearCurrentAbility(m);
return null;
}
if (a?.ValidatesDuringHit == true && !a.Validate(m))
{
ClearCurrentAbility(m);
return null;
}
return a;
}
public static bool SetCurrentAbility(Mobile m, WeaponAbility a)
{
if (!Core.AOS)
{
ClearCurrentAbility(m);
return false;
}
if (!IsWeaponAbility(m, a))
{
ClearCurrentAbility(m);
return false;
}
if (a?.Validate(m) == false)
{
ClearCurrentAbility(m);
return false;
}
if (a == null)
{
Table.Remove(m);
}
else
{
SpecialMove.ClearCurrentMove(m);
Table[m] = a;
}
return true;
}
public static void ClearCurrentAbility(Mobile m)
{
Table.Remove(m);
if (Core.AOS && m.NetState != null)
m.Send(ClearWeaponAbility.Instance);
}
public static void Initialize()
{
EventSink.SetAbility += EventSink_SetAbility;
}
private static void EventSink_SetAbility(SetAbilityEventArgs e)
{
int index = e.Index;
if (index == 0)
ClearCurrentAbility(e.Mobile);
else if (index >= 1 && index < Abilities.Length)
SetCurrentAbility(e.Mobile, Abilities[index]);
}
private static void AddContext(Mobile m, WeaponAbilityContext context)
{
m_PlayersTable[m] = context;
}
private static void RemoveContext(Mobile m)
{
WeaponAbilityContext context = GetContext(m);
if (context != null)
RemoveContext(m, context);
}
private static void RemoveContext(Mobile m, WeaponAbilityContext context)
{
m_PlayersTable.Remove(m);
context.Timer.Stop();
}
private static WeaponAbilityContext GetContext(Mobile m)
{
m_PlayersTable.TryGetValue(m, out WeaponAbilityContext context);
return context;
}
private class WeaponAbilityTimer : Timer
{
private Mobile m_Mobile;
public WeaponAbilityTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0))
{
m_Mobile = from;
Priority = TimerPriority.TwentyFiveMS;
}
protected override void OnTick()
{
RemoveContext(m_Mobile);
}
}
private class WeaponAbilityContext
{
public WeaponAbilityContext(Timer timer)
{
Timer = timer;
}
public Timer Timer{ get; }
}
}
}

View file

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Server.Spells;
namespace Server.Items
{
/// <summary>
/// A godsend to a warrior surrounded, the Whirlwind Attack allows the fighter to strike at all nearby targets in one mighty
/// spinning swing.
/// </summary>
public class WhirlwindAttack : WeaponAbility
{
public override int BaseMana => 15;
public override void OnHit(Mobile attacker, Mobile defender, int damage)
{
if (!Validate(attacker))
return;
ClearCurrentAbility(attacker);
Map map = attacker.Map;
if (map == null)
return;
if (!(attacker.Weapon is BaseWeapon weapon))
return;
if (!CheckMana(attacker, true))
return;
attacker.FixedEffect(0x3728, 10, 15);
attacker.PlaySound(0x2A1);
List<Mobile> targets = attacker.GetMobilesInRange(1).Where(m =>
m?.Deleted == false && m != defender && m != attacker && SpellHelper.ValidIndirectTarget(attacker, m) &&
m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) &&
attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m)).ToList();
if (targets.Count <= 0)
return;
double bushido = attacker.Skills.Bushido.Value;
double damageBonus = 1.0 + Math.Pow(targets.Count * bushido / 60, 2) / 100;
if (damageBonus > 2.0)
damageBonus = 2.0;
attacker.RevealingAction();
for (int i = 0; i < targets.Count; ++i)
{
Mobile m = targets[i];
attacker.SendLocalizedMessage(1060161); // The whirling attack strikes a target!
m.SendLocalizedMessage(1060162); // You are struck by the whirling attack and take damage!
weapon.OnHit(attacker, m, damageBonus);
}
}
}
}

View file

@ -0,0 +1,39 @@
namespace Server.Items
{
public class AxeOfTheHeavens : DoubleAxe
{
[Constructible]
public AxeOfTheHeavens()
{
Hue = 0x4D5;
WeaponAttributes.HitLightning = 50;
Attributes.AttackChance = 15;
Attributes.DefendChance = 15;
Attributes.WeaponDamage = 50;
}
public AxeOfTheHeavens(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061106; // Axe of the Heavens
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,42 @@
namespace Server.Items
{
public class BladeOfInsanity : Katana
{
[Constructible]
public BladeOfInsanity()
{
Hue = 0x76D;
WeaponAttributes.HitLeechStam = 100;
Attributes.RegenStam = 2;
Attributes.WeaponSpeed = 30;
Attributes.WeaponDamage = 50;
}
public BladeOfInsanity(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061088; // Blade of Insanity
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Hue == 0x44F)
Hue = 0x76D;
}
}
}

View file

@ -0,0 +1,44 @@
namespace Server.Items
{
public class BladeOfTheRighteous : Longsword
{
[Constructible]
public BladeOfTheRighteous()
{
Hue = 0x47E;
//Slayer = SlayerName.DaemonDismissal;
Slayer = SlayerName.Exorcism;
WeaponAttributes.HitLeechHits = 50;
WeaponAttributes.UseBestSkill = 1;
Attributes.BonusHits = 10;
Attributes.WeaponDamage = 50;
}
public BladeOfTheRighteous(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061107; // Blade of the Righteous
public override int ArtifactRarity => 10;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Slayer == SlayerName.None)
Slayer = SlayerName.Exorcism;
}
}
}

View file

@ -0,0 +1,45 @@
namespace Server.Items
{
public class BoneCrusher : WarMace
{
[Constructible]
public BoneCrusher()
{
ItemID = 0x1406;
Hue = 0x60C;
WeaponAttributes.HitLowerDefend = 50;
Attributes.BonusStr = 10;
Attributes.WeaponDamage = 75;
}
public BoneCrusher(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061596; // Bone Crusher
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Hue == 0x604)
Hue = 0x60C;
if (ItemID == 0x1407)
ItemID = 0x1406;
}
}
}

View file

@ -0,0 +1,39 @@
namespace Server.Items
{
public class BreathOfTheDead : BoneHarvester
{
[Constructible]
public BreathOfTheDead()
{
Hue = 0x455;
WeaponAttributes.HitLeechHits = 100;
WeaponAttributes.HitHarm = 25;
Attributes.SpellDamage = 5;
Attributes.WeaponDamage = 50;
}
public BreathOfTheDead(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061109; // Breath of the Dead
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,45 @@
namespace Server.Items
{
public class Frostbringer : Bow
{
[Constructible]
public Frostbringer()
{
Hue = 0x4F2;
WeaponAttributes.HitDispel = 50;
Attributes.RegenStam = 10;
Attributes.WeaponDamage = 50;
}
public Frostbringer(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061111; // Frostbringer
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = pois = nrgy = chaos = direct = 0;
cold = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,45 @@
namespace Server.Items
{
public class LegacyOfTheDreadLord : Bardiche
{
[Constructible]
public LegacyOfTheDreadLord()
{
Hue = 0x676;
Attributes.SpellChanneling = 1;
Attributes.CastRecovery = 3;
Attributes.WeaponSpeed = 30;
Attributes.WeaponDamage = 50;
}
public LegacyOfTheDreadLord(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1060860; // Legacy of the Dread Lord
public override int ArtifactRarity => 10;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Attributes.CastSpeed == 3)
Attributes.CastRecovery = 3;
if (Hue == 0x4B9)
Hue = 0x676;
}
}
}

View file

@ -0,0 +1,51 @@
namespace Server.Items
{
public class SerpentsFang : Kryss
{
[Constructible]
public SerpentsFang()
{
ItemID = 0x1400;
Hue = 0x488;
WeaponAttributes.HitPoisonArea = 100;
WeaponAttributes.ResistPoisonBonus = 20;
Attributes.AttackChance = 15;
Attributes.WeaponDamage = 50;
}
public SerpentsFang(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061601; // Serpent's Fang
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
fire = cold = nrgy = chaos = direct = 0;
phys = 25;
pois = 75;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (ItemID == 0x1401)
ItemID = 0x1400;
}
}
}

View file

@ -0,0 +1,52 @@
namespace Server.Items
{
public class StaffOfTheMagi : BlackStaff
{
[Constructible]
public StaffOfTheMagi()
{
Hue = 0x481;
WeaponAttributes.MageWeapon = 30;
Attributes.SpellChanneling = 1;
Attributes.CastSpeed = 1;
Attributes.WeaponDamage = 50;
}
public StaffOfTheMagi(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061600; // Staff of the Magi
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = cold = pois = chaos = direct = 0;
nrgy = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (WeaponAttributes.MageWeapon == 0)
WeaponAttributes.MageWeapon = 30;
if (ItemID == 0xDF1)
ItemID = 0xDF0;
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
public class TheBeserkersMaul : Maul
{
[Constructible]
public TheBeserkersMaul()
{
Hue = 0x21;
Attributes.WeaponSpeed = 75;
Attributes.WeaponDamage = 50;
}
public TheBeserkersMaul(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061108; // The Berserker's Maul
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
public class TheDragonSlayer : Lance
{
[Constructible]
public TheDragonSlayer()
{
Hue = 0x530;
Slayer = SlayerName.DragonSlaying;
Attributes.Luck = 110;
Attributes.WeaponDamage = 50;
WeaponAttributes.ResistFireBonus = 20;
WeaponAttributes.UseBestSkill = 1;
}
public TheDragonSlayer(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061248; // The Dragon Slayer
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = cold = pois = chaos = direct = 0;
nrgy = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Slayer == SlayerName.None)
Slayer = SlayerName.DragonSlaying;
}
}
}

View file

@ -0,0 +1,56 @@
namespace Server.Items
{
public class TheDryadBow : Bow
{
private static SkillName[] m_PossibleBonusSkills =
{
SkillName.Archery,
SkillName.Healing,
SkillName.MagicResist,
SkillName.Peacemaking,
SkillName.Chivalry,
SkillName.Ninjitsu
};
[Constructible]
public TheDryadBow()
{
ItemID = 0x13B1;
Hue = 0x48F;
SkillBonuses.SetValues(0, m_PossibleBonusSkills[Utility.Random(m_PossibleBonusSkills.Length)],
Utility.Random(4) == 0 ? 10.0 : 5.0);
WeaponAttributes.SelfRepair = 5;
Attributes.WeaponSpeed = 50;
Attributes.WeaponDamage = 35;
WeaponAttributes.ResistPoisonBonus = 15;
}
public TheDryadBow(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061090; // The Dryad Bow
public override int ArtifactRarity => 11;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(1);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (version < 1)
SkillBonuses.SetValues(0, m_PossibleBonusSkills[Utility.Random(m_PossibleBonusSkills.Length)],
Utility.Random(4) == 0 ? 10.0 : 5.0);
}
}
}

View file

@ -0,0 +1,46 @@
namespace Server.Items
{
public class TheTaskmaster : WarFork
{
[Constructible]
public TheTaskmaster()
{
Hue = 0x4F8;
WeaponAttributes.HitPoisonArea = 100;
Attributes.BonusDex = 5;
Attributes.AttackChance = 15;
Attributes.WeaponDamage = 50;
}
public TheTaskmaster(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061110; // The Taskmaster
public override int ArtifactRarity => 10;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = cold = nrgy = chaos = direct = 0;
pois = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,39 @@
namespace Server.Items
{
public class TitansHammer : WarHammer
{
[Constructible]
public TitansHammer()
{
Hue = 0x482;
WeaponAttributes.HitEnergyArea = 100;
Attributes.BonusStr = 15;
Attributes.AttackChance = 15;
Attributes.WeaponDamage = 50;
}
public TitansHammer(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1060024; // Titan's Hammer
public override int ArtifactRarity => 10;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,49 @@
namespace Server.Items
{
public class ZyronicClaw : ExecutionersAxe
{
[Constructible]
public ZyronicClaw()
{
Hue = 0x485;
Slayer = SlayerName.ElementalBan;
WeaponAttributes.HitLeechMana = 50;
Attributes.AttackChance = 30;
Attributes.WeaponDamage = 50;
}
public ZyronicClaw(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1061593; // Zyronic Claw
public override int ArtifactRarity => 10;
public override int InitMinHits => 255;
public override int InitMaxHits => 255;
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
chaos = direct = 0;
phys = fire = cold = pois = nrgy = 20;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Slayer == SlayerName.None)
Slayer = SlayerName.ElementalBan;
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0xF49, 0xF4a)]
public class Axe : BaseAxe
{
[Constructible]
public Axe() : base(0xF49)
{
Weight = 4.0;
}
public Axe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 16;
public override int AosSpeed => 37;
public override float MlSpeed => 3.00f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 6;
public override int OldMaxDamage => 33;
public override int OldSpeed => 37;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using Server.ContextMenus;
using Server.Engines.ConPVP;
using Server.Engines.Harvest;
using Server.Network;
namespace Server.Items
{
public interface IAxe
{
bool Axe(Mobile from, BaseAxe axe);
}
public abstract class BaseAxe : BaseMeleeWeapon
{
private bool m_ShowUsesRemaining;
private int m_UsesRemaining;
public BaseAxe(int itemID) : base(itemID)
{
m_UsesRemaining = 150;
}
public BaseAxe(Serial serial) : base(serial)
{
}
public override int DefHitSound => 0x232;
public override int DefMissSound => 0x23A;
public override SkillName DefSkill => SkillName.Swords;
public override WeaponType DefType => WeaponType.Axe;
public override WeaponAnimation DefAnimation => WeaponAnimation.Slash2H;
public virtual HarvestSystem HarvestSystem => Lumberjacking.System;
[CommandProperty(AccessLevel.GameMaster)]
public int UsesRemaining
{
get => m_UsesRemaining;
set
{
m_UsesRemaining = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.GameMaster)]
public bool ShowUsesRemaining
{
get => m_ShowUsesRemaining;
set
{
m_ShowUsesRemaining = value;
InvalidateProperties();
}
}
public virtual int GetUsesScalar()
{
if (Quality == WeaponQuality.Exceptional)
return 200;
return 100;
}
public override void UnscaleDurability()
{
base.UnscaleDurability();
int scale = GetUsesScalar();
m_UsesRemaining = (m_UsesRemaining * 100 + (scale - 1)) / scale;
InvalidateProperties();
}
public override void ScaleDurability()
{
base.ScaleDurability();
int scale = GetUsesScalar();
m_UsesRemaining = (m_UsesRemaining * scale + 99) / 100;
InvalidateProperties();
}
public override void OnDoubleClick(Mobile from)
{
if (HarvestSystem == null || Deleted)
return;
Point3D loc = GetWorldLocation();
if (!from.InLOS(loc) || !from.InRange(loc, 2))
{
from.LocalOverheadMessage(MessageType.Regular, 0x3E9, 1019045); // I can't reach that
return;
}
if (!IsAccessibleTo(from))
{
PublicOverheadMessage(MessageType.Regular, 0x3E9, 1061637); // You are not allowed to access this.
return;
}
if (!(HarvestSystem is Mining))
from.SendLocalizedMessage(1010018); // What do you want to use this item on?
HarvestSystem.BeginHarvesting(from, this);
}
public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
{
base.GetContextMenuEntries(from, list);
if (HarvestSystem != null)
BaseHarvestTool.AddContextMenuEntries(from, this, list, HarvestSystem);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(2); // version
writer.Write(m_ShowUsesRemaining);
writer.Write(m_UsesRemaining);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 2:
{
m_ShowUsesRemaining = reader.ReadBool();
goto case 1;
}
case 1:
{
m_UsesRemaining = reader.ReadInt();
goto case 0;
}
case 0:
{
if (m_UsesRemaining < 1)
m_UsesRemaining = 150;
break;
}
}
}
public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1)
{
base.OnHit(attacker, defender, damageBonus);
if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded &&
attacker.Skills.Anatomy.Value >= 80 &&
attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() &&
DuelContext.AllowSpecialAbility(attacker, "Concussion Blow", false))
{
StatMod mod = defender.GetStatMod("Concussion");
if (mod == null)
{
defender.SendMessage("You receive a concussion blow!");
defender.AddStatMod(new StatMod(StatType.Int, "Concussion", -(defender.RawInt / 2),
TimeSpan.FromSeconds(30.0)));
attacker.SendMessage("You deliver a concussion blow!");
attacker.PlaySound(0x308);
}
}
}
}
}

View file

@ -0,0 +1,48 @@
namespace Server.Items
{
[Flippable(0xF47, 0xF48)]
public class BattleAxe : BaseAxe
{
[Constructible]
public BattleAxe() : base(0xF47)
{
Weight = 4.0;
Layer = Layer.TwoHanded;
}
public BattleAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 15;
public override int AosMaxDamage => 17;
public override int AosSpeed => 31;
public override float MlSpeed => 3.50f;
public override int OldStrengthReq => 40;
public override int OldMinDamage => 6;
public override int OldMaxDamage => 38;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0xf4b, 0xf4c)]
public class DoubleAxe : BaseAxe
{
[Constructible]
public DoubleAxe() : base(0xF4B)
{
Weight = 8.0;
}
public DoubleAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.WhirlwindAttack;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 15;
public override int AosMaxDamage => 17;
public override int AosSpeed => 33;
public override float MlSpeed => 3.25f;
public override int OldStrengthReq => 45;
public override int OldMinDamage => 5;
public override int OldMaxDamage => 35;
public override int OldSpeed => 37;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0xf45, 0xf46)]
public class ExecutionersAxe : BaseAxe
{
[Constructible]
public ExecutionersAxe() : base(0xF45)
{
Weight = 8.0;
}
public ExecutionersAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
public override int AosStrengthReq => 40;
public override int AosMinDamage => 15;
public override int AosMaxDamage => 17;
public override int AosSpeed => 33;
public override float MlSpeed => 3.25f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 6;
public override int OldMaxDamage => 33;
public override int OldSpeed => 37;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,32 @@
namespace Server.Items
{
public class GuardianAxe : OrnateAxe
{
[Constructible]
public GuardianAxe()
{
Attributes.BonusHits = 4;
Attributes.RegenHits = 1;
}
public GuardianAxe(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073545; // guardian axe
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0xF43, 0xF44)]
public class Hatchet : BaseAxe
{
[Constructible]
public Hatchet() : base(0xF43)
{
Weight = 4.0;
}
public Hatchet(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 20;
public override int AosMinDamage => 13;
public override int AosMaxDamage => 15;
public override int AosSpeed => 41;
public override float MlSpeed => 2.75f;
public override int OldStrengthReq => 15;
public override int OldMinDamage => 2;
public override int OldMaxDamage => 17;
public override int OldSpeed => 40;
public override int InitMinHits => 31;
public override int InitMaxHits => 80;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class HeavyOrnateAxe : OrnateAxe
{
[Constructible]
public HeavyOrnateAxe()
{
Attributes.WeaponDamage = 8;
}
public HeavyOrnateAxe(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073548; // heavy ornate axe
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x13FB, 0x13FA)]
public class LargeBattleAxe : BaseAxe
{
[Constructible]
public LargeBattleAxe() : base(0x13FB)
{
Weight = 6.0;
}
public LargeBattleAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack;
public override int AosStrengthReq => 80;
public override int AosMinDamage => 16;
public override int AosMaxDamage => 17;
public override int AosSpeed => 29;
public override float MlSpeed => 3.75f;
public override int OldStrengthReq => 40;
public override int OldMinDamage => 6;
public override int OldMaxDamage => 38;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,56 @@
using Server.Engines.Harvest;
namespace Server.Items
{
[Flippable(0xE86, 0xE85)]
public class Pickaxe : BaseAxe, IUsesRemaining
{
[Constructible]
public Pickaxe() : base(0xE86)
{
Weight = 11.0;
UsesRemaining = 50;
ShowUsesRemaining = true;
}
public Pickaxe(Serial serial) : base(serial)
{
}
public override HarvestSystem HarvestSystem => Mining.System;
public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 50;
public override int AosMinDamage => 13;
public override int AosMaxDamage => 15;
public override int AosSpeed => 35;
public override float MlSpeed => 3.00f;
public override int OldStrengthReq => 25;
public override int OldMinDamage => 1;
public override int OldMaxDamage => 15;
public override int OldSpeed => 35;
public override int InitMinHits => 31;
public override int InitMaxHits => 60;
public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
ShowUsesRemaining = true;
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class SingingAxe : OrnateAxe
{
[Constructible]
public SingingAxe()
{
SkillBonuses.SetValues(0, SkillName.Musicianship, 5);
}
public SingingAxe(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073546; // singing axe
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class ThunderingAxe : OrnateAxe
{
[Constructible]
public ThunderingAxe()
{
WeaponAttributes.HitLightning = 10;
}
public ThunderingAxe(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073547; // thundering axe
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x1443, 0x1442)]
public class TwoHandedAxe : BaseAxe
{
[Constructible]
public TwoHandedAxe() : base(0x1443)
{
Weight = 8.0;
}
public TwoHandedAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.DoubleStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike;
public override int AosStrengthReq => 40;
public override int AosMinDamage => 16;
public override int AosMaxDamage => 17;
public override int AosSpeed => 31;
public override float MlSpeed => 3.50f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 5;
public override int OldMaxDamage => 39;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 90;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,58 @@
using Server.Engines.Harvest;
namespace Server.Items
{
[Flippable(0x13B0, 0x13AF)]
public class WarAxe : BaseAxe
{
[Constructible]
public WarAxe() : base(0x13B0)
{
Weight = 8.0;
}
public WarAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore;
public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 15;
public override int AosSpeed => 33;
public override float MlSpeed => 3.25f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 9;
public override int OldMaxDamage => 27;
public override int OldSpeed => 40;
public override int DefHitSound => 0x233;
public override int DefMissSound => 0x239;
public override int InitMinHits => 31;
public override int InitMaxHits => 80;
public override SkillName DefSkill => SkillName.Macing;
public override WeaponType DefType => WeaponType.Bashing;
public override WeaponAnimation DefAnimation => WeaponAnimation.Bash1H;
public override HarvestSystem HarvestSystem => null;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,64 @@
using Server.Spells.Spellweaving;
namespace Server.Items
{
public abstract class BaseMeleeWeapon : BaseWeapon
{
public BaseMeleeWeapon(int itemID) : base(itemID)
{
}
public BaseMeleeWeapon(Serial serial) : base(serial)
{
}
public override int AbsorbDamage(Mobile attacker, Mobile defender, int damage)
{
damage = base.AbsorbDamage(attacker, defender, damage);
AttuneWeaponSpell.TryAbsorb(defender, ref damage);
if (Core.AOS)
return damage;
int absorb = defender.MeleeDamageAbsorb;
if (absorb > 0)
{
if (absorb > damage)
{
int react = damage / 5;
if (react <= 0)
react = 1;
defender.MeleeDamageAbsorb -= damage;
damage = 0;
attacker.Damage(react, defender);
attacker.PlaySound(0x1F1);
attacker.FixedEffect(0x374A, 10, 16);
}
else
{
defender.MeleeDamageAbsorb = 0;
defender.SendLocalizedMessage(1005556); // Your reactive armor spell has been nullified.
DefensiveSpell.Nullify(defender);
}
}
return damage;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,313 @@
using System;
using Server.Engines.ConPVP;
namespace Server.Items
{
public class Fists : BaseMeleeWeapon
{
public Fists() : base(0)
{
Visible = false;
Movable = false;
Quality = WeaponQuality.Regular;
}
public Fists(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm;
public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow;
public override int AosStrengthReq => 0;
public override int AosMinDamage => 1;
public override int AosMaxDamage => 4;
public override int AosSpeed => 50;
public override float MlSpeed => 2.50f;
public override int OldStrengthReq => 0;
public override int OldMinDamage => 1;
public override int OldMaxDamage => 8;
public override int OldSpeed => 30;
public override int DefHitSound => -1;
public override int DefMissSound => -1;
public override SkillName DefSkill => SkillName.Wrestling;
public override WeaponType DefType => WeaponType.Fists;
public override WeaponAnimation DefAnimation => WeaponAnimation.Wrestle;
public static void Initialize()
{
Mobile.DefaultWeapon = new Fists();
EventSink.DisarmRequest += EventSink_DisarmRequest;
EventSink.StunRequest += EventSink_StunRequest;
}
public override double GetDefendSkillValue(Mobile attacker, Mobile defender)
{
double wresValue = defender.Skills.Wrestling.Value;
double anatValue = defender.Skills.Anatomy.Value;
double evalValue = defender.Skills.EvalInt.Value;
double incrValue = (anatValue + evalValue + 20.0) * 0.5;
if (incrValue > 120.0)
incrValue = 120.0;
if (wresValue > incrValue)
return wresValue;
return incrValue;
}
private void CheckPreAOSMoves(Mobile attacker, Mobile defender)
{
if (attacker.StunReady)
{
if (attacker.CanBeginAction<Fists>())
{
if (attacker.Skills.Anatomy.Value >= 80.0 &&
attacker.Skills.Wrestling.Value >= 80.0)
{
if (attacker.Stam >= 15)
{
attacker.Stam -= 15;
if (CheckMove(attacker, SkillName.Anatomy))
{
StartMoveDelay(attacker);
attacker.StunReady = false;
attacker.SendLocalizedMessage(1004013); // You successfully stun your opponent!
defender.SendLocalizedMessage(1004014); // You have been stunned!
defender.Freeze(TimeSpan.FromSeconds(4.0));
}
else
{
attacker.SendLocalizedMessage(1004010); // You failed in your attempt to stun.
defender.SendLocalizedMessage(1004011); // Your opponent tried to stun you and failed.
}
}
else
{
attacker.SendLocalizedMessage(1004009); // You are too fatigued to attempt anything.
}
}
else
{
attacker.SendLocalizedMessage(1004008); // You are not skilled enough to stun your opponent.
attacker.StunReady = false;
}
}
}
else if (attacker.DisarmReady)
{
if (attacker.CanBeginAction<Fists>())
{
if (defender.Player || defender.Body.IsHuman)
{
if (attacker.Skills.ArmsLore.Value >= 80.0 &&
attacker.Skills.Wrestling.Value >= 80.0)
{
if (attacker.Stam >= 15)
{
Item toDisarm = defender.FindItemOnLayer(Layer.OneHanded);
if (toDisarm?.Movable == false)
toDisarm = defender.FindItemOnLayer(Layer.TwoHanded);
Container pack = defender.Backpack;
if (pack == null || toDisarm?.Movable == false)
{
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
}
else if (CheckMove(attacker, SkillName.ArmsLore))
{
StartMoveDelay(attacker);
attacker.Stam -= 15;
attacker.DisarmReady = false;
attacker.SendLocalizedMessage(1004006); // You successfully disarm your opponent!
defender.SendLocalizedMessage(1004007); // You have been disarmed!
pack.DropItem(toDisarm);
}
else
{
attacker.Stam -= 15;
attacker.SendLocalizedMessage(1004004); // You failed in your attempt to disarm.
defender.SendLocalizedMessage(1004005); // Your opponent tried to disarm you but failed.
}
}
else
{
attacker.SendLocalizedMessage(1004003); // You are too fatigued to attempt anything.
}
}
else
{
attacker.SendLocalizedMessage(1004002); // You are not skilled enough to disarm your opponent.
attacker.DisarmReady = false;
}
}
else
{
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
}
}
}
}
public override TimeSpan OnSwing(Mobile attacker, Mobile defender)
{
if (!Core.AOS)
CheckPreAOSMoves(attacker, defender);
return base.OnSwing(attacker, defender);
}
/*public override void OnMiss( Mobile attacker, Mobile defender )
{
base.PlaySwingAnimation( attacker );
}*/
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
Delete();
}
/* Wrestling moves */
private static bool CheckMove(Mobile m, SkillName other)
{
double wresValue = m.Skills.Wrestling.Value;
double scndValue = m.Skills[other].Value;
/* 40% chance at 80, 80
* 50% chance at 100, 100
* 60% chance at 120, 120
*/
double chance = (wresValue + scndValue) / 400.0;
return chance >= Utility.RandomDouble();
}
private static bool HasFreeHands(Mobile m)
{
Item item = m.FindItemOnLayer(Layer.OneHanded);
return (item == null || item is Spellbook) && m.FindItemOnLayer(Layer.TwoHanded) == null;
}
private static void EventSink_DisarmRequest(DisarmRequestEventArgs e)
{
if (Core.AOS)
return;
Mobile m = e.Mobile;
#region Dueling
if (!DuelContext.AllowSpecialAbility(m, "Disarm", true))
return;
#endregion
double armsValue = m.Skills.ArmsLore.Value;
double wresValue = m.Skills.Wrestling.Value;
if (!HasFreeHands(m))
{
m.SendLocalizedMessage(1004029); // You must have your hands free to attempt to disarm your opponent.
m.DisarmReady = false;
}
else if (armsValue >= 80.0 && wresValue >= 80.0)
{
m.DisruptiveAction();
m.DisarmReady = !m.DisarmReady;
m.SendLocalizedMessage(m.DisarmReady ? 1019013 : 1019014);
}
else
{
m.SendLocalizedMessage(1004002); // You are not skilled enough to disarm your opponent.
m.DisarmReady = false;
}
}
private static void EventSink_StunRequest(StunRequestEventArgs e)
{
if (Core.AOS)
return;
Mobile m = e.Mobile;
#region Dueling
if (!DuelContext.AllowSpecialAbility(m, "Stun", true))
return;
#endregion
double anatValue = m.Skills.Anatomy.Value;
double wresValue = m.Skills.Wrestling.Value;
if (!HasFreeHands(m))
{
m.SendLocalizedMessage(1004031); // You must have your hands free to attempt to stun your opponent.
m.StunReady = false;
}
else if (anatValue >= 80.0 && wresValue >= 80.0)
{
m.DisruptiveAction();
m.StunReady = !m.StunReady;
m.SendLocalizedMessage(m.StunReady ? 1019011 : 1019012);
}
else
{
m.SendLocalizedMessage(1004008); // You are not skilled enough to stun your opponent.
m.StunReady = false;
}
}
private static void StartMoveDelay(Mobile m)
{
new MoveDelayTimer(m).Start();
}
private class MoveDelayTimer : Timer
{
private Mobile m_Mobile;
public MoveDelayTimer(Mobile m) : base(TimeSpan.FromSeconds(10.0))
{
m_Mobile = m;
Priority = TimerPriority.TwoFiftyMS;
m_Mobile.BeginAction<Fists>();
}
protected override void OnTick()
{
m_Mobile.EndAction<Fists>();
}
}
}
}

View file

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
namespace Server.Items
{
public class HitLower
{
public static readonly TimeSpan AttackEffectDuration = TimeSpan.FromSeconds(10.0);
public static readonly TimeSpan DefenseEffectDuration = TimeSpan.FromSeconds(8.0);
private static HashSet<Mobile> m_AttackTable = new HashSet<Mobile>();
private static HashSet<Mobile> m_DefenseTable = new HashSet<Mobile>();
public static bool IsUnderAttackEffect(Mobile m)
{
return m_AttackTable.Contains(m);
}
public static bool ApplyAttack(Mobile m)
{
if (IsUnderAttackEffect(m))
return false;
m_AttackTable.Add(m);
AttackTimer timer = new AttackTimer(m);
timer.Start();
m.SendLocalizedMessage(1062319); // Your attack chance has been reduced!
return true;
}
private static void RemoveAttack(Mobile m)
{
m_AttackTable.Remove(m);
m.SendLocalizedMessage(1062320); // Your attack chance has returned to normal.
}
public static bool IsUnderDefenseEffect(Mobile m)
{
return m_DefenseTable.Contains(m);
}
public static bool ApplyDefense(Mobile m)
{
if (IsUnderDefenseEffect(m))
return false;
m_DefenseTable.Add(m);
DefenseTimer timer = new DefenseTimer(m);
timer.Start();
m.SendLocalizedMessage(1062318); // Your defense chance has been reduced!
return true;
}
private static void RemoveDefense(Mobile m)
{
m_DefenseTable.Remove(m);
m.SendLocalizedMessage(1062321); // Your defense chance has returned to normal.
}
private class AttackTimer : Timer
{
private Mobile m_Player;
public AttackTimer(Mobile player) : base(AttackEffectDuration)
{
m_Player = player;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
RemoveAttack(m_Player);
}
}
private class DefenseTimer : Timer
{
private Mobile m_Player;
public DefenseTimer(Mobile player) : base(DefenseEffectDuration)
{
m_Player = player;
Priority = TimerPriority.TwoFiftyMS;
}
protected override void OnTick()
{
RemoveDefense(m_Player);
}
}
}
}

View file

@ -0,0 +1,56 @@
using Server.Targets;
namespace Server.Items
{
public abstract class BaseKnife : BaseMeleeWeapon
{
public BaseKnife(int itemID) : base(itemID)
{
}
public BaseKnife(Serial serial) : base(serial)
{
}
public override int DefHitSound => 0x23B;
public override int DefMissSound => 0x238;
public override SkillName DefSkill => SkillName.Swords;
public override WeaponType DefType => WeaponType.Slashing;
public override WeaponAnimation DefAnimation => WeaponAnimation.Slash1H;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void OnDoubleClick(Mobile from)
{
from.SendLocalizedMessage(1010018); // What do you want to use this item on?
from.Target = new BladedItemTarget(this);
}
public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1)
{
base.OnHit(attacker, defender, damageBonus);
if (!Core.AOS && Poison != null && PoisonCharges > 0)
{
--PoisonCharges;
if (Utility.RandomDouble() >= 0.5) // 50% chance to poison
defender.ApplyPoison(attacker, Poison);
}
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x13F6, 0x13F7)]
public class ButcherKnife : BaseKnife
{
[Constructible]
public ButcherKnife() : base(0x13F6)
{
Weight = 1.0;
}
public ButcherKnife(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 5;
public override int AosMinDamage => 9;
public override int AosMaxDamage => 11;
public override int AosSpeed => 49;
public override float MlSpeed => 2.25f;
public override int OldStrengthReq => 5;
public override int OldMinDamage => 2;
public override int OldMaxDamage => 14;
public override int OldSpeed => 40;
public override int InitMinHits => 31;
public override int InitMaxHits => 40;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0xEC3, 0xEC2)]
public class Cleaver : BaseKnife
{
[Constructible]
public Cleaver() : base(0xEC3)
{
Weight = 2.0;
}
public Cleaver(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.BleedAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.InfectiousStrike;
public override int AosStrengthReq => 10;
public override int AosMinDamage => 11;
public override int AosMaxDamage => 13;
public override int AosSpeed => 46;
public override float MlSpeed => 2.50f;
public override int OldStrengthReq => 10;
public override int OldMinDamage => 2;
public override int OldMaxDamage => 13;
public override int OldSpeed => 40;
public override int InitMinHits => 31;
public override int InitMaxHits => 50;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Weight == 1.0)
Weight = 2.0;
}
}
}

View file

@ -0,0 +1,51 @@
namespace Server.Items
{
[Flippable(0xF52, 0xF51)]
public class Dagger : BaseKnife
{
[Constructible]
public Dagger() : base(0xF52)
{
Weight = 1.0;
}
public Dagger(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike;
public override int AosStrengthReq => 10;
public override int AosMinDamage => 10;
public override int AosMaxDamage => 11;
public override int AosSpeed => 56;
public override float MlSpeed => 2.00f;
public override int OldStrengthReq => 1;
public override int OldMinDamage => 3;
public override int OldMaxDamage => 15;
public override int OldSpeed => 55;
public override int InitMinHits => 31;
public override int InitMaxHits => 40;
public override SkillName DefSkill => SkillName.Fencing;
public override WeaponType DefType => WeaponType.Piercing;
public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0xEC4, 0xEC5)]
public class SkinningKnife : BaseKnife
{
[Constructible]
public SkinningKnife() : base(0xEC4)
{
Weight = 1.0;
}
public SkinningKnife(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 5;
public override int AosMinDamage => 9;
public override int AosMaxDamage => 11;
public override int AosSpeed => 49;
public override float MlSpeed => 2.25f;
public override int OldStrengthReq => 5;
public override int OldMinDamage => 1;
public override int OldMaxDamage => 10;
public override int OldSpeed => 40;
public override int InitMinHits => 31;
public override int InitMaxHits => 40;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,133 @@
using System;
using Server.Targeting;
namespace Server.Items
{
[Flippable(0xF52, 0xF51)]
public class ThrowingDagger : Item
{
[Constructible]
public ThrowingDagger() : base(0xF52)
{
Weight = 1.0;
Layer = Layer.OneHanded;
}
public ThrowingDagger(Serial serial) : base(serial)
{
}
public override string DefaultName => "a throwing dagger";
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void OnDoubleClick(Mobile from)
{
if (from.Items.Contains(this))
{
InternalTarget t = new InternalTarget(this);
from.Target = t;
}
else
{
from.SendMessage("You must be holding that weapon to use it.");
}
}
private class InternalTarget : Target
{
private ThrowingDagger m_Dagger;
public InternalTarget(ThrowingDagger dagger) : base(10, false, TargetFlags.Harmful)
{
m_Dagger = dagger;
}
protected override void OnTarget(Mobile from, object targeted)
{
if (m_Dagger.Deleted) return;
if (!from.Items.Contains(m_Dagger))
from.SendMessage("You must be holding that weapon to use it.");
else if (targeted is Mobile m)
if (m != from && from.HarmfulCheck(m))
{
Direction to = from.GetDirectionTo(m);
from.Direction = to;
from.Animate(from.Mounted ? 26 : 9, 7, 1, true, false, 0);
if (Utility.RandomDouble() >= Math.Sqrt(m.Dex / 100.0) * 0.8)
{
from.MovingEffect(m, 0x1BFE, 7, 1, false, false, 0x481, 0);
AOS.Damage(m, from, Utility.Random(5, from.Str / 10), 100, 0, 0, 0, 0);
m_Dagger.MoveToWorld(m.Location, m.Map);
}
else
{
int x = 0, y = 0;
switch (to & Direction.Mask)
{
case Direction.North:
--y;
break;
case Direction.South:
++y;
break;
case Direction.West:
--x;
break;
case Direction.East:
++x;
break;
case Direction.Up:
--x;
--y;
break;
case Direction.Down:
++x;
++y;
break;
case Direction.Left:
--x;
++y;
break;
case Direction.Right:
++x;
--y;
break;
}
x += Utility.Random(-1, 3);
y += Utility.Random(-1, 3);
x += m.X;
y += m.Y;
m_Dagger.MoveToWorld(new Point3D(x, y, m.Z), m.Map);
from.MovingEffect(m_Dagger, 0x1BFE, 7, 1, false, false, 0x481, 0);
from.SendMessage("You miss.");
}
}
}
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
public class BlightGrippedLongbow : ElvenCompositeLongbow
{
[Constructible]
public BlightGrippedLongbow()
{
Hue = 0x8A4;
WeaponAttributes.HitPoisonArea = 20;
Attributes.RegenStam = 3;
Attributes.NightSight = 1;
Attributes.WeaponSpeed = 20;
Attributes.WeaponDamage = 35;
}
public BlightGrippedLongbow(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072907; // Blight Gripped Longbow
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,44 @@
namespace Server.Items
{
public class ColdForgedBlade : ElvenSpellblade
{
[Constructible]
public ColdForgedBlade()
{
WeaponAttributes.HitHarm = 40;
Attributes.SpellChanneling = 1;
Attributes.NightSight = 1;
Attributes.WeaponSpeed = 25;
Attributes.WeaponDamage = 50;
Hue = GetElementalDamageHue();
}
public ColdForgedBlade(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072916; // Cold Forged Blade
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = pois = nrgy = chaos = direct = 0;
cold = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,44 @@
namespace Server.Items
{
public class LuminousRuneBlade : RuneBlade
{
[Constructible]
public LuminousRuneBlade()
{
WeaponAttributes.HitLightning = 40;
WeaponAttributes.SelfRepair = 5;
Attributes.NightSight = 1;
Attributes.WeaponSpeed = 25;
Attributes.WeaponDamage = 55;
Hue = GetElementalDamageHue();
}
public LuminousRuneBlade(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072922; // Luminous Rune Blade
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = cold = pois = chaos = direct = 0;
nrgy = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,46 @@
namespace Server.Items
{
public class OverseerSunderedBlade : RadiantScimitar
{
[Constructible]
public OverseerSunderedBlade()
{
ItemID = 0x2D27;
Hue = 0x485;
Attributes.RegenStam = 2;
Attributes.AttackChance = 10;
Attributes.WeaponSpeed = 35;
Attributes.WeaponDamage = 45;
Hue = GetElementalDamageHue();
}
public OverseerSunderedBlade(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072920; // Overseer Sundered Blade
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = cold = pois = nrgy = chaos = direct = 0;
fire = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,42 @@
namespace Server.Items
{
public class PhantomStaff : WildStaff
{
[Constructible]
public PhantomStaff()
{
Hue = 0x1;
Attributes.RegenHits = 2;
Attributes.NightSight = 1;
Attributes.WeaponSpeed = 20;
Attributes.WeaponDamage = 60;
}
public PhantomStaff(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072919; // Phantom Staff
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = nrgy = chaos = direct = 0;
cold = pois = 50;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
public class RuneCarvingKnife : AssassinSpike
{
[Constructible]
public RuneCarvingKnife()
{
Hue = 0x48D;
WeaponAttributes.HitLeechMana = 40;
Attributes.RegenStam = 2;
Attributes.LowerManaCost = 10;
Attributes.WeaponSpeed = 35;
Attributes.WeaponDamage = 30;
}
public RuneCarvingKnife(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072915; // Rune Carving Knife
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
public class ShardThrasher : DiamondMace
{
[Constructible]
public ShardThrasher()
{
Hue = 0x4F2;
WeaponAttributes.HitPhysicalArea = 30;
Attributes.BonusStam = 8;
Attributes.AttackChance = 10;
Attributes.WeaponSpeed = 35;
Attributes.WeaponDamage = 40;
}
public ShardThrasher(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072918; // Shard Thrasher
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,43 @@
namespace Server.Items
{
public class SilvanisFeywoodBow : ElvenCompositeLongbow
{
[Constructible]
public SilvanisFeywoodBow()
{
Hue = 0x1A;
Attributes.SpellChanneling = 1;
Attributes.AttackChance = 12;
Attributes.WeaponSpeed = 30;
Attributes.WeaponDamage = 35;
}
public SilvanisFeywoodBow(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072955; // Silvani's Feywood Bow
public override void GetDamageTypes(Mobile wielder, out int phys, out int fire, out int cold, out int pois,
out int nrgy, out int chaos, out int direct)
{
phys = fire = cold = pois = chaos = direct = 0;
nrgy = 100;
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
public class TheNightReaper : RepeatingCrossbow
{
[Constructible]
public TheNightReaper()
{
ItemID = 0x26CD;
Hue = 0x41C;
Slayer = SlayerName.Exorcism;
Attributes.NightSight = 1;
Attributes.WeaponSpeed = 25;
Attributes.WeaponDamage = 55;
}
public TheNightReaper(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1072912; // The Night Reaper
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x2D21, 0x2D2D)]
public class AssassinSpike : BaseKnife
{
[Constructible]
public AssassinSpike() : base(0x2D21)
{
Weight = 4.0;
}
public AssassinSpike(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.InfectiousStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.ShadowStrike;
public override int AosStrengthReq => 15;
public override int AosMinDamage => 10;
public override int AosMaxDamage => 12;
public override int AosSpeed => 50;
public override float MlSpeed => 2.00f;
public override int OldStrengthReq => 15;
public override int OldMinDamage => 10;
public override int OldMaxDamage => 12;
public override int OldSpeed => 50;
public override int DefMissSound => 0x239;
public override SkillName DefSkill => SkillName.Fencing;
public override int InitMinHits => 30; // TODO
public override int InitMaxHits => 60; // TODO
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,37 @@
namespace Server.Items
{
public class ButchersWarCleaver : WarCleaver
{
[Constructible]
public ButchersWarCleaver()
{
}
public ButchersWarCleaver(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073526; // butcher's war cleaver
public override void AppendChildNameProperties(ObjectPropertyList list)
{
base.AppendChildNameProperties(list);
list.Add(1072512); // Bovine Slayer
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x2D24, 0x2D30)]
public class DiamondMace : BaseBashing
{
[Constructible]
public DiamondMace() : base(0x2D24)
{
Weight = 10.0;
}
public DiamondMace(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 17;
public override int AosSpeed => 37;
public override float MlSpeed => 3.00f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 14;
public override int OldMaxDamage => 17;
public override int OldSpeed => 37;
public override int InitMinHits => 30; // TODO
public override int InitMaxHits => 60; // TODO
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,57 @@
using System;
namespace Server.Items
{
[Flippable(0x2D1E, 0x2D2A)]
public class ElvenCompositeLongbow : BaseRanged
{
[Constructible]
public ElvenCompositeLongbow() : base(0x2D1E)
{
Weight = 8.0;
}
public ElvenCompositeLongbow(Serial serial) : base(serial)
{
}
public override int EffectID => 0xF42;
public override Type AmmoType => typeof(Arrow);
public override Item Ammo => new Arrow();
public override WeaponAbility PrimaryAbility => WeaponAbility.ForceArrow;
public override WeaponAbility SecondaryAbility => WeaponAbility.SerpentArrow;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 12;
public override int AosMaxDamage => 16;
public override int AosSpeed => 27;
public override float MlSpeed => 4.00f;
public override int OldStrengthReq => 45;
public override int OldMinDamage => 12;
public override int OldMaxDamage => 16;
public override int OldSpeed => 27;
public override int DefMaxRange => 10;
public override int InitMinHits => 41;
public override int InitMaxHits => 90;
public override WeaponAnimation DefAnimation => WeaponAnimation.ShootBow;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x2D35, 0x2D29)]
public class ElvenMachete : BaseSword
{
[Constructible]
public ElvenMachete() : base(0x2D35)
{
Weight = 6.0;
}
public ElvenMachete(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.DefenseMastery;
public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave;
public override int AosStrengthReq => 20;
public override int AosMinDamage => 13;
public override int AosMaxDamage => 15;
public override int AosSpeed => 41;
public override float MlSpeed => 2.75f;
public override int OldStrengthReq => 20;
public override int OldMinDamage => 13;
public override int OldMaxDamage => 15;
public override int OldSpeed => 41;
public override int DefHitSound => 0x23B;
public override int DefMissSound => 0x239;
public override int InitMinHits => 30;
public override int InitMaxHits => 60;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x2D20, 0x2D2C)]
public class ElvenSpellblade : BaseKnife
{
[Constructible]
public ElvenSpellblade() : base(0x2D20)
{
Weight = 5.0;
Layer = Layer.TwoHanded;
}
public ElvenSpellblade(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.PsychicAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.BleedAttack;
public override int AosStrengthReq => 35;
public override int AosMinDamage => 12;
public override int AosMaxDamage => 14;
public override int AosSpeed => 44;
public override float MlSpeed => 2.50f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 12;
public override int OldMaxDamage => 14;
public override int OldSpeed => 44;
public override int DefMissSound => 0x239;
public override int InitMinHits => 30; // TODO
public override int InitMaxHits => 60; // TODO
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x2D22, 0x2D2E)]
public class Leafblade : BaseKnife
{
[Constructible]
public Leafblade() : base(0x2D22)
{
Weight = 8.0;
}
public Leafblade(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Feint;
public override WeaponAbility SecondaryAbility => WeaponAbility.ArmorIgnore;
public override int AosStrengthReq => 20;
public override int AosMinDamage => 13;
public override int AosMaxDamage => 15;
public override int AosSpeed => 42;
public override float MlSpeed => 2.75f;
public override int OldStrengthReq => 20;
public override int OldMinDamage => 13;
public override int OldMaxDamage => 15;
public override int OldSpeed => 42;
public override int DefMissSound => 0x239;
public override SkillName DefSkill => SkillName.Fencing;
public override int InitMinHits => 30; // TODO
public override int InitMaxHits => 60; // TODO
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,55 @@
using System;
namespace Server.Items
{
[Flippable(0x2D2B, 0x2D1F)]
public class MagicalShortbow : BaseRanged
{
[Constructible]
public MagicalShortbow() : base(0x2D2B)
{
Weight = 6.0;
}
public MagicalShortbow(Serial serial) : base(serial)
{
}
public override int EffectID => 0xF42;
public override Type AmmoType => typeof(Arrow);
public override Item Ammo => new Arrow();
public override WeaponAbility PrimaryAbility => WeaponAbility.LightningArrow;
public override WeaponAbility SecondaryAbility => WeaponAbility.PsychicAttack;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 9;
public override int AosMaxDamage => 13;
public override int AosSpeed => 38;
public override float MlSpeed => 3.00f;
public override int OldStrengthReq => 45;
public override int OldMinDamage => 9;
public override int OldMaxDamage => 13;
public override int OldSpeed => 38;
public override int DefMaxRange => 10;
public override int InitMinHits => 41;
public override int InitMaxHits => 90;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x2D28, 0x2D34)]
public class OrnateAxe : BaseAxe
{
[Constructible]
public OrnateAxe() : base(0x2D28)
{
Weight = 12.0;
Layer = Layer.TwoHanded;
}
public OrnateAxe(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm;
public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 18;
public override int AosMaxDamage => 20;
public override int AosSpeed => 26;
public override float MlSpeed => 3.50f;
public override int OldStrengthReq => 45;
public override int OldMinDamage => 18;
public override int OldMaxDamage => 20;
public override int OldSpeed => 26;
public override int DefMissSound => 0x239;
public override int InitMinHits => 30;
public override int InitMaxHits => 60;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x2D33, 0x2D27)]
public class RadiantScimitar : BaseSword
{
[Constructible]
public RadiantScimitar() : base(0x2D33)
{
Weight = 9.0;
}
public RadiantScimitar(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave;
public override int AosStrengthReq => 20;
public override int AosMinDamage => 12;
public override int AosMaxDamage => 14;
public override int AosSpeed => 43;
public override float MlSpeed => 2.50f;
public override int OldStrengthReq => 20;
public override int OldMinDamage => 12;
public override int OldMaxDamage => 14;
public override int OldSpeed => 43;
public override int DefHitSound => 0x23B;
public override int DefMissSound => 0x239;
public override int InitMinHits => 30;
public override int InitMaxHits => 60;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,51 @@
namespace Server.Items
{
[Flippable(0x2D32, 0x2D26)]
public class RuneBlade : BaseSword
{
[Constructible]
public RuneBlade() : base(0x2D32)
{
Weight = 7.0;
Layer = Layer.TwoHanded;
}
public RuneBlade(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm;
public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave;
public override int AosStrengthReq => 30;
public override int AosMinDamage => 15;
public override int AosMaxDamage => 17;
public override int AosSpeed => 35;
public override float MlSpeed => 3.00f;
public override int OldStrengthReq => 30;
public override int OldMinDamage => 15;
public override int OldMaxDamage => 17;
public override int OldSpeed => 35;
public override int DefHitSound => 0x23B;
public override int DefMissSound => 0x239;
public override int InitMinHits => 30;
public override int InitMaxHits => 60;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,54 @@
namespace Server.Items
{
[Flippable(0x2D2F, 0x2D23)]
public class WarCleaver : BaseKnife
{
[Constructible]
public WarCleaver() : base(0x2D2F)
{
Weight = 10.0;
}
public WarCleaver(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Disarm;
public override WeaponAbility SecondaryAbility => WeaponAbility.Bladeweave;
public override int AosStrengthReq => 15;
public override int AosMinDamage => 9;
public override int AosMaxDamage => 11;
public override int AosSpeed => 48;
public override float MlSpeed => 2.25f;
public override int OldStrengthReq => 15;
public override int OldMinDamage => 9;
public override int OldMaxDamage => 11;
public override int OldSpeed => 48;
public override int DefHitSound => 0x23B;
public override int DefMissSound => 0x239;
public override int InitMinHits => 30; // TODO
public override int InitMaxHits => 60; // TODO
public override SkillName DefSkill => SkillName.Fencing;
public override WeaponType DefType => WeaponType.Piercing;
public override WeaponAnimation DefAnimation => WeaponAnimation.Pierce1H;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x2D25, 0x2D31)]
public class WildStaff : BaseStaff
{
[Constructible]
public WildStaff() : base(0x2D25)
{
Weight = 8.0;
}
public WildStaff(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Block;
public override WeaponAbility SecondaryAbility => WeaponAbility.ForceOfNature;
public override int AosStrengthReq => 15;
public override int AosMinDamage => 10;
public override int AosMaxDamage => 12;
public override int AosSpeed => 48;
public override float MlSpeed => 2.25f;
public override int OldStrengthReq => 15;
public override int OldMinDamage => 10;
public override int OldMaxDamage => 12;
public override int OldSpeed => 48;
public override int InitMinHits => 30;
public override int InitMaxHits => 60;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,61 @@
using Server.Engines.ConPVP;
namespace Server.Items
{
public abstract class BaseBashing : BaseMeleeWeapon
{
public BaseBashing(int itemID) : base(itemID)
{
}
public BaseBashing(Serial serial) : base(serial)
{
}
public override int DefHitSound => 0x233;
public override int DefMissSound => 0x239;
public override SkillName DefSkill => SkillName.Macing;
public override WeaponType DefType => WeaponType.Bashing;
public override WeaponAnimation DefAnimation => WeaponAnimation.Bash1H;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1)
{
base.OnHit(attacker, defender, damageBonus);
defender.Stam -= Utility.Random(3, 3); // 3-5 points of stamina loss
}
public override double GetBaseDamage(Mobile attacker)
{
double damage = base.GetBaseDamage(attacker);
if (!Core.AOS && (attacker.Player || attacker.Body.IsHuman) && Layer == Layer.TwoHanded &&
attacker.Skills.Anatomy.Value >= 80 &&
attacker.Skills.Anatomy.Value / 400.0 >= Utility.RandomDouble() &&
DuelContext.AllowSpecialAbility(attacker, "Crushing Blow", false))
{
damage *= 1.5;
attacker.SendMessage("You deliver a crushing blow!"); // Is this not localized?
attacker.PlaySound(0x11C);
}
return damage;
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x13b4, 0x13b3)]
public class Club : BaseBashing
{
[Constructible]
public Club() : base(0x13B4)
{
Weight = 9.0;
}
public Club(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ShadowStrike;
public override WeaponAbility SecondaryAbility => WeaponAbility.Dismount;
public override int AosStrengthReq => 40;
public override int AosMinDamage => 11;
public override int AosMaxDamage => 13;
public override int AosSpeed => 44;
public override float MlSpeed => 2.50f;
public override int OldStrengthReq => 10;
public override int OldMinDamage => 8;
public override int OldMaxDamage => 24;
public override int OldSpeed => 40;
public override int InitMinHits => 31;
public override int InitMaxHits => 40;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class EmeraldMace : DiamondMace
{
[Constructible]
public EmeraldMace()
{
WeaponAttributes.ResistPoisonBonus = 5;
}
public EmeraldMace(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073530; // emerald mace
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,130 @@
using System;
namespace Server.Items
{
public class FireworksWand : MagicWand
{
private int m_Charges;
[Constructible]
public FireworksWand(int charges = 100)
{
m_Charges = charges;
LootType = LootType.Blessed;
}
public FireworksWand(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1041424; // a fireworks wand
[CommandProperty(AccessLevel.GameMaster)]
public int Charges
{
get => m_Charges;
set
{
m_Charges = value;
InvalidateProperties();
}
}
public override void AddNameProperties(ObjectPropertyList list)
{
base.AddNameProperties(list);
list.Add(1060741, m_Charges.ToString()); // charges: ~1_val~
}
public override void OnDoubleClick(Mobile from)
{
BeginLaunch(from, true);
}
public void BeginLaunch(Mobile from, bool useCharges)
{
Map map = from.Map;
if (map == null || map == Map.Internal)
return;
if (useCharges)
{
if (Charges > 0)
{
--Charges;
}
else
{
from.SendLocalizedMessage(502412); // There are no charges left on that item.
return;
}
}
from.SendLocalizedMessage(502615); // You launch a firework!
Point3D ourLoc = GetWorldLocation();
Point3D startLoc = new Point3D(ourLoc.X, ourLoc.Y, ourLoc.Z + 10);
Point3D endLoc = new Point3D(startLoc.X + Utility.RandomMinMax(-2, 2), startLoc.Y + Utility.RandomMinMax(-2, 2),
startLoc.Z + 32);
Effects.SendMovingEffect(new Entity(Serial.Zero, startLoc, map), new Entity(Serial.Zero, endLoc, map),
0x36E4, 5, 0, false, false);
Timer.DelayCall(TimeSpan.FromSeconds(1.0), () => FinishLaunch(endLoc, map));
}
private void FinishLaunch(Point3D endLoc, Map map)
{
int hue = Utility.Random(40);
if (hue < 8)
hue = 0x66D;
else if (hue < 10)
hue = 0x482;
else if (hue < 12)
hue = 0x47E;
else if (hue < 16)
hue = 0x480;
else if (hue < 20)
hue = 0x47F;
else
hue = 0;
if (Utility.RandomBool())
hue = Utility.RandomList(0x47E, 0x47F, 0x480, 0x482, 0x66D);
int renderMode = Utility.RandomList(0, 2, 3, 4, 5, 7);
Effects.PlaySound(endLoc, map, Utility.Random(0x11B, 4));
Effects.SendLocationEffect(endLoc, map, 0x373A + 0x10 * Utility.Random(4), 16, 10, hue, renderMode);
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(m_Charges);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
switch (version)
{
case 0:
{
m_Charges = reader.ReadInt();
break;
}
}
}
}
}

View file

@ -0,0 +1,48 @@
namespace Server.Items
{
[Flippable(0x143D, 0x143C)]
public class HammerPick : BaseBashing
{
[Constructible]
public HammerPick() : base(0x143D)
{
Weight = 9.0;
Layer = Layer.OneHanded;
}
public HammerPick(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore;
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 15;
public override int AosMaxDamage => 17;
public override int AosSpeed => 28;
public override float MlSpeed => 3.75f;
public override int OldStrengthReq => 35;
public override int OldMinDamage => 6;
public override int OldMaxDamage => 33;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0xF5C, 0xF5D)]
public class Mace : BaseBashing
{
[Constructible]
public Mace() : base(0xF5C)
{
Weight = 14.0;
}
public Mace(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 12;
public override int AosMaxDamage => 14;
public override int AosSpeed => 40;
public override float MlSpeed => 2.75f;
public override int OldStrengthReq => 20;
public override int OldMinDamage => 8;
public override int OldMaxDamage => 32;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,46 @@
namespace Server.Items
{
public class MagicWand : BaseBashing
{
[Constructible]
public MagicWand() : base(0xDF2)
{
Weight = 1.0;
}
public MagicWand(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.Dismount;
public override WeaponAbility SecondaryAbility => WeaponAbility.Disarm;
public override int AosStrengthReq => 5;
public override int AosMinDamage => 9;
public override int AosMaxDamage => 11;
public override int AosSpeed => 40;
public override float MlSpeed => 2.75f;
public override int OldStrengthReq => 0;
public override int OldMinDamage => 2;
public override int OldMaxDamage => 6;
public override int OldSpeed => 35;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x143B, 0x143A)]
public class Maul : BaseBashing
{
[Constructible]
public Maul() : base(0x143B)
{
Weight = 10.0;
}
public Maul(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow;
public override int AosStrengthReq => 45;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 16;
public override int AosSpeed => 32;
public override float MlSpeed => 3.50f;
public override int OldStrengthReq => 20;
public override int OldMinDamage => 10;
public override int OldMaxDamage => 30;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 70;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
if (Weight == 14.0)
Weight = 10.0;
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class RubyMace : DiamondMace
{
[Constructible]
public RubyMace()
{
Attributes.WeaponDamage = 5;
}
public RubyMace(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073529; // ruby mace
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class SapphireMace : DiamondMace
{
[Constructible]
public SapphireMace()
{
WeaponAttributes.ResistEnergyBonus = 5;
}
public SapphireMace(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073531; // sapphire mace
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x26BC, 0x26C6)]
public class Scepter : BaseBashing
{
[Constructible]
public Scepter() : base(0x26BC)
{
Weight = 8.0;
}
public Scepter(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
public override int AosStrengthReq => 40;
public override int AosMinDamage => 14;
public override int AosMaxDamage => 17;
public override int AosSpeed => 30;
public override float MlSpeed => 3.50f;
public override int OldStrengthReq => 40;
public override int OldMinDamage => 14;
public override int OldMaxDamage => 17;
public override int OldSpeed => 30;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,31 @@
namespace Server.Items
{
public class SilverEtchedMace : DiamondMace
{
[Constructible]
public SilverEtchedMace()
{
Slayer = SlayerName.Exorcism;
}
public SilverEtchedMace(Serial serial) : base(serial)
{
}
public override int LabelNumber => 1073532; // silver-etched mace
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.WriteEncodedInt(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,50 @@
namespace Server.Items
{
[Flippable(0x1439, 0x1438)]
public class WarHammer : BaseBashing
{
[Constructible]
public WarHammer() : base(0x1439)
{
Weight = 10.0;
Layer = Layer.TwoHanded;
}
public WarHammer(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.WhirlwindAttack;
public override WeaponAbility SecondaryAbility => WeaponAbility.CrushingBlow;
public override int AosStrengthReq => 95;
public override int AosMinDamage => 17;
public override int AosMaxDamage => 18;
public override int AosSpeed => 28;
public override float MlSpeed => 3.75f;
public override int OldStrengthReq => 40;
public override int OldMinDamage => 8;
public override int OldMaxDamage => 36;
public override int OldSpeed => 31;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override WeaponAnimation DefAnimation => WeaponAnimation.Bash2H;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

View file

@ -0,0 +1,47 @@
namespace Server.Items
{
[Flippable(0x1407, 0x1406)]
public class WarMace : BaseBashing
{
[Constructible]
public WarMace() : base(0x1407)
{
Weight = 17.0;
}
public WarMace(Serial serial) : base(serial)
{
}
public override WeaponAbility PrimaryAbility => WeaponAbility.CrushingBlow;
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
public override int AosStrengthReq => 80;
public override int AosMinDamage => 16;
public override int AosMaxDamage => 17;
public override int AosSpeed => 26;
public override float MlSpeed => 4.00f;
public override int OldStrengthReq => 30;
public override int OldMinDamage => 10;
public override int OldMaxDamage => 30;
public override int OldSpeed => 32;
public override int InitMinHits => 31;
public override int InitMaxHits => 110;
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
int version = reader.ReadInt();
}
}
}

Some files were not shown because too many files have changed in this diff Show more