fix: Adds throwing weapons (#1107)
This commit is contained in:
parent
38686c09b2
commit
7c981b2d10
17 changed files with 443 additions and 160 deletions
|
|
@ -23,7 +23,7 @@ public static class Utility
|
|||
|
||||
private static Dictionary<IPAddress, IPAddress> _ipAddressTable;
|
||||
|
||||
private static readonly SkillName[] m_AllSkills =
|
||||
private static SkillName[] _allSkills =
|
||||
{
|
||||
SkillName.Alchemy,
|
||||
SkillName.Anatomy,
|
||||
|
|
@ -79,7 +79,10 @@ public static class Utility
|
|||
SkillName.Chivalry,
|
||||
SkillName.Bushido,
|
||||
SkillName.Ninjitsu,
|
||||
SkillName.Spellweaving
|
||||
SkillName.Spellweaving,
|
||||
// SkillName.Mysticism,
|
||||
// SkillName.Imbuing,
|
||||
SkillName.Throwing
|
||||
};
|
||||
|
||||
private static readonly SkillName[] m_CombatSkills =
|
||||
|
|
@ -622,11 +625,7 @@ public static class Utility
|
|||
array.Length > 0 ? array.GetValue(Math.Clamp(index, 0, array.Length - 1)) : emptyValue;
|
||||
|
||||
public static SkillName RandomSkill() =>
|
||||
m_AllSkills[Random(
|
||||
m_AllSkills.Length - (Core.ML ? 0 :
|
||||
Core.SE ? 1 :
|
||||
Core.AOS ? 3 : 6)
|
||||
)];
|
||||
_allSkills[Random(_allSkills.Length - (Core.ML ? 0 : Core.SE ? 1 : Core.AOS ? 3 : 6))];
|
||||
|
||||
public static SkillName RandomCombatSkill() => m_CombatSkills.RandomElement();
|
||||
|
||||
|
|
|
|||
|
|
@ -48,11 +48,12 @@ namespace Server.Items
|
|||
|
||||
public override void OnDoubleClick(Mobile from)
|
||||
{
|
||||
if ((_arrows > 0 || _bolts > 0) && from.InRange(GetWorldLocation(), 1))
|
||||
var inRange = from.InRange(GetWorldLocation(), 1);
|
||||
if ((_arrows > 0 || _bolts > 0) && inRange)
|
||||
{
|
||||
Gather(from);
|
||||
}
|
||||
else
|
||||
else if (from.Weapon is not BaseThrown || inRange)
|
||||
{
|
||||
Fire(from);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,114 +2,108 @@ using System;
|
|||
using Server.Mobiles;
|
||||
using Server.Spells.Ninjitsu;
|
||||
|
||||
namespace Server.Items
|
||||
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
|
||||
{
|
||||
/// <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 void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
public static readonly TimeSpan RemountDelay = TimeSpan.FromSeconds(10.0);
|
||||
|
||||
public override int BaseMana => 20;
|
||||
|
||||
public override bool Validate(Mobile from)
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
{
|
||||
if (!base.Validate(from))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (from.Mounted && from.Weapon is not Lance)
|
||||
{
|
||||
from.SendLocalizedMessage(1061283); // You cannot perform that attack while mounted!
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
if (defender is ChaosDragoon or ChaosDragoonElite)
|
||||
{
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
return;
|
||||
}
|
||||
|
||||
if (attacker.Mounted || attacker.Flying)
|
||||
{
|
||||
if (attacker.Weapon is not Lance || !defender.Mounted && !defender.Flying && defender.Weapon is not Lance)
|
||||
{
|
||||
return;
|
||||
attacker.SendLocalizedMessage(1061283); // You cannot perform that attack while mounted!
|
||||
}
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
|
||||
var mount = defender.Mount;
|
||||
|
||||
if (mount == null && !AnimalForm.UnderTransformation(defender))
|
||||
{
|
||||
attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets
|
||||
return;
|
||||
}
|
||||
|
||||
if (Core.ML && attacker is LesserHiryu && Utility.RandomDouble() <= 0.8)
|
||||
{
|
||||
return; // Lesser Hiryu have an 80% chance of missing this attack
|
||||
}
|
||||
|
||||
DoDismount(attacker, defender, TimeSpan.FromSeconds(10));
|
||||
|
||||
if (!attacker.Mounted)
|
||||
{
|
||||
AOS.Damage(defender, attacker, Utility.RandomMinMax(15, 25), 100, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoDismount(Mobile attacker, Mobile defender, TimeSpan delay, BlockMountType type = BlockMountType.Dazed)
|
||||
{
|
||||
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 (defender.Flying)
|
||||
{
|
||||
defender.SendLocalizedMessage(1113590, attacker.Name); // You have been grounded by ~1_NAME~!
|
||||
}
|
||||
else if (mobile.Mounted)
|
||||
{
|
||||
mobile.SendLocalizedMessage(1040023); // You have been knocked off of your mount!
|
||||
}
|
||||
|
||||
if (defender is ChaosDragoon or ChaosDragoonElite)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mobile.SetMountBlock(type, delay, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
defender.Mount.Rider = null;
|
||||
}
|
||||
|
||||
// TODO: Should there be a message here?
|
||||
if (attacker.Mounted && (attacker.Weapon is not Lance || defender.Weapon is not Lance))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
|
||||
var mount = defender.Mount;
|
||||
|
||||
if (mount == null && !AnimalForm.UnderTransformation(defender))
|
||||
{
|
||||
attacker.SendLocalizedMessage(1060848); // This attack only works on mounted targets
|
||||
return;
|
||||
}
|
||||
|
||||
if (Core.ML && attacker is LesserHiryu && Utility.RandomDouble() <= 0.8)
|
||||
{
|
||||
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 { ControlMaster: PlayerMobile pm })
|
||||
{
|
||||
pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false);
|
||||
}
|
||||
|
||||
if (!attacker.Mounted)
|
||||
{
|
||||
AOS.Damage(defender, attacker, Utility.RandomMinMax(15, 25), 100, 0, 0, 0, 0);
|
||||
}
|
||||
if (attacker is PlayerMobile playerMobile)
|
||||
{
|
||||
playerMobile.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, true);
|
||||
}
|
||||
else if (Core.ML && attacker is BaseCreature { ControlMaster: PlayerMobile pm })
|
||||
{
|
||||
pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
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) || !CheckMana(attacker, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
var toDisrobe = defender.FindItemOnLayer(Layer.InnerTorso);
|
||||
|
||||
if (toDisrobe?.Movable == false)
|
||||
{
|
||||
toDisrobe = defender.FindItemOnLayer(Layer.OuterTorso);
|
||||
}
|
||||
|
||||
var pack = defender.Backpack;
|
||||
|
||||
if (pack == null || toDisrobe?.Movable == false)
|
||||
{
|
||||
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Projects/UOContent/Items/Weapons/Abilities/InfusedThrow.cs
Normal file
45
Projects/UOContent/Items/Weapons/Abilities/InfusedThrow.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
using Server.Mobiles;
|
||||
using System;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
// The projectile will be infused with energy by the attacker causing it to do more damage and stun or dismount the target.
|
||||
// The player infuses their throwing projectile with mystical power.
|
||||
// The infused projectile will dismount the target if possible; otherwise it will temporarily stun the target.
|
||||
// The target will be hit with chaos damage regardless of whether they were dismounted or paralyzed.
|
||||
public class InfusedThrow : WeaponAbility
|
||||
{
|
||||
public override int BaseMana => 25;
|
||||
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!CheckMana(attacker, true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
|
||||
attacker.SendLocalizedMessage(1149563); //The infused projectile strikes a target!
|
||||
defender.SendLocalizedMessage(1149564); //You are struck by the infused projectile and take damage!
|
||||
|
||||
AOS.Damage(defender, attacker, 15, false, 0, 0, 0, 0, 0, 100);
|
||||
|
||||
IMount mount = defender.Mount;
|
||||
|
||||
if ((defender.Mounted || defender.Flying || Spells.Ninjitsu.AnimalForm.UnderTransformation(defender)) &&
|
||||
!attacker.Mounted && !attacker.Flying && defender is not ChaosDragoon && defender is not ChaosDragoonElite)
|
||||
{
|
||||
defender.PlaySound(0x140);
|
||||
defender.FixedParticles(0x3728, 10, 15, 9955, EffectLayer.Waist);
|
||||
|
||||
Items.Dismount.DoDismount(attacker, defender, TimeSpan.FromSeconds(10));
|
||||
}
|
||||
else
|
||||
{
|
||||
defender.FixedEffect(0x376A, 9, 32);
|
||||
defender.PlaySound(0x204);
|
||||
defender.Paralyze(TimeSpan.FromSeconds(defender.Player ? 3.0 : 6.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Projects/UOContent/Items/Weapons/Abilities/MysticArc.cs
Normal file
91
Projects/UOContent/Items/Weapons/Abilities/MysticArc.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using Server.Collections;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
// The thrown projectile will arc to a second target after hitting the primary target.
|
||||
// Chaos energy will burst from the projectile at each target. This will only hit targets that are in combat with the user.
|
||||
public class MysticArc : WeaponAbility
|
||||
{
|
||||
private readonly int Damage = 15;
|
||||
private Mobile _target;
|
||||
private Mobile _mobile;
|
||||
|
||||
public override int BaseMana => 20;
|
||||
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!CheckMana(attacker, true) && defender != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BaseThrown weapon = attacker.Weapon as BaseThrown;
|
||||
|
||||
if (weapon == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var queue = PooledRefQueue<Mobile>.Create();
|
||||
IPooledEnumerable eable = attacker.GetMobilesInRange(weapon.MaxRange);
|
||||
|
||||
foreach (Mobile m in eable)
|
||||
{
|
||||
if (m == defender)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m.Combatant != attacker)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
queue.Enqueue(m);
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
|
||||
if (queue.Count > 0)
|
||||
{
|
||||
_target = queue.PeekRandom();
|
||||
}
|
||||
|
||||
AOS.Damage(defender, attacker, Damage, 0, 0, 0, 0, 0, 100);
|
||||
|
||||
if (_target != null)
|
||||
{
|
||||
defender?.MovingEffect(_target, weapon.ItemID, 18, 1, false, false);
|
||||
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(0.3), ThrowAgain);
|
||||
_mobile = attacker;
|
||||
}
|
||||
|
||||
ClearCurrentAbility(attacker);
|
||||
}
|
||||
|
||||
public void ThrowAgain()
|
||||
{
|
||||
if (_target == null || _mobile == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mobile.Weapon is not BaseThrown weapon)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetCurrentAbility(_mobile) is MysticArc)
|
||||
{
|
||||
ClearCurrentAbility(_mobile);
|
||||
}
|
||||
|
||||
if (weapon.CheckHit(_mobile, _target))
|
||||
{
|
||||
weapon.OnHit(_mobile, _target, 0.0);
|
||||
AOS.Damage(_target, _mobile, Damage, 0, 0, 0, 0, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,8 @@ namespace Server.Items
|
|||
new PsychicAttack(),
|
||||
new SerpentArrow(),
|
||||
new ForceOfNature(),
|
||||
new Disrobe()
|
||||
new InfusedThrow(),
|
||||
new MysticArc(),
|
||||
};
|
||||
|
||||
public static readonly WeaponAbility ArmorIgnore = Abilities[1];
|
||||
|
|
@ -79,7 +80,8 @@ namespace Server.Items
|
|||
public static readonly WeaponAbility SerpentArrow = Abilities[28];
|
||||
public static readonly WeaponAbility ForceOfNature = Abilities[29];
|
||||
|
||||
public static readonly WeaponAbility Disrobe = Abilities[30];
|
||||
public static readonly WeaponAbility InfusedThrow = Abilities[30];
|
||||
public static readonly WeaponAbility MysticArc = Abilities[31];
|
||||
|
||||
private static readonly Dictionary<Mobile, WeaponAbilityContext> m_PlayersTable =
|
||||
new();
|
||||
|
|
|
|||
105
Projects/UOContent/Items/Weapons/Throwing/BaseThrown.cs
Normal file
105
Projects/UOContent/Items/Weapons/Throwing/BaseThrown.cs
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
using System;
|
||||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public abstract partial class BaseThrown : BaseRanged
|
||||
{
|
||||
public BaseThrown(int itemID) : base(itemID)
|
||||
{
|
||||
}
|
||||
|
||||
public abstract int MinThrowRange { get; }
|
||||
|
||||
public virtual int MaxThrowRange => MinThrowRange + 3;
|
||||
|
||||
public override int DefMaxRange
|
||||
{
|
||||
get
|
||||
{
|
||||
int baseRange = MaxThrowRange;
|
||||
|
||||
return Parent is Mobile attacker
|
||||
? baseRange - 3 + (attacker.Str - AosStrengthReq) / ((140 - AosStrengthReq) / 3)
|
||||
: baseRange;
|
||||
}
|
||||
}
|
||||
|
||||
public override int EffectID => ItemID;
|
||||
|
||||
public override Type AmmoType => null;
|
||||
|
||||
public override Item Ammo => null;
|
||||
|
||||
public override int DefHitSound => 0x5D3;
|
||||
public override int DefMissSound => 0x5D4;
|
||||
|
||||
public override SkillName DefSkill => SkillName.Throwing;
|
||||
|
||||
public override WeaponAnimation DefAnimation => WeaponAnimation.Throwing;
|
||||
|
||||
public override bool OnFired(Mobile attacker, Mobile defender)
|
||||
{
|
||||
if (!attacker.InRange(defender, 1))
|
||||
{
|
||||
attacker.MovingEffect(defender, EffectID, 18, 1, false, false, Hue, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnHit(Mobile attacker, Mobile defender, double damageBonus = 1)
|
||||
{
|
||||
if (WeaponAbility.GetCurrentAbility(attacker) is not MysticArc)
|
||||
{
|
||||
var location = new WorldLocation(defender.Location, attacker.Map);
|
||||
Timer.StartTimer(TimeSpan.FromSeconds(0.3), () => Return(attacker, defender, location));
|
||||
}
|
||||
|
||||
base.OnHit(attacker, defender, damageBonus);
|
||||
}
|
||||
|
||||
public override void OnMiss(Mobile attacker, Mobile defender)
|
||||
{
|
||||
if (WeaponAbility.GetCurrentAbility(attacker) is not MysticArc)
|
||||
{
|
||||
var location = new WorldLocation(defender.Location, attacker.Map);
|
||||
Timer.StartTimer(TimeSpan.FromSeconds(0.3), () => Return(attacker, defender, location));
|
||||
}
|
||||
|
||||
base.OnMiss(attacker, defender);
|
||||
}
|
||||
|
||||
public virtual void Return(Mobile thrower, Mobile target, WorldLocation worldLocation)
|
||||
{
|
||||
if (thrower == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (target != null)
|
||||
{
|
||||
target.MovingEffect(thrower, EffectID, 18, 1, false, false, Hue, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Effects.SendMovingParticles(
|
||||
new Entity(Serial.Zero, worldLocation.Location, worldLocation.Map),
|
||||
thrower,
|
||||
ItemID,
|
||||
18,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
Hue,
|
||||
0,
|
||||
9502,
|
||||
1,
|
||||
0,
|
||||
(EffectLayer)255,
|
||||
0x100
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Projects/UOContent/Items/Weapons/Throwing/Boomerang.cs
Normal file
25
Projects/UOContent/Items/Weapons/Throwing/Boomerang.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class Boomerang : BaseThrown
|
||||
{
|
||||
[Constructible]
|
||||
public Boomerang() : base(0x8FF)
|
||||
{
|
||||
Weight = 4.0;
|
||||
Layer = Layer.OneHanded;
|
||||
}
|
||||
|
||||
public override int MinThrowRange => 4;
|
||||
|
||||
public override WeaponAbility PrimaryAbility => WeaponAbility.MysticArc;
|
||||
public override WeaponAbility SecondaryAbility => WeaponAbility.ConcussionBlow;
|
||||
public override int AosStrengthReq => 25;
|
||||
public override int AosMinDamage => 11;
|
||||
public override int AosMaxDamage => 15;
|
||||
public override float MlSpeed => 2.75f;
|
||||
public override int InitMinHits => 31;
|
||||
public override int InitMaxHits => 60;
|
||||
}
|
||||
27
Projects/UOContent/Items/Weapons/Throwing/Cyclone.cs
Normal file
27
Projects/UOContent/Items/Weapons/Throwing/Cyclone.cs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class Cyclone : BaseThrown
|
||||
{
|
||||
[Constructible]
|
||||
public Cyclone() : base(0x901)
|
||||
{
|
||||
Weight = 6.0;
|
||||
Layer = Layer.OneHanded;
|
||||
}
|
||||
|
||||
public override int MinThrowRange => 6;
|
||||
|
||||
public override WeaponAbility PrimaryAbility => WeaponAbility.MovingShot;
|
||||
public override WeaponAbility SecondaryAbility => WeaponAbility.InfusedThrow;
|
||||
public override int AosStrengthReq => 40;
|
||||
public override int AosMinDamage => 13;
|
||||
public override int AosMaxDamage => 17;
|
||||
public override float MlSpeed => 3.25f;
|
||||
public override int InitMinHits => 31;
|
||||
public override int InitMaxHits => 60;
|
||||
|
||||
|
||||
}
|
||||
26
Projects/UOContent/Items/Weapons/Throwing/SoulGlaive.cs
Normal file
26
Projects/UOContent/Items/Weapons/Throwing/SoulGlaive.cs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
using ModernUO.Serialization;
|
||||
|
||||
namespace Server.Items;
|
||||
|
||||
[SerializationGenerator(0)]
|
||||
public partial class SoulGlaive : BaseThrown
|
||||
{
|
||||
[Constructible]
|
||||
public SoulGlaive() : base(0x090A)
|
||||
{
|
||||
Weight = 8.0;
|
||||
Layer = Layer.OneHanded;
|
||||
}
|
||||
|
||||
public override int MinThrowRange => 8;
|
||||
|
||||
public override WeaponAbility PrimaryAbility => WeaponAbility.ArmorIgnore;
|
||||
public override WeaponAbility SecondaryAbility => WeaponAbility.MortalStrike;
|
||||
public override int AosStrengthReq => 60;
|
||||
public override int AosMinDamage => 16;
|
||||
public override int AosMaxDamage => 20;
|
||||
public override float MlSpeed => 4.00f;
|
||||
|
||||
public override int InitMinHits => 31;
|
||||
public override int InitMaxHits => 65;
|
||||
}
|
||||
|
|
@ -59,6 +59,7 @@ namespace Server.Items
|
|||
Pierce2H = 14,
|
||||
ShootBow = 18,
|
||||
ShootXBow = 19,
|
||||
Wrestle = 31
|
||||
Wrestle = 31,
|
||||
Throwing = 32
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Items.BaseThrown"
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Items.Boomerang"
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Items.Cyclone"
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"version": 0,
|
||||
"type": "Server.Items.SoulGlaive"
|
||||
}
|
||||
|
|
@ -1264,7 +1264,7 @@ public static class CharacterCreation
|
|||
{
|
||||
if (gargoyle)
|
||||
{
|
||||
// EquipItem(m, new Boomerang());
|
||||
EquipItem(m, new Boomerang());
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue