fix: Adds missing ML Abilities (#799)
This commit is contained in:
parent
4893094bb4
commit
5725fba373
27 changed files with 931 additions and 243 deletions
|
|
@ -10,18 +10,7 @@ namespace Server.Items
|
||||||
public override double DamageScalar => 1.5;
|
public override double DamageScalar => 1.5;
|
||||||
|
|
||||||
public override bool RequiresSE => true;
|
public override bool RequiresSE => true;
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
public override bool CheckSkills(Mobile from)
|
|
||||||
{
|
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063347, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
106
Projects/UOContent/Items/Weapons/Abilities/Bladeweave.cs
Normal file
106
Projects/UOContent/Items/Weapons/Abilities/Bladeweave.cs
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
using Server.Mobiles;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Server.Items
|
||||||
|
{
|
||||||
|
public class Bladeweave : WeaponAbility
|
||||||
|
{
|
||||||
|
private class BladeWeaveRedirect
|
||||||
|
{
|
||||||
|
public readonly WeaponAbility NewAbility;
|
||||||
|
public readonly int ClilocEntry;
|
||||||
|
|
||||||
|
public BladeWeaveRedirect(WeaponAbility ability, int cliloc)
|
||||||
|
{
|
||||||
|
NewAbility = ability;
|
||||||
|
ClilocEntry = cliloc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<Mobile, BladeWeaveRedirect> _newAttack = new();
|
||||||
|
|
||||||
|
public static bool BladeWeaving(Mobile attacker, out WeaponAbility a)
|
||||||
|
{
|
||||||
|
if (_newAttack.TryGetValue(attacker, out var bwr))
|
||||||
|
{
|
||||||
|
a = bwr.NewAbility;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
a = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
|
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
|
||||||
|
{
|
||||||
|
if (!Validate(attacker) || !CheckMana(attacker, false))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bladeweave is only from 90 fighting and tactics skill, so you need only to check bushido/ninjitsu value over 50 to perform block and feint.
|
||||||
|
var requiredBushido = Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value);
|
||||||
|
|
||||||
|
var ran = Utility.Random(requiredBushido >= 50 ? 9 : 7);
|
||||||
|
|
||||||
|
var newAttack = _newAttack[attacker] = GetBladeWeaveRedirect(ran);
|
||||||
|
|
||||||
|
return newAttack.NewAbility.OnBeforeSwing(attacker, defender);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BladeWeaveRedirect GetBladeWeaveRedirect(int number) =>
|
||||||
|
number switch
|
||||||
|
{
|
||||||
|
0 => new BladeWeaveRedirect(ArmorIgnore, 1028838),
|
||||||
|
1 => new BladeWeaveRedirect(BleedAttack, 1028839),
|
||||||
|
2 => new BladeWeaveRedirect(ConcussionBlow, 1028840),
|
||||||
|
3 => new BladeWeaveRedirect(CrushingBlow, 1028841),
|
||||||
|
4 => new BladeWeaveRedirect(DoubleStrike, 1028844),
|
||||||
|
5 => new BladeWeaveRedirect(MortalStrike, 1028846),
|
||||||
|
6 => new BladeWeaveRedirect(ParalyzingBlow, 1028848),
|
||||||
|
7 => new BladeWeaveRedirect(Block, 1028853),
|
||||||
|
_ => new BladeWeaveRedirect(Feint, 1028857) //8
|
||||||
|
};
|
||||||
|
|
||||||
|
public override bool OnBeforeDamage(Mobile attacker, Mobile defender) =>
|
||||||
|
_newAttack.TryGetValue(attacker, out var bwr)
|
||||||
|
? bwr.NewAbility.OnBeforeDamage(attacker, defender)
|
||||||
|
: base.OnBeforeDamage(attacker, defender);
|
||||||
|
|
||||||
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
|
{
|
||||||
|
if (CheckMana(attacker, false))
|
||||||
|
{
|
||||||
|
if (_newAttack.TryGetValue(attacker, out var bwr))
|
||||||
|
{
|
||||||
|
attacker.SendLocalizedMessage(1072841, $"#{bwr.ClilocEntry}");
|
||||||
|
bwr.NewAbility.OnHit(attacker, defender, damage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.OnHit(attacker, defender, damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
_newAttack.Remove(attacker);
|
||||||
|
ClearCurrentAbility(attacker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnMiss(Mobile attacker, Mobile defender)
|
||||||
|
{
|
||||||
|
if (_newAttack.TryGetValue(attacker, out var bwr))
|
||||||
|
{
|
||||||
|
bwr.NewAbility.OnMiss(attacker, defender);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.OnMiss(attacker, defender);
|
||||||
|
}
|
||||||
|
|
||||||
|
_newAttack.Remove(attacker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,18 +11,7 @@ namespace Server.Items
|
||||||
private static readonly Dictionary<Mobile, InternalTimer> _table = new();
|
private static readonly Dictionary<Mobile, InternalTimer> _table = new();
|
||||||
|
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
public override bool CheckSkills(Mobile from)
|
|
||||||
{
|
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063347, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,24 @@ namespace Server.Items
|
||||||
public override int BaseMana => 25;
|
public override int BaseMana => 25;
|
||||||
public override double DamageScalar => 1.5;
|
public override double DamageScalar => 1.5;
|
||||||
|
|
||||||
|
public virtual double GetRequiredTactics(Mobile from)
|
||||||
|
{
|
||||||
|
if (from.Weapon is BaseWeapon weapon)
|
||||||
|
{
|
||||||
|
if (weapon.PrimaryAbility == this)
|
||||||
|
{
|
||||||
|
return 30.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weapon.SecondaryAbility == this)
|
||||||
|
{
|
||||||
|
return 60.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 200.0;
|
||||||
|
}
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,7 @@ namespace Server.Items
|
||||||
private static readonly Dictionary<Mobile, DefenseMasteryInfo> _table = new();
|
private static readonly Dictionary<Mobile, DefenseMasteryInfo> _table = new();
|
||||||
|
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
public override bool CheckSkills(Mobile from)
|
|
||||||
{
|
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063347, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
@ -40,8 +29,7 @@ namespace Server.Items
|
||||||
|
|
||||||
var modifier =
|
var modifier =
|
||||||
(int)(30.0 *
|
(int)(30.0 *
|
||||||
((Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value) -
|
((Math.Max(attacker.Skills.Bushido.Value, attacker.Skills.Ninjitsu.Value) - 50.0) / 70.0));
|
||||||
50.0) / 70.0));
|
|
||||||
|
|
||||||
if (_table.TryGetValue(attacker, out var info))
|
if (_table.TryGetValue(attacker, out var info))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,33 +12,25 @@ namespace Server.Items
|
||||||
|
|
||||||
public override int BaseMana => 20;
|
public override int BaseMana => 20;
|
||||||
|
|
||||||
// No longer active in pub21:
|
public override bool RequiresTactics(Mobile from) => from.Weapon is not BaseWeapon { Skill: SkillName.Wrestling };
|
||||||
/*public override bool CheckSkills( Mobile from )
|
|
||||||
|
// Disarm is special. Doesnt need tactics when wresling and tactics need is lower than fighting skill.
|
||||||
|
public virtual double GetRequiredTactics(Mobile from)
|
||||||
{
|
{
|
||||||
if (!base.CheckSkills( from ))
|
if (from.Weapon is BaseWeapon weapon)
|
||||||
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;
|
if (weapon.PrimaryAbility == this)
|
||||||
|
{
|
||||||
|
return 30.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weapon.SecondaryAbility == this)
|
||||||
|
{
|
||||||
|
return 60.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return weapon.Skill != SkillName.Wrestling;
|
return 200.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
|
|
@ -52,7 +44,7 @@ namespace Server.Items
|
||||||
|
|
||||||
var toDisarm = defender.FindItemOnLayer(Layer.OneHanded);
|
var toDisarm = defender.FindItemOnLayer(Layer.OneHanded);
|
||||||
|
|
||||||
if (toDisarm?.Movable == false)
|
if (toDisarm?.Movable != false)
|
||||||
{
|
{
|
||||||
toDisarm = defender.FindItemOnLayer(Layer.TwoHanded);
|
toDisarm = defender.FindItemOnLayer(Layer.TwoHanded);
|
||||||
}
|
}
|
||||||
|
|
@ -63,7 +55,7 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
|
attacker.SendLocalizedMessage(1004001); // You cannot disarm your opponent.
|
||||||
}
|
}
|
||||||
else if (!Core.ML && toDisarm == null || toDisarm is BaseShield || toDisarm is Spellbook)
|
else if (!Core.ML && toDisarm == null || toDisarm is BaseShield or Spellbook)
|
||||||
{
|
{
|
||||||
attacker.SendLocalizedMessage(1060849); // Your target is already unarmed!
|
attacker.SendLocalizedMessage(1060849); // Your target is already unarmed!
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +69,8 @@ namespace Server.Items
|
||||||
|
|
||||||
pack.DropItem(toDisarm);
|
pack.DropItem(toDisarm);
|
||||||
|
|
||||||
|
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.NoRearm, 1075637, BlockEquipDuration, defender));
|
||||||
|
|
||||||
BaseWeapon.BlockEquip(defender, BlockEquipDuration);
|
BaseWeapon.BlockEquip(defender, BlockEquipDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ namespace Server.Items
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attacker.Mounted && (!(attacker.Weapon is Lance) || !(defender.Weapon is Lance))
|
// TODO: Should there be a message here?
|
||||||
) // TODO: Should there be a message here?
|
if (attacker.Mounted && (attacker.Weapon is not Lance || defender.Weapon is not Lance))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -101,12 +101,9 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
playerMobile.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, true);
|
playerMobile.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, true);
|
||||||
}
|
}
|
||||||
else if (Core.ML && attacker is BaseCreature bc)
|
else if (Core.ML && attacker is BaseCreature { ControlMaster: PlayerMobile pm })
|
||||||
{
|
{
|
||||||
if (bc.ControlMaster is PlayerMobile pm)
|
pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false);
|
||||||
{
|
|
||||||
pm.SetMountBlock(BlockMountType.DismountRecovery, RemountDelay, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!attacker.Mounted)
|
if (!attacker.Mounted)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Server.Items
|
namespace Server.Items
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -7,17 +9,8 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
public override bool CheckSkills(Mobile from)
|
public override bool RequiresTactics(Mobile from) => false;
|
||||||
{
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063347, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,8 @@ namespace Server.Items
|
||||||
|
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
public override bool CheckSkills(Mobile from)
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
{
|
public override SkillName GetSecondarySkillName(Mobile from) => SkillName.Ninjitsu;
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063352, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
@ -44,8 +35,8 @@ namespace Server.Items
|
||||||
|
|
||||||
timer = new DualWieldTimer(
|
timer = new DualWieldTimer(
|
||||||
attacker,
|
attacker,
|
||||||
(int)(20.0 + 3.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 7.0)
|
(int)(20.0 + 3.0 * (attacker.Skills.Ninjitsu.Value - 50.0) / 7.0) // 20-50 % increase
|
||||||
); // 20-50 % increase
|
);
|
||||||
|
|
||||||
timer.Start();
|
timer.Start();
|
||||||
Registry.Add(attacker, timer);
|
Registry.Add(attacker, timer);
|
||||||
|
|
@ -55,8 +46,7 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
private readonly Mobile m_Owner;
|
private readonly Mobile m_Owner;
|
||||||
|
|
||||||
public DualWieldTimer(Mobile owner, int bonusSwingSpeed)
|
public DualWieldTimer(Mobile owner, int bonusSwingSpeed) : base(TimeSpan.FromSeconds(6.0))
|
||||||
: base(TimeSpan.FromSeconds(6.0))
|
|
||||||
{
|
{
|
||||||
m_Owner = owner;
|
m_Owner = owner;
|
||||||
BonusSwingSpeed = bonusSwingSpeed;
|
BonusSwingSpeed = bonusSwingSpeed;
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,7 @@ namespace Server.Items
|
||||||
public static Dictionary<Mobile, FeintTimer> Registry { get; } = new();
|
public static Dictionary<Mobile, FeintTimer> Registry { get; } = new();
|
||||||
|
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
public override bool CheckSkills(Mobile from)
|
|
||||||
{
|
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063347, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
@ -46,10 +35,8 @@ namespace Server.Items
|
||||||
|
|
||||||
timer = new FeintTimer(
|
timer = new FeintTimer(
|
||||||
defender,
|
defender,
|
||||||
(int)(20.0 + 3.0 * (Math.Max(
|
(int)(20.0 + 3.0 *
|
||||||
attacker.Skills.Ninjitsu.Value,
|
(Math.Max(attacker.Skills.Ninjitsu.Value, attacker.Skills.Bushido.Value) - 50.0) / 7.0)
|
||||||
attacker.Skills.Bushido.Value
|
|
||||||
) - 50.0) / 7.0)
|
|
||||||
); // 20-50 % decrease
|
); // 20-50 % decrease
|
||||||
|
|
||||||
timer.Start();
|
timer.Start();
|
||||||
|
|
|
||||||
164
Projects/UOContent/Items/Weapons/Abilities/ForceArrow.cs
Normal file
164
Projects/UOContent/Items/Weapons/Abilities/ForceArrow.cs
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
using Server.Spells;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Server.Items
|
||||||
|
{
|
||||||
|
public class ForceArrow : WeaponAbility
|
||||||
|
{
|
||||||
|
public override int BaseMana => 20;
|
||||||
|
|
||||||
|
public override bool RequiresTactics(Mobile from) => false;
|
||||||
|
|
||||||
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
|
{
|
||||||
|
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearCurrentAbility(attacker);
|
||||||
|
|
||||||
|
attacker.SendLocalizedMessage(1074381); // You fire an arrow of pure force.
|
||||||
|
defender.SendLocalizedMessage(1074382); // You are struck by a force arrow!
|
||||||
|
|
||||||
|
if (0.4 > Utility.RandomDouble())
|
||||||
|
{
|
||||||
|
defender.Combatant = null;
|
||||||
|
defender.Warmode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ForceArrowInfo info = GetInfo(attacker, defender);
|
||||||
|
|
||||||
|
if (info == null)
|
||||||
|
{
|
||||||
|
BeginForceArrow(attacker, defender);
|
||||||
|
}
|
||||||
|
else if (info.Timer.Running)
|
||||||
|
{
|
||||||
|
info.Timer.IncreaseExpiration();
|
||||||
|
|
||||||
|
BuffInfo.RemoveBuff(defender, BuffIcon.ForceArrow);
|
||||||
|
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.ForceArrow, 1151285, 1151286, info.DefenseChanceMalus.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defender.Spell is Spell spell && spell.IsCasting)
|
||||||
|
{
|
||||||
|
spell.Disturb(DisturbType.Hurt, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<Mobile, List<ForceArrowInfo>> _table = new Dictionary<Mobile, List<ForceArrowInfo>>();
|
||||||
|
|
||||||
|
public static void BeginForceArrow(Mobile attacker, Mobile defender)
|
||||||
|
{
|
||||||
|
ForceArrowInfo info = new ForceArrowInfo(attacker, defender);
|
||||||
|
info.Timer = new ForceArrowTimer(info);
|
||||||
|
|
||||||
|
if (_table.TryGetValue(attacker, out var list))
|
||||||
|
{
|
||||||
|
list.Add(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_table.Add(attacker, new List<ForceArrowInfo>() { info });
|
||||||
|
}
|
||||||
|
|
||||||
|
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.ForceArrow, 1151285, 1151286, info.DefenseChanceMalus.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EndForceArrow(ForceArrowInfo info)
|
||||||
|
{
|
||||||
|
if (info == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mobile attacker = info.Attacker;
|
||||||
|
|
||||||
|
if (_table.TryGetValue(attacker, out var list) && list.Remove(info) && list.Count == 0)
|
||||||
|
{
|
||||||
|
_table.Remove(attacker);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuffInfo.RemoveBuff(info.Defender, BuffIcon.ForceArrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool HasForceArrow(Mobile attacker, Mobile defender)
|
||||||
|
{
|
||||||
|
if (_table.TryGetValue(attacker, out var list))
|
||||||
|
{
|
||||||
|
foreach (ForceArrowInfo info in list)
|
||||||
|
{
|
||||||
|
if (info.Defender == defender)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ForceArrowInfo GetInfo(Mobile attacker, Mobile defender)
|
||||||
|
{
|
||||||
|
if (_table.TryGetValue(attacker,out var list))
|
||||||
|
{
|
||||||
|
foreach (ForceArrowInfo info in list)
|
||||||
|
{
|
||||||
|
if (info.Defender == defender)
|
||||||
|
{
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ForceArrowInfo
|
||||||
|
{
|
||||||
|
public Mobile Attacker { get; }
|
||||||
|
public Mobile Defender { get; }
|
||||||
|
public ForceArrowTimer Timer { get; set; }
|
||||||
|
public int DefenseChanceMalus { get; set; }
|
||||||
|
|
||||||
|
public ForceArrowInfo(Mobile attacker, Mobile defender)
|
||||||
|
{
|
||||||
|
Attacker = attacker;
|
||||||
|
Defender = defender;
|
||||||
|
DefenseChanceMalus = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ForceArrowTimer : Timer
|
||||||
|
{
|
||||||
|
private readonly ForceArrowInfo _info;
|
||||||
|
private DateTime _expires;
|
||||||
|
|
||||||
|
public ForceArrowTimer(ForceArrowInfo info)
|
||||||
|
: base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1))
|
||||||
|
{
|
||||||
|
_info = info;
|
||||||
|
_expires = Core.Now + TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnTick()
|
||||||
|
{
|
||||||
|
if (_expires < Core.Now)
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
EndForceArrow(_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void IncreaseExpiration()
|
||||||
|
{
|
||||||
|
_expires += TimeSpan.FromSeconds(2);
|
||||||
|
_info.DefenseChanceMalus += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
111
Projects/UOContent/Items/Weapons/Abilities/ForceOfNature.cs
Normal file
111
Projects/UOContent/Items/Weapons/Abilities/ForceOfNature.cs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Server.Items
|
||||||
|
{
|
||||||
|
public class ForceOfNature : WeaponAbility
|
||||||
|
{
|
||||||
|
public override int BaseMana => 35;
|
||||||
|
|
||||||
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
|
{
|
||||||
|
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearCurrentAbility(attacker);
|
||||||
|
|
||||||
|
attacker.SendLocalizedMessage(1074374); // You attack your enemy with the force of nature!
|
||||||
|
defender.SendLocalizedMessage(1074375); // You are assaulted with great force!
|
||||||
|
|
||||||
|
defender.PlaySound(0x22F);
|
||||||
|
defender.FixedParticles(0x36CB, 1, 9, 9911, 67, 5, EffectLayer.Head);
|
||||||
|
defender.FixedParticles(0x374A, 1, 17, 9502, 1108, 4, (EffectLayer)255);
|
||||||
|
|
||||||
|
Remove(attacker);
|
||||||
|
|
||||||
|
ForceOfNatureTimer t = new ForceOfNatureTimer(attacker, defender);
|
||||||
|
t.Start();
|
||||||
|
|
||||||
|
_table[attacker] = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Dictionary<Mobile, ForceOfNatureTimer> _table = new Dictionary<Mobile, ForceOfNatureTimer>();
|
||||||
|
|
||||||
|
public static void Remove(Mobile m)
|
||||||
|
{
|
||||||
|
if (_table.Remove(m, out var timer))
|
||||||
|
{
|
||||||
|
timer.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void OnHit(Mobile from, Mobile target)
|
||||||
|
{
|
||||||
|
if (_table.TryGetValue(from,out var t))
|
||||||
|
{
|
||||||
|
t.Hits++;
|
||||||
|
t.LastHit = Core.Now;
|
||||||
|
|
||||||
|
if (t.Hits % 12 == 0)
|
||||||
|
{
|
||||||
|
int duration = target.Skills[SkillName.MagicResist].Value >= 90.0 ? 1 : 2;
|
||||||
|
target.Paralyze(TimeSpan.FromSeconds(duration));
|
||||||
|
|
||||||
|
target.FixedEffect(0x376A, 9, 32);
|
||||||
|
target.PlaySound(0x204);
|
||||||
|
|
||||||
|
t.Hits = 0;
|
||||||
|
|
||||||
|
from.SendLocalizedMessage(1004013); // You successfully stun your opponent!
|
||||||
|
target.SendLocalizedMessage(1004014); // You have been stunned!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double GetDamageScalar(Mobile from, Mobile target)
|
||||||
|
{
|
||||||
|
if (_table.TryGetValue(from, out var t) && t.Target == target)
|
||||||
|
{
|
||||||
|
var bonus = Math.Min(100, Math.Max(50, from.Str - 50));
|
||||||
|
return (100.0 + bonus) / 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ForceOfNatureTimer : Timer
|
||||||
|
{
|
||||||
|
public Mobile Target { get; }
|
||||||
|
public Mobile From { get; }
|
||||||
|
public int Hits { get; set; }
|
||||||
|
public DateTime LastHit { get; set; }
|
||||||
|
|
||||||
|
public ForceOfNatureTimer(Mobile from, Mobile target)
|
||||||
|
: base(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1))
|
||||||
|
{
|
||||||
|
Target = target;
|
||||||
|
From = from;
|
||||||
|
Hits = 1;
|
||||||
|
LastHit = Core.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnTick()
|
||||||
|
{
|
||||||
|
if (!From.Alive || !Target.Alive || Target.Map != From.Map || Target.GetDistanceToSqrt(From.Location) > 10 || LastHit + TimeSpan.FromSeconds(20) < Core.Now || Index > 36)
|
||||||
|
{
|
||||||
|
Remove(From);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Index == 1)
|
||||||
|
{
|
||||||
|
int damage = Utility.RandomMinMax(15, 35);
|
||||||
|
|
||||||
|
AOS.Damage(From, From, damage, false, 0, 0, 0, 0, 0, 0, 100, false, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,18 +12,8 @@ namespace Server.Items
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
public static Dictionary<Mobile, FrenziedWirlwindTimer> Registry { get; } = new();
|
public static Dictionary<Mobile, FrenziedWirlwindTimer> Registry { get; } = new();
|
||||||
|
public override bool RequiresTactics(Mobile from) => false;
|
||||||
public override bool CheckSkills(Mobile from)
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
{
|
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0 && GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063347, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Server.Items
|
||||||
|
|
||||||
ClearCurrentAbility(attacker);
|
ClearCurrentAbility(attacker);
|
||||||
|
|
||||||
if (!(attacker.Weapon is BaseWeapon weapon))
|
if (attacker.Weapon is not BaseWeapon weapon)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
58
Projects/UOContent/Items/Weapons/Abilities/LightningArrow.cs
Normal file
58
Projects/UOContent/Items/Weapons/Abilities/LightningArrow.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
using Server.Spells;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Server.Items
|
||||||
|
{
|
||||||
|
public class LightningArrow : WeaponAbility
|
||||||
|
{
|
||||||
|
public override int BaseMana => 20;
|
||||||
|
|
||||||
|
//TODO - add ConsumeAmmo on weaponabilities
|
||||||
|
// public override bool ConsumeAmmo => false;
|
||||||
|
|
||||||
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
|
{
|
||||||
|
if (!Validate(attacker))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearCurrentAbility(attacker);
|
||||||
|
|
||||||
|
Map map = attacker.Map;
|
||||||
|
|
||||||
|
if (map == null || attacker.Weapon is not BaseWeapon weapon || !CheckMana(attacker, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Mobile> targets = new List<Mobile>();
|
||||||
|
IPooledEnumerable eable = defender.GetMobilesInRange(5);
|
||||||
|
|
||||||
|
foreach (Mobile m in eable)
|
||||||
|
{
|
||||||
|
if (m != defender && m != attacker && SpellHelper.ValidIndirectTarget(attacker, m) && m?.Deleted == false &&
|
||||||
|
m.Map == attacker.Map && m.Alive && attacker.CanSee(m) && attacker.CanBeHarmful(m) &&
|
||||||
|
attacker.InRange(m, weapon.MaxRange) && attacker.InLOS(m))
|
||||||
|
{
|
||||||
|
targets.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eable.Free();
|
||||||
|
defender.BoltEffect(0);
|
||||||
|
|
||||||
|
var mobilesLeft = Math.Min(targets.Count, 2);
|
||||||
|
while (mobilesLeft-- > 0)
|
||||||
|
{
|
||||||
|
var index = Utility.Random(targets.Count);
|
||||||
|
var m = targets[index];
|
||||||
|
targets.RemoveAt(index);
|
||||||
|
|
||||||
|
m.BoltEffect(0);
|
||||||
|
AOS.Damage(m, attacker, Utility.RandomMinMax(29, 40), 0, 0, 0, 0, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,17 +9,8 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
public override bool CheckSkills(Mobile from)
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
{
|
public override SkillName GetSecondarySkillName(Mobile from) => SkillName.Bushido;
|
||||||
if (GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1070768, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
|
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,7 @@ namespace Server.Items
|
||||||
|
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
// No longer active in pub21:
|
// When using Wrestling, tactics isnt needed.
|
||||||
/*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) =>
|
public override bool RequiresTactics(Mobile from) =>
|
||||||
!(from.Weapon is BaseWeapon weapon && weapon.Skill == SkillName.Wrestling);
|
!(from.Weapon is BaseWeapon weapon && weapon.Skill == SkillName.Wrestling);
|
||||||
|
|
||||||
|
|
|
||||||
93
Projects/UOContent/Items/Weapons/Abilities/PsychicAttack.cs
Normal file
93
Projects/UOContent/Items/Weapons/Abilities/PsychicAttack.cs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Server.Items
|
||||||
|
{
|
||||||
|
public class PsychicAttack : WeaponAbility
|
||||||
|
{
|
||||||
|
public static Dictionary<Mobile, PsychicAttackTimer> Registry { get; } = new();
|
||||||
|
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(1074383); // Your shot sends forth a wave of psychic energy.
|
||||||
|
defender.SendLocalizedMessage(1074384); // Your mind is attacked by psychic force!
|
||||||
|
|
||||||
|
defender.FixedParticles(0x3789, 10, 25, 5032, EffectLayer.Head);
|
||||||
|
defender.PlaySound(0x1F8);
|
||||||
|
|
||||||
|
if (Registry.TryGetValue(defender, out var timer))
|
||||||
|
{
|
||||||
|
if (!timer.DoneIncrease)
|
||||||
|
{
|
||||||
|
timer.SpellDamageMalus *= 2;
|
||||||
|
timer.ManaCostMalus *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timer = new PsychicAttackTimer(defender);
|
||||||
|
timer.Start();
|
||||||
|
Registry.Add(defender, timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
BuffInfo.RemoveBuff(defender, BuffIcon.PsychicAttack);
|
||||||
|
|
||||||
|
string args = $"{timer.SpellDamageMalus}\t{timer.ManaCostMalus}";
|
||||||
|
BuffInfo.AddBuff(defender, new BuffInfo(BuffIcon.PsychicAttack, 1151296, 1151297, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RemoveEffects(Mobile defender)
|
||||||
|
{
|
||||||
|
if (defender == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BuffInfo.RemoveBuff(defender, BuffIcon.PsychicAttack);
|
||||||
|
|
||||||
|
Registry.Remove(defender);
|
||||||
|
|
||||||
|
defender.SendLocalizedMessage(1150292); // You recover from the effects of the psychic attack.
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PsychicAttackTimer : Timer
|
||||||
|
{
|
||||||
|
private readonly Mobile _defender;
|
||||||
|
private int _spellDamageMalus;
|
||||||
|
private int _manaCostMalus;
|
||||||
|
|
||||||
|
public int SpellDamageMalus
|
||||||
|
{
|
||||||
|
get => _spellDamageMalus;
|
||||||
|
set { _spellDamageMalus = value; DoneIncrease = true; }
|
||||||
|
}
|
||||||
|
public int ManaCostMalus
|
||||||
|
{
|
||||||
|
get => _manaCostMalus;
|
||||||
|
set { _manaCostMalus = value; DoneIncrease = true; }
|
||||||
|
}
|
||||||
|
public bool DoneIncrease { get; private set; }
|
||||||
|
|
||||||
|
public PsychicAttackTimer(Mobile defender) : base(TimeSpan.FromSeconds(10))
|
||||||
|
{
|
||||||
|
_defender = defender;
|
||||||
|
_spellDamageMalus = 15;
|
||||||
|
_manaCostMalus = 15;
|
||||||
|
DoneIncrease = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnTick()
|
||||||
|
{
|
||||||
|
RemoveEffects(_defender);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,18 +13,8 @@ namespace Server.Items
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
|
|
||||||
public override bool RequiresSE => true;
|
public override bool RequiresSE => true;
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
public override bool CheckSkills(Mobile from)
|
public override SkillName GetSecondarySkillName(Mobile from) => SkillName.Bushido;
|
||||||
{
|
|
||||||
if (GetSkill(from, SkillName.Bushido) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Bushido skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1070768, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
46
Projects/UOContent/Items/Weapons/Abilities/SerpentArrow.cs
Normal file
46
Projects/UOContent/Items/Weapons/Abilities/SerpentArrow.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
namespace Server.Items
|
||||||
|
{
|
||||||
|
public class SerpentArrow : WeaponAbility
|
||||||
|
{
|
||||||
|
public override int BaseMana => 25;
|
||||||
|
|
||||||
|
// Serpent arrow is used only as secondary ability on "Elven composite longbow" so needed skill is always 60, but for sure we will use GetRequiredSecondarySkill
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
|
public override double GetRequiredSecondarySkill(Mobile from) => 60;
|
||||||
|
public override SkillName GetSecondarySkillName(Mobile from) => SkillName.Poisoning;
|
||||||
|
|
||||||
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
|
{
|
||||||
|
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearCurrentAbility(attacker);
|
||||||
|
|
||||||
|
defender.SendLocalizedMessage(1112369); // You have been poisoned by a lethal arrow!
|
||||||
|
|
||||||
|
int level;
|
||||||
|
|
||||||
|
if (attacker.InRange(defender, 2))
|
||||||
|
{
|
||||||
|
level = attacker.Skills.Poisoning.Fixed / 2 switch
|
||||||
|
{
|
||||||
|
>= 1000 => 3,
|
||||||
|
> 850 => 2,
|
||||||
|
> 650 => 1,
|
||||||
|
_ => 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
level = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
defender.ApplyPoison(attacker, Poison.GetPoison(level));
|
||||||
|
|
||||||
|
defender.FixedParticles(0x374A, 10, 15, 5021, EffectLayer.Waist);
|
||||||
|
defender.PlaySound(0x474);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,10 @@ namespace Server.Items
|
||||||
|
|
||||||
public override bool RequiresTactics(Mobile from) => false;
|
public override bool RequiresTactics(Mobile from) => false;
|
||||||
|
|
||||||
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
|
public override double GetRequiredSecondarySkill(Mobile from) => 80;
|
||||||
|
public override SkillName GetSecondarySkillName(Mobile from) => SkillName.Stealth;
|
||||||
|
|
||||||
public override bool CheckSkills(Mobile from)
|
public override bool CheckSkills(Mobile from)
|
||||||
{
|
{
|
||||||
if (!base.CheckSkills(from))
|
if (!base.CheckSkills(from))
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,9 @@ namespace Server.Items
|
||||||
public override int BaseMana => 30;
|
public override int BaseMana => 30;
|
||||||
public override double DamageScalar => 1.2;
|
public override double DamageScalar => 1.2;
|
||||||
|
|
||||||
public override bool CheckSkills(Mobile from)
|
public override bool RequiresSecondarySkill(Mobile from) => true;
|
||||||
{
|
public override SkillName GetSecondarySkillName(Mobile from) => SkillName.Ninjitsu;
|
||||||
if (GetSkill(from, SkillName.Ninjitsu) < 50.0)
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
|
|
||||||
from.SendLocalizedMessage(1063352, "50");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CheckSkills(from);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ namespace Server.Items
|
||||||
new DualWield(),
|
new DualWield(),
|
||||||
new DoubleShot(),
|
new DoubleShot(),
|
||||||
new ArmorPierce(),
|
new ArmorPierce(),
|
||||||
null,
|
new Bladeweave(),
|
||||||
null,
|
new ForceArrow(),
|
||||||
null,
|
new LightningArrow(),
|
||||||
null,
|
new PsychicAttack(),
|
||||||
null,
|
new SerpentArrow(),
|
||||||
null,
|
new ForceOfNature(),
|
||||||
new Disrobe()
|
new Disrobe()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -109,16 +109,60 @@ namespace Server.Items
|
||||||
|
|
||||||
public virtual bool RequiresTactics(Mobile from) => true;
|
public virtual bool RequiresTactics(Mobile from) => true;
|
||||||
|
|
||||||
|
public virtual bool RequiresSecondarySkill(Mobile from) => false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return primary skill for ability. Default 70/90
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public virtual double GetRequiredSkill(Mobile from)
|
public virtual double GetRequiredSkill(Mobile from)
|
||||||
{
|
{
|
||||||
if (from.Weapon is BaseWeapon weapon)
|
if (from.Weapon is BaseWeapon weapon)
|
||||||
{
|
{
|
||||||
if (weapon.PrimaryAbility == this)
|
if (weapon.PrimaryAbility == this || weapon.PrimaryAbility == Bladeweave)
|
||||||
{
|
{
|
||||||
return 70.0;
|
return 70.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weapon.SecondaryAbility == this)
|
if (weapon.SecondaryAbility == this || weapon.SecondaryAbility == Bladeweave)
|
||||||
|
{
|
||||||
|
return 90.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 200.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns secondary skill for Ability. Default 50.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual double GetRequiredSecondarySkill(Mobile from) => 50.0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return secondary skillName. Default bushido/ninjitsu
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual SkillName GetSecondarySkillName(Mobile from) => from.Skills[SkillName.Ninjitsu].Base > from.Skills[SkillName.Bushido].Base ? SkillName.Ninjitsu : SkillName.Bushido;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns tactics needed for Ability. Default 70/90.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="from"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public virtual double GetRequiredTactics(Mobile from)
|
||||||
|
{
|
||||||
|
if (from.Weapon is BaseWeapon weapon)
|
||||||
|
{
|
||||||
|
if (weapon.PrimaryAbility == this || weapon.PrimaryAbility == Bladeweave)
|
||||||
|
{
|
||||||
|
return 70.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weapon.SecondaryAbility == this || weapon.SecondaryAbility == Bladeweave)
|
||||||
{
|
{
|
||||||
return 90.0;
|
return 90.0;
|
||||||
}
|
}
|
||||||
|
|
@ -184,13 +228,32 @@ namespace Server.Items
|
||||||
var reqSkill = GetRequiredSkill(from);
|
var reqSkill = GetRequiredSkill(from);
|
||||||
var reqTactics = Core.ML && RequiresTactics(from);
|
var reqTactics = Core.ML && RequiresTactics(from);
|
||||||
|
|
||||||
if (Core.ML && reqTactics && from.Skills.Tactics.Base < reqSkill)
|
if (reqTactics && from.Skills.Tactics.Base < GetRequiredTactics(from))
|
||||||
{
|
{
|
||||||
// You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
|
// You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
|
||||||
from.SendLocalizedMessage(1079308, reqSkill.ToString());
|
from.SendLocalizedMessage(1079308, reqSkill.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var reqSecondarySkill = GetRequiredSecondarySkill(from);
|
||||||
|
SkillName secondarySkill = GetSecondarySkillName(from);
|
||||||
|
|
||||||
|
if (RequiresSecondarySkill(from) && from.Skills[secondarySkill].Base < reqSecondarySkill)
|
||||||
|
{
|
||||||
|
int loc = GetSkillLocalization(secondarySkill);
|
||||||
|
|
||||||
|
if (loc == 1060184)
|
||||||
|
{
|
||||||
|
from.SendLocalizedMessage(loc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
from.SendLocalizedMessage(loc, reqSecondarySkill.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (skill?.Base >= reqSkill)
|
if (skill?.Base >= reqSkill)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -207,19 +270,22 @@ namespace Server.Items
|
||||||
}
|
}
|
||||||
/* </UBWS> */
|
/* </UBWS> */
|
||||||
|
|
||||||
if (reqTactics)
|
// You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
|
||||||
{
|
from.SendLocalizedMessage(1060182, reqSkill.ToString());
|
||||||
// You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
|
|
||||||
from.SendLocalizedMessage(1079308, reqSkill.ToString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// You need ~1_SKILL_REQUIREMENT~ weapon skill to perform that attack
|
|
||||||
from.SendLocalizedMessage(1060182, reqSkill.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
private int GetSkillLocalization(SkillName skill)
|
||||||
|
{
|
||||||
|
return skill switch
|
||||||
|
{
|
||||||
|
SkillName.Bushido => 1063347, // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
||||||
|
SkillName.Ninjitsu => 1063347, // You need ~1_SKILL_REQUIREMENT~ Bushido or Ninjitsu skill to perform that attack!
|
||||||
|
SkillName.Poisoning => 1060184, // You lack the required poisoning to perform that attack
|
||||||
|
_ => 1157351 // You need ~1_SKILL_REQUIREMENT~ weapon and tactics skill to perform that attack
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual bool CheckSkills(Mobile from) => CheckWeaponSkill(from);
|
public virtual bool CheckSkills(Mobile from) => CheckWeaponSkill(from);
|
||||||
|
|
||||||
|
|
@ -420,10 +486,7 @@ namespace Server.Items
|
||||||
{
|
{
|
||||||
private readonly Mobile m_Mobile;
|
private readonly Mobile m_Mobile;
|
||||||
|
|
||||||
public WeaponAbilityTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0))
|
public WeaponAbilityTimer(Mobile from) : base(TimeSpan.FromSeconds(3.0)) => m_Mobile = from;
|
||||||
{
|
|
||||||
m_Mobile = from;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnTick()
|
protected override void OnTick()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Server.Items
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(attacker.Weapon is BaseWeapon weapon))
|
if (attacker.Weapon is not BaseWeapon weapon)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1024,6 +1024,7 @@ namespace Server.Items
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmolatingWeaponSpell.StopImmolating(this);
|
ImmolatingWeaponSpell.StopImmolating(this);
|
||||||
|
ForceOfNature.Remove(m);
|
||||||
|
|
||||||
m.CheckStatTimers();
|
m.CheckStatTimers();
|
||||||
|
|
||||||
|
|
@ -1157,6 +1158,13 @@ namespace Server.Items
|
||||||
|
|
||||||
bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance);
|
bonus = AosAttributes.GetValue(defender, AosAttribute.DefendChance);
|
||||||
|
|
||||||
|
var info = ForceArrow.GetInfo(attacker, defender);
|
||||||
|
|
||||||
|
if (info != null && info.Defender == defender)
|
||||||
|
{
|
||||||
|
bonus -= info.DefenseChanceMalus;
|
||||||
|
}
|
||||||
|
|
||||||
if (DivineFurySpell.UnderEffect(defender))
|
if (DivineFurySpell.UnderEffect(defender))
|
||||||
{
|
{
|
||||||
bonus -= 20; // defender loses 20% bonus when they're under divine fury
|
bonus -= 20; // defender loses 20% bonus when they're under divine fury
|
||||||
|
|
@ -1662,6 +1670,8 @@ namespace Server.Items
|
||||||
percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100;
|
percentageBonus += (int)(move.GetDamageScalar(attacker, defender) * 100) - 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
percentageBonus += (int)(ForceOfNature.GetDamageScalar(attacker, defender) * 100) - 100;
|
||||||
|
|
||||||
percentageBonus += (int)(damageBonus * 100) - 100;
|
percentageBonus += (int)(damageBonus * 100) - 100;
|
||||||
|
|
||||||
var cs = CheckSlayers(attacker, defender);
|
var cs = CheckSlayers(attacker, defender);
|
||||||
|
|
@ -1864,7 +1874,10 @@ namespace Server.Items
|
||||||
move = null;
|
move = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var ignoreArmor = a is ArmorIgnore || move?.IgnoreArmor(attacker) == true;
|
var ignoreArmor = a is ArmorIgnore ||
|
||||||
|
move?.IgnoreArmor(attacker) == true ||
|
||||||
|
Bladeweave.BladeWeaving(attacker, out var bladeweavingAbi) &&
|
||||||
|
bladeweavingAbi is ArmorIgnore;
|
||||||
|
|
||||||
var damageGiven = AOS.Damage(
|
var damageGiven = AOS.Damage(
|
||||||
defender,
|
defender,
|
||||||
|
|
@ -1981,8 +1994,8 @@ namespace Server.Items
|
||||||
mobile.LocalOverheadMessage(
|
mobile.LocalOverheadMessage(
|
||||||
MessageType.Regular,
|
MessageType.Regular,
|
||||||
0x3B2,
|
0x3B2,
|
||||||
1061121
|
1061121 // Your equipment is severely damaged.
|
||||||
); // Your equipment is severely damaged.
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2101,6 +2114,8 @@ namespace Server.Items
|
||||||
a?.OnHit(attacker, defender, damage);
|
a?.OnHit(attacker, defender, damage);
|
||||||
move?.OnHit(attacker, defender, damage);
|
move?.OnHit(attacker, defender, damage);
|
||||||
|
|
||||||
|
ForceOfNature.OnHit(attacker, defender);
|
||||||
|
|
||||||
if (defender is IHonorTarget it)
|
if (defender is IHonorTarget it)
|
||||||
{
|
{
|
||||||
it.ReceivedHonorContext?.OnTargetHit(attacker);
|
it.ReceivedHonorContext?.OnTargetHit(attacker);
|
||||||
|
|
@ -2142,6 +2157,11 @@ namespace Server.Items
|
||||||
// SDI bonus
|
// SDI bonus
|
||||||
damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage);
|
damageBonus += AosAttributes.GetValue(attacker, AosAttribute.SpellDamage);
|
||||||
|
|
||||||
|
if(PsychicAttack.Registry.TryGetValue(attacker,out var timer))
|
||||||
|
{
|
||||||
|
damageBonus -= timer.SpellDamageMalus;
|
||||||
|
}
|
||||||
|
|
||||||
var context = TransformationSpellHelper.GetContext(attacker);
|
var context = TransformationSpellHelper.GetContext(attacker);
|
||||||
|
|
||||||
if (context?.Spell is ReaperFormSpell spell)
|
if (context?.Spell is ReaperFormSpell spell)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Server.Items
|
||||||
public GnarledStaff() : base(0x13F8) => Weight = 3.0;
|
public GnarledStaff() : base(0x13F8) => Weight = 3.0;
|
||||||
|
|
||||||
public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow;
|
public override WeaponAbility PrimaryAbility => WeaponAbility.ConcussionBlow;
|
||||||
public override WeaponAbility SecondaryAbility => WeaponAbility.ParalyzingBlow;
|
public override WeaponAbility SecondaryAbility => WeaponAbility.ForceOfNature;
|
||||||
|
|
||||||
public override int AosStrengthReq => 20;
|
public override int AosStrengthReq => 20;
|
||||||
public override int AosMinDamage => 15;
|
public override int AosMinDamage => 15;
|
||||||
|
|
|
||||||
|
|
@ -228,57 +228,190 @@ namespace Server
|
||||||
{
|
{
|
||||||
DismountPrevention = 0x3E9,
|
DismountPrevention = 0x3E9,
|
||||||
NoRearm = 0x3EA,
|
NoRearm = 0x3EA,
|
||||||
|
//Currently, no 0x3EB or 0x3EC
|
||||||
// Currently, no 0x3EB or 0x3EC
|
NightSight = 0x3ED, //*
|
||||||
NightSight = 0x3ED, // *
|
|
||||||
DeathStrike,
|
DeathStrike,
|
||||||
EvilOmen,
|
EvilOmen,
|
||||||
UnknownStandingSwirl, // Which is healing throttle & Stamina throttle?
|
HonoredDebuff,
|
||||||
UnknownKneelingSword,
|
AchievePerfection,
|
||||||
DivineFury, // *
|
DivineFury, //*
|
||||||
EnemyOfOne, // *
|
EnemyOfOne, //*
|
||||||
HidingAndOrStealth, // *
|
HidingAndOrStealth, //*
|
||||||
ActiveMeditation, // *
|
ActiveMeditation, //*
|
||||||
BloodOathCaster, // *
|
BloodOathCaster, //*
|
||||||
BloodOathCurse, // *
|
BloodOathCurse, //*
|
||||||
CorpseSkin, // *
|
CorpseSkin, //*
|
||||||
Mindrot, // *
|
Mindrot, //*
|
||||||
PainSpike, // *
|
PainSpike, //*
|
||||||
Strangle,
|
Strangle,
|
||||||
GiftOfRenewal, // *
|
GiftOfRenewal, //*
|
||||||
AttuneWeapon, // *
|
AttuneWeapon, //*
|
||||||
Thunderstorm, // *
|
Thunderstorm, //*
|
||||||
EssenceOfWind, // *
|
EssenceOfWind, //*
|
||||||
EtherealVoyage, // *
|
EtherealVoyage, //*
|
||||||
GiftOfLife, // *
|
GiftOfLife, //*
|
||||||
ArcaneEmpowerment, // *
|
ArcaneEmpowerment, //*
|
||||||
MortalStrike,
|
MortalStrike,
|
||||||
ReactiveArmor, // *
|
ReactiveArmor, //*
|
||||||
Protection, // *
|
Protection, //*
|
||||||
ArchProtection,
|
ArchProtection,
|
||||||
MagicReflection, // *
|
MagicReflection, //*
|
||||||
Incognito, // *
|
Incognito, //*
|
||||||
Disguised,
|
Disguised,
|
||||||
AnimalForm,
|
AnimalForm,
|
||||||
Polymorph,
|
Polymorph,
|
||||||
Invisibility, // *
|
Invisibility, //*
|
||||||
Paralyze, // *
|
Paralyze, //*
|
||||||
Poison,
|
Poison,
|
||||||
Bleed,
|
Bleed,
|
||||||
Clumsy, // *
|
Clumsy, //*
|
||||||
FeebleMind, // *
|
FeebleMind, //*
|
||||||
Weaken, // *
|
Weaken, //*
|
||||||
Curse, // *
|
Curse, //*
|
||||||
MassCurse,
|
MassCurse,
|
||||||
Agility, // *
|
Agility, //*
|
||||||
Cunning, // *
|
Cunning, //*
|
||||||
Strength, // *
|
Strength, //*
|
||||||
Bless, // *
|
Bless, //*
|
||||||
Sleep,
|
Sleep,
|
||||||
StoneForm,
|
StoneForm,
|
||||||
SpellPlague,
|
SpellPlague,
|
||||||
SpellTrigger,
|
Berserk,
|
||||||
NetherBolt,
|
MassSleep,
|
||||||
Fly
|
Fly,
|
||||||
|
Inspire,
|
||||||
|
Invigorate,
|
||||||
|
Resilience,
|
||||||
|
Perseverance,
|
||||||
|
TribulationTarget,
|
||||||
|
DespairTarget,
|
||||||
|
FishPie = 0x426,
|
||||||
|
HitLowerAttack,
|
||||||
|
HitLowerDefense,
|
||||||
|
DualWield,
|
||||||
|
Block,
|
||||||
|
DefenseMastery,
|
||||||
|
DespairCaster,
|
||||||
|
Healing,
|
||||||
|
SpellFocusingBuff,
|
||||||
|
SpellFocusingDebuff,
|
||||||
|
RageFocusingDebuff,
|
||||||
|
RageFocusingBuff,
|
||||||
|
Warding,
|
||||||
|
TribulationCaster,
|
||||||
|
ForceArrow,
|
||||||
|
Disarm,
|
||||||
|
Surge,
|
||||||
|
Feint,
|
||||||
|
TalonStrike,
|
||||||
|
PsychicAttack,
|
||||||
|
ConsecrateWeapon,
|
||||||
|
GrapesOfWrath,
|
||||||
|
EnemyOfOneDebuff,
|
||||||
|
HorrificBeast,
|
||||||
|
LichForm,
|
||||||
|
VampiricEmbrace,
|
||||||
|
CurseWeapon,
|
||||||
|
ReaperForm,
|
||||||
|
ImmolatingWeapon,
|
||||||
|
Enchant,
|
||||||
|
HonorableExecution,
|
||||||
|
Confidence,
|
||||||
|
Evasion,
|
||||||
|
CounterAttack,
|
||||||
|
LightningStrike,
|
||||||
|
MomentumStrike,
|
||||||
|
OrangePetals,
|
||||||
|
RoseOfTrinsic,
|
||||||
|
PoisonImmunity,
|
||||||
|
Veterinary,
|
||||||
|
Perfection,
|
||||||
|
Honored,
|
||||||
|
ManaPhase,
|
||||||
|
FanDancerFanFire,
|
||||||
|
Rage,
|
||||||
|
Webbing,
|
||||||
|
MedusaStone,
|
||||||
|
TrueFear,
|
||||||
|
AuraOfNausea,
|
||||||
|
HowlOfCacophony,
|
||||||
|
GazeDespair,
|
||||||
|
HiryuPhysicalResistance,
|
||||||
|
RuneBeetleCorruption,
|
||||||
|
BloodwormAnemia,
|
||||||
|
RotwormBloodDisease,
|
||||||
|
SkillUseDelay,
|
||||||
|
FactionStatLoss,
|
||||||
|
HeatOfBattleStatus,
|
||||||
|
CriminalStatus,
|
||||||
|
ArmorPierce,
|
||||||
|
SplinteringEffect,
|
||||||
|
SwingSpeedDebuff,
|
||||||
|
WraithForm,
|
||||||
|
CityTradeDeal = 0x466,
|
||||||
|
HumilityDebuff = 0x467,
|
||||||
|
Spirituality,
|
||||||
|
Humility,
|
||||||
|
// Skill Masteries
|
||||||
|
Rampage,
|
||||||
|
Stagger, // Debuff
|
||||||
|
Toughness,
|
||||||
|
Thrust,
|
||||||
|
Pierce, // Debuff
|
||||||
|
PlayingTheOdds,
|
||||||
|
FocusedEye,
|
||||||
|
Onslaught, // Debuff
|
||||||
|
ElementalFury,
|
||||||
|
ElementalFuryDebuff, // Debuff
|
||||||
|
CalledShot,
|
||||||
|
Knockout,
|
||||||
|
SavingThrow,
|
||||||
|
Conduit,
|
||||||
|
EtherealBurst,
|
||||||
|
MysticWeapon,
|
||||||
|
ManaShield,
|
||||||
|
AnticipateHit,
|
||||||
|
Warcry,
|
||||||
|
Shadow,
|
||||||
|
WhiteTigerForm,
|
||||||
|
Bodyguard,
|
||||||
|
HeightenedSenses,
|
||||||
|
Tolerance,
|
||||||
|
DeathRay,
|
||||||
|
DeathRayDebuff,
|
||||||
|
Intuition,
|
||||||
|
EnchantedSummoning,
|
||||||
|
ShieldBash,
|
||||||
|
Whispering,
|
||||||
|
CombatTraining,
|
||||||
|
InjectedStrikeDebuff,
|
||||||
|
InjectedStrike,
|
||||||
|
UnknownTomato,
|
||||||
|
PlayingTheOddsDebuff,
|
||||||
|
DragonTurtleDebuff,
|
||||||
|
Boarding,
|
||||||
|
Potency,
|
||||||
|
ThrustDebuff,
|
||||||
|
FistsOfFury, // 1169
|
||||||
|
BarrabHemolymphConcentrate,
|
||||||
|
JukariBurnPoiltice,
|
||||||
|
KurakAmbushersEssence,
|
||||||
|
BarakoDraftOfMight,
|
||||||
|
UraliTranceTonic,
|
||||||
|
SakkhraProphylaxis, // 1175
|
||||||
|
Sparks,
|
||||||
|
Swarm,
|
||||||
|
BoneBreaker,
|
||||||
|
Unknown2,
|
||||||
|
SwarmImmune,
|
||||||
|
BoneBreakerImmune,
|
||||||
|
UnknownGoblin,
|
||||||
|
UnknownRedDrop,
|
||||||
|
UnknownStar,
|
||||||
|
FeintDebuff,
|
||||||
|
CaddelliteInfused,
|
||||||
|
PotionGloriousFortune,
|
||||||
|
MysticalPolymorphTotem,
|
||||||
|
UnknownDebuff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue