Fixes code according to modern code style. Fixes a few expression bugs.
This commit is contained in:
parent
89eea25e5f
commit
970fd563b2
3324 changed files with 441118 additions and 433755 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -3,73 +3,69 @@ using Server.SkillHandlers;
|
|||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class Backstab : NinjaMove
|
||||
{
|
||||
public Backstab()
|
||||
{
|
||||
}
|
||||
public class Backstab : NinjaMove
|
||||
{
|
||||
public override int BaseMana => 30;
|
||||
public override double RequiredSkill => Core.ML ? 40.0 : 20.0;
|
||||
|
||||
public override int BaseMana => 30;
|
||||
public override double RequiredSkill => Core.ML ? 40.0 : 20.0;
|
||||
public override TextDefinition AbilityMessage =>
|
||||
new TextDefinition(1063089); // You prepare to Backstab your opponent.
|
||||
|
||||
public override TextDefinition AbilityMessage => new TextDefinition( 1063089 ); // You prepare to Backstab your opponent.
|
||||
public override bool ValidatesDuringHit => false;
|
||||
|
||||
public override double GetDamageScalar( Mobile attacker, Mobile defender )
|
||||
{
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
public override double GetDamageScalar(Mobile attacker, Mobile defender)
|
||||
{
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
|
||||
return 1.0 + (ninjitsu / 360) + Tracking.GetStalkingBonus( attacker, defender ) / 100;
|
||||
}
|
||||
return 1.0 + ninjitsu / 360 + Tracking.GetStalkingBonus(attacker, defender) / 100;
|
||||
}
|
||||
|
||||
public override bool Validate( Mobile from )
|
||||
{
|
||||
if ( !from.Hidden || from.AllowedStealthSteps <= 0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1063087 ); // You must be in stealth mode to use this ability.
|
||||
return false;
|
||||
}
|
||||
public override bool Validate(Mobile from)
|
||||
{
|
||||
if (!from.Hidden || from.AllowedStealthSteps <= 0)
|
||||
{
|
||||
from.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.Validate( from );
|
||||
}
|
||||
return base.Validate(from);
|
||||
}
|
||||
|
||||
public override bool OnBeforeSwing( Mobile attacker, Mobile defender )
|
||||
{
|
||||
bool valid = Validate( attacker ) && CheckMana( attacker, true );
|
||||
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
|
||||
{
|
||||
bool valid = Validate(attacker) && CheckMana(attacker, true);
|
||||
|
||||
if ( valid )
|
||||
{
|
||||
attacker.BeginAction( typeof( Stealth ) );
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), delegate { attacker.EndAction( typeof( Stealth ) ); } );
|
||||
}
|
||||
if (valid)
|
||||
{
|
||||
attacker.BeginAction(typeof(Stealth));
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(5.0), delegate { attacker.EndAction(typeof(Stealth)); });
|
||||
}
|
||||
|
||||
return valid;
|
||||
return valid;
|
||||
}
|
||||
|
||||
}
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
//Validates before swing
|
||||
|
||||
public override bool ValidatesDuringHit => false;
|
||||
ClearCurrentMove(attacker);
|
||||
|
||||
public override void OnHit( Mobile attacker, Mobile defender, int damage )
|
||||
{
|
||||
//Validates before swing
|
||||
attacker.SendLocalizedMessage(1063090); // You quickly stab your opponent as you come out of hiding!
|
||||
|
||||
ClearCurrentMove( attacker );
|
||||
defender.FixedParticles(0x37B9, 1, 5, 0x251D, 0x651, 0, EffectLayer.Waist);
|
||||
|
||||
attacker.SendLocalizedMessage( 1063090 ); // You quickly stab your opponent as you come out of hiding!
|
||||
attacker.RevealingAction();
|
||||
|
||||
defender.FixedParticles( 0x37B9, 1, 5, 0x251D, 0x651, 0, EffectLayer.Waist );
|
||||
CheckGain(attacker);
|
||||
}
|
||||
|
||||
attacker.RevealingAction();
|
||||
public override void OnMiss(Mobile attacker, Mobile defender)
|
||||
{
|
||||
ClearCurrentMove(attacker);
|
||||
|
||||
CheckGain( attacker );
|
||||
}
|
||||
attacker.SendLocalizedMessage(1063161); // You failed to properly use the element of surprise.
|
||||
|
||||
public override void OnMiss( Mobile attacker, Mobile defender )
|
||||
{
|
||||
ClearCurrentMove( attacker );
|
||||
|
||||
attacker.SendLocalizedMessage( 1063161 ); // You failed to properly use the element of surprise.
|
||||
|
||||
attacker.RevealingAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
attacker.RevealingAction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,163 +5,162 @@ using Server.SkillHandlers;
|
|||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class DeathStrike : NinjaMove
|
||||
{
|
||||
public DeathStrike()
|
||||
{
|
||||
}
|
||||
public class DeathStrike : NinjaMove
|
||||
{
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
|
||||
public override int BaseMana => 30;
|
||||
public override double RequiredSkill => 85.0;
|
||||
public override int BaseMana => 30;
|
||||
public override double RequiredSkill => 85.0;
|
||||
|
||||
public override TextDefinition AbilityMessage => new TextDefinition( 1063091 ); // You prepare to hit your opponent with a Death Strike.
|
||||
public override TextDefinition AbilityMessage =>
|
||||
new TextDefinition(1063091); // You prepare to hit your opponent with a Death Strike.
|
||||
|
||||
public override double GetDamageScalar( Mobile attacker, Mobile defender )
|
||||
{
|
||||
return 0.5;
|
||||
}
|
||||
public override double GetDamageScalar(Mobile attacker, Mobile defender)
|
||||
{
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
public override void OnHit( Mobile attacker, Mobile defender, int damage )
|
||||
{
|
||||
if ( !Validate( attacker ) || !CheckMana( attacker, true ) )
|
||||
return;
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
return;
|
||||
|
||||
ClearCurrentMove( attacker );
|
||||
ClearCurrentMove(attacker);
|
||||
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
|
||||
double chance;
|
||||
bool isRanged = false; // should be defined onHit method, what if the player hit and remove the weapon before process? ;)
|
||||
double chance;
|
||||
bool
|
||||
isRanged = false; // should be defined onHit method, what if the player hit and remove the weapon before process? ;)
|
||||
|
||||
if ( attacker.Weapon is BaseRanged )
|
||||
isRanged = true;
|
||||
if (attacker.Weapon is BaseRanged)
|
||||
isRanged = true;
|
||||
|
||||
if ( ninjitsu < 100 ) //This formula is an approximation from OSI data. TODO: find correct formula
|
||||
chance = 30 + (ninjitsu - 85) * 2.2;
|
||||
else
|
||||
chance = 63 + (ninjitsu - 100) * 1.1;
|
||||
if (ninjitsu < 100) //This formula is an approximation from OSI data. TODO: find correct formula
|
||||
chance = 30 + (ninjitsu - 85) * 2.2;
|
||||
else
|
||||
chance = 63 + (ninjitsu - 100) * 1.1;
|
||||
|
||||
if ( (chance / 100) < Utility.RandomDouble() )
|
||||
{
|
||||
attacker.SendLocalizedMessage( 1070779 ); // You missed your opponent with a Death Strike.
|
||||
return;
|
||||
}
|
||||
if (chance / 100 < Utility.RandomDouble())
|
||||
{
|
||||
attacker.SendLocalizedMessage(1070779); // You missed your opponent with a Death Strike.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DeathStrikeInfo info;
|
||||
DeathStrikeInfo info;
|
||||
|
||||
int damageBonus = 0;
|
||||
int damageBonus = 0;
|
||||
|
||||
if ( m_Table.Contains( defender ) )
|
||||
{
|
||||
defender.SendLocalizedMessage( 1063092 ); // Your opponent lands another Death Strike!
|
||||
if (m_Table.Contains(defender))
|
||||
{
|
||||
defender.SendLocalizedMessage(1063092); // Your opponent lands another Death Strike!
|
||||
|
||||
info = (DeathStrikeInfo)m_Table[defender];
|
||||
info = (DeathStrikeInfo)m_Table[defender];
|
||||
|
||||
if ( info.m_Steps > 0 )
|
||||
damageBonus = attacker.Skills[SkillName.Ninjitsu].Fixed / 150;
|
||||
if (info.m_Steps > 0)
|
||||
damageBonus = attacker.Skills[SkillName.Ninjitsu].Fixed / 150;
|
||||
|
||||
info.m_Timer?.Stop();
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
m_Table.Remove( defender );
|
||||
}
|
||||
else
|
||||
{
|
||||
defender.SendLocalizedMessage( 1063093 ); // You have been hit by a Death Strike! Move with caution!
|
||||
}
|
||||
m_Table.Remove(defender);
|
||||
}
|
||||
else
|
||||
{
|
||||
defender.SendLocalizedMessage(1063093); // You have been hit by a Death Strike! Move with caution!
|
||||
}
|
||||
|
||||
attacker.SendLocalizedMessage( 1063094 ); // You inflict a Death Strike upon your opponent!
|
||||
attacker.SendLocalizedMessage(1063094); // You inflict a Death Strike upon your opponent!
|
||||
|
||||
defender.FixedParticles( 0x374A, 1, 17, 0x26BC, EffectLayer.Waist );
|
||||
attacker.PlaySound( attacker.Female ? 0x50D : 0x50E );
|
||||
defender.FixedParticles(0x374A, 1, 17, 0x26BC, EffectLayer.Waist);
|
||||
attacker.PlaySound(attacker.Female ? 0x50D : 0x50E);
|
||||
|
||||
info = new DeathStrikeInfo( defender, attacker, damageBonus, isRanged );
|
||||
info.m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), new TimerStateCallback( ProcessDeathStrike ), defender );
|
||||
info = new DeathStrikeInfo(defender, attacker, damageBonus, isRanged);
|
||||
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerStateCallback(ProcessDeathStrike), defender);
|
||||
|
||||
m_Table[defender] = info;
|
||||
m_Table[defender] = info;
|
||||
|
||||
CheckGain( attacker );
|
||||
}
|
||||
CheckGain(attacker);
|
||||
}
|
||||
|
||||
public static void AddStep(Mobile m)
|
||||
{
|
||||
DeathStrikeInfo info = m_Table[m] as DeathStrikeInfo;
|
||||
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
if (info == null)
|
||||
return;
|
||||
|
||||
private class DeathStrikeInfo
|
||||
{
|
||||
public Mobile m_Target;
|
||||
public Mobile m_Attacker;
|
||||
public int m_Steps;
|
||||
public int m_DamageBonus;
|
||||
public Timer m_Timer;
|
||||
public bool m_isRanged;
|
||||
if (++info.m_Steps >= 5)
|
||||
ProcessDeathStrike(m);
|
||||
}
|
||||
|
||||
public DeathStrikeInfo( Mobile target, Mobile attacker, int damageBonus, bool isRanged )
|
||||
{
|
||||
m_Target = target;
|
||||
m_Attacker = attacker;
|
||||
m_DamageBonus = damageBonus;
|
||||
m_isRanged = isRanged;
|
||||
}
|
||||
}
|
||||
private static void ProcessDeathStrike(object state)
|
||||
{
|
||||
Mobile defender = (Mobile)state;
|
||||
|
||||
public static void AddStep( Mobile m )
|
||||
{
|
||||
DeathStrikeInfo info = m_Table[m] as DeathStrikeInfo;
|
||||
DeathStrikeInfo info = m_Table[defender] as DeathStrikeInfo;
|
||||
|
||||
if ( info == null )
|
||||
return;
|
||||
if (info == null) //sanity
|
||||
return;
|
||||
|
||||
if ( ++info.m_Steps >= 5 )
|
||||
ProcessDeathStrike( m );
|
||||
}
|
||||
int maxDamage, damage = 0;
|
||||
|
||||
private static void ProcessDeathStrike( object state )
|
||||
{
|
||||
Mobile defender = (Mobile)state;
|
||||
double ninjitsu = info.m_Attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
double stalkingBonus = Tracking.GetStalkingBonus(info.m_Attacker, info.m_Target);
|
||||
|
||||
DeathStrikeInfo info = m_Table[defender] as DeathStrikeInfo;
|
||||
if (Core.ML)
|
||||
{
|
||||
double scalar = (info.m_Attacker.Skills[SkillName.Hiding].Value +
|
||||
info.m_Attacker.Skills[SkillName.Stealth].Value) / 220;
|
||||
|
||||
if ( info == null ) //sanity
|
||||
return;
|
||||
if (scalar > 1)
|
||||
scalar = 1;
|
||||
|
||||
int maxDamage, damage = 0;
|
||||
// New formula doesn't apply DamageBonus anymore, caps must be, directly, 60/30.
|
||||
if (info.m_Steps >= 5)
|
||||
damage = (int)Math.Floor(Math.Min(60, ninjitsu / 3 * (0.3 + 0.7 * scalar) + stalkingBonus));
|
||||
else
|
||||
damage = (int)Math.Floor(Math.Min(30, ninjitsu / 9 * (0.3 + 0.7 * scalar) + stalkingBonus));
|
||||
|
||||
double ninjitsu = info.m_Attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
double stalkingBonus = Tracking.GetStalkingBonus( info.m_Attacker, info.m_Target );
|
||||
if (info.m_isRanged)
|
||||
damage /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int divisor = info.m_Steps >= 5 ? 30 : 80;
|
||||
double baseDamage = ninjitsu / divisor * 10;
|
||||
|
||||
if ( Core.ML )
|
||||
{
|
||||
double scalar = ( info.m_Attacker.Skills[SkillName.Hiding].Value + info.m_Attacker.Skills[SkillName.Stealth].Value ) / 220;
|
||||
maxDamage = info.m_Steps >= 5 ? 62 : 22; // DamageBonus is 8 at most. That brings the cap up to 70/30.
|
||||
damage = Math.Max(0, Math.Min(maxDamage, (int)(baseDamage + stalkingBonus))) + info.m_DamageBonus;
|
||||
}
|
||||
|
||||
if ( scalar > 1 )
|
||||
scalar = 1;
|
||||
if (Core.ML)
|
||||
info.m_Target.Damage(damage, info.m_Attacker); // Damage is direct.
|
||||
else
|
||||
AOS.Damage(info.m_Target, info.m_Attacker, damage, true, 100, 0, 0, 0, 0, 0, 0, false, false,
|
||||
true); // Damage is physical.
|
||||
|
||||
// New formula doesn't apply DamageBonus anymore, caps must be, directly, 60/30.
|
||||
if ( info.m_Steps >= 5 )
|
||||
damage = (int)Math.Floor( Math.Min( 60, ( ninjitsu / 3 ) * ( 0.3 + 0.7 * scalar ) + stalkingBonus ) );
|
||||
else
|
||||
damage = (int)Math.Floor( Math.Min( 30, ( ninjitsu / 9 ) * ( 0.3 + 0.7 * scalar ) + stalkingBonus ) );
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
if ( info.m_isRanged )
|
||||
damage /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
int divisor = (info.m_Steps >= 5) ? 30 : 80;
|
||||
double baseDamage = ninjitsu / divisor * 10;
|
||||
m_Table.Remove(info.m_Target);
|
||||
}
|
||||
|
||||
maxDamage = (info.m_Steps >= 5) ? 62 : 22; // DamageBonus is 8 at most. That brings the cap up to 70/30.
|
||||
damage = Math.Max( 0, Math.Min( maxDamage, (int)( baseDamage + stalkingBonus ) ) ) + info.m_DamageBonus;
|
||||
}
|
||||
private class DeathStrikeInfo
|
||||
{
|
||||
public Mobile m_Attacker;
|
||||
public int m_DamageBonus;
|
||||
public bool m_isRanged;
|
||||
public int m_Steps;
|
||||
public Mobile m_Target;
|
||||
public Timer m_Timer;
|
||||
|
||||
if ( Core.ML )
|
||||
info.m_Target.Damage( damage, info.m_Attacker ); // Damage is direct.
|
||||
else
|
||||
AOS.Damage( info.m_Target, info.m_Attacker, damage, true, 100, 0, 0, 0, 0, 0, 0, false, false, true ); // Damage is physical.
|
||||
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
m_Table.Remove( info.m_Target );
|
||||
}
|
||||
}
|
||||
}
|
||||
public DeathStrikeInfo(Mobile target, Mobile attacker, int damageBonus, bool isRanged)
|
||||
{
|
||||
m_Target = target;
|
||||
m_Attacker = attacker;
|
||||
m_DamageBonus = damageBonus;
|
||||
m_isRanged = isRanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,68 +2,65 @@ using Server.Items;
|
|||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class FocusAttack : NinjaMove
|
||||
{
|
||||
public FocusAttack()
|
||||
{
|
||||
}
|
||||
public class FocusAttack : NinjaMove
|
||||
{
|
||||
public override int BaseMana => Core.ML ? 10 : 20;
|
||||
public override double RequiredSkill => Core.ML ? 30.0 : 60;
|
||||
|
||||
public override int BaseMana => Core.ML ? 10 : 20;
|
||||
public override double RequiredSkill => Core.ML? 30.0 : 60 ;
|
||||
public override TextDefinition AbilityMessage =>
|
||||
new TextDefinition(1063095); // You prepare to focus all of your abilities into your next strike.
|
||||
|
||||
public override TextDefinition AbilityMessage => new TextDefinition( 1063095 ); // You prepare to focus all of your abilities into your next strike.
|
||||
public override bool Validate(Mobile from)
|
||||
{
|
||||
if (from.FindItemOnLayer(Layer.TwoHanded) as BaseShield != null)
|
||||
{
|
||||
from.SendLocalizedMessage(1063096); // You cannot use this ability while holding a shield.
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool Validate( Mobile from )
|
||||
{
|
||||
if ( from.FindItemOnLayer( Layer.TwoHanded ) as BaseShield != null )
|
||||
{
|
||||
from.SendLocalizedMessage( 1063096 ); // You cannot use this ability while holding a shield.
|
||||
return false;
|
||||
}
|
||||
Item handOne = from.FindItemOnLayer(Layer.OneHanded) as BaseWeapon;
|
||||
|
||||
Item handOne = from.FindItemOnLayer( Layer.OneHanded ) as BaseWeapon;
|
||||
if (handOne != null && !(handOne is BaseRanged))
|
||||
return base.Validate(from);
|
||||
|
||||
if ( handOne != null && !(handOne is BaseRanged) )
|
||||
return base.Validate( from );
|
||||
Item handTwo = from.FindItemOnLayer(Layer.TwoHanded) as BaseWeapon;
|
||||
|
||||
Item handTwo = from.FindItemOnLayer( Layer.TwoHanded ) as BaseWeapon;
|
||||
if (handTwo != null && !(handTwo is BaseRanged))
|
||||
return base.Validate(from);
|
||||
|
||||
if ( handTwo != null && !(handTwo is BaseRanged) )
|
||||
return base.Validate( from );
|
||||
from.SendLocalizedMessage(1063097); // You must be wielding a melee weapon without a shield to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage( 1063097 ); // You must be wielding a melee weapon without a shield to use this ability.
|
||||
return false;
|
||||
}
|
||||
public override double GetDamageScalar(Mobile attacker, Mobile defender)
|
||||
{
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
|
||||
public override double GetDamageScalar( Mobile attacker, Mobile defender )
|
||||
{
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
return 1.0 + ninjitsu * ninjitsu / 43636;
|
||||
}
|
||||
|
||||
return 1.0 + (ninjitsu * ninjitsu) / 43636;
|
||||
}
|
||||
public override double GetPropertyBonus(Mobile attacker)
|
||||
{
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
|
||||
public override double GetPropertyBonus( Mobile attacker )
|
||||
{
|
||||
double ninjitsu = attacker.Skills[SkillName.Ninjitsu].Value;
|
||||
double bonus = ninjitsu * ninjitsu / 43636;
|
||||
|
||||
double bonus = (ninjitsu * ninjitsu) / 43636;
|
||||
return 1.0 + (bonus * 3 + 0.01);
|
||||
}
|
||||
|
||||
return 1.0 + (bonus * 3 + 0.01);
|
||||
}
|
||||
public override bool OnBeforeDamage(Mobile attacker, Mobile defender)
|
||||
{
|
||||
return Validate(attacker) && CheckMana(attacker, true);
|
||||
}
|
||||
|
||||
public override bool OnBeforeDamage( Mobile attacker, Mobile defender )
|
||||
{
|
||||
return Validate( attacker ) && CheckMana( attacker, true );
|
||||
}
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
ClearCurrentMove(attacker);
|
||||
|
||||
public override void OnHit( Mobile attacker, Mobile defender, int damage )
|
||||
{
|
||||
ClearCurrentMove( attacker );
|
||||
attacker.SendLocalizedMessage(1063098); // You focus all of your abilities and strike with deadly force!
|
||||
attacker.PlaySound(0x510);
|
||||
|
||||
attacker.SendLocalizedMessage( 1063098 ); // You focus all of your abilities and strike with deadly force!
|
||||
attacker.PlaySound( 0x510 );
|
||||
|
||||
CheckGain( attacker );
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckGain(attacker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,141 +4,139 @@ using Server.Items;
|
|||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class KiAttack : NinjaMove
|
||||
{
|
||||
public KiAttack()
|
||||
{
|
||||
}
|
||||
public class KiAttack : NinjaMove
|
||||
{
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
|
||||
public override int BaseMana => 25;
|
||||
public override double RequiredSkill => 80.0;
|
||||
public override int BaseMana => 25;
|
||||
public override double RequiredSkill => 80.0;
|
||||
|
||||
public override TextDefinition AbilityMessage => new TextDefinition( 1063099 ); // Your Ki Attack must be complete within 2 seconds for the damage bonus!
|
||||
public override TextDefinition AbilityMessage =>
|
||||
new TextDefinition(1063099); // Your Ki Attack must be complete within 2 seconds for the damage bonus!
|
||||
|
||||
public override void OnUse( Mobile from )
|
||||
{
|
||||
if ( !Validate( from ) )
|
||||
return;
|
||||
public override void OnUse(Mobile from)
|
||||
{
|
||||
if (!Validate(from))
|
||||
return;
|
||||
|
||||
KiAttackInfo info = new KiAttackInfo( from );
|
||||
info.m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 2.0 ), new TimerStateCallback( EndKiAttack ), info );
|
||||
KiAttackInfo info = new KiAttackInfo(from);
|
||||
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(2.0), new TimerStateCallback(EndKiAttack), info);
|
||||
|
||||
m_Table[from] = info;
|
||||
}
|
||||
m_Table[from] = info;
|
||||
}
|
||||
|
||||
public override bool Validate( Mobile from )
|
||||
{
|
||||
if ( from.Hidden && from.AllowedStealthSteps > 0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1063127 ); // You cannot use this ability while in stealth mode.
|
||||
return false;
|
||||
}
|
||||
public override bool Validate(Mobile from)
|
||||
{
|
||||
if (from.Hidden && from.AllowedStealthSteps > 0)
|
||||
{
|
||||
from.SendLocalizedMessage(1063127); // You cannot use this ability while in stealth mode.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Core.ML )
|
||||
{
|
||||
BaseRanged ranged = from.Weapon as BaseRanged;
|
||||
if (Core.ML)
|
||||
{
|
||||
BaseRanged ranged = from.Weapon as BaseRanged;
|
||||
|
||||
if ( ranged != null )
|
||||
{
|
||||
from.SendLocalizedMessage( 1075858 ); // You can only use this with melee attacks.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ranged != null)
|
||||
{
|
||||
from.SendLocalizedMessage(1075858); // You can only use this with melee attacks.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return base.Validate( from );
|
||||
}
|
||||
return base.Validate(from);
|
||||
}
|
||||
|
||||
public override double GetDamageScalar( Mobile attacker, Mobile defender )
|
||||
{
|
||||
if ( attacker.Hidden )
|
||||
return 1.0;
|
||||
public override double GetDamageScalar(Mobile attacker, Mobile defender)
|
||||
{
|
||||
if (attacker.Hidden)
|
||||
return 1.0;
|
||||
|
||||
/*
|
||||
* Pub40 changed pvp damage max to 55%
|
||||
*/
|
||||
/*
|
||||
* Pub40 changed pvp damage max to 55%
|
||||
*/
|
||||
|
||||
return 1.0 + GetBonus(attacker) / ( (Core.ML && attacker.Player && defender.Player) ? 40 : 10 );
|
||||
}
|
||||
return 1.0 + GetBonus(attacker) / (Core.ML && attacker.Player && defender.Player ? 40 : 10);
|
||||
}
|
||||
|
||||
public override void OnHit( Mobile attacker, Mobile defender, int damage )
|
||||
{
|
||||
if ( !Validate( attacker ) || !CheckMana( attacker, true ) )
|
||||
return;
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
if (!Validate(attacker) || !CheckMana(attacker, true))
|
||||
return;
|
||||
|
||||
if ( GetBonus( attacker ) == 0.0 )
|
||||
{
|
||||
attacker.SendLocalizedMessage( 1063101 ); // You were too close to your target to cause any additional damage.
|
||||
}
|
||||
else
|
||||
{
|
||||
attacker.FixedParticles( 0x37BE, 1, 5, 0x26BD, 0x0, 0x1, EffectLayer.Waist );
|
||||
attacker.PlaySound( 0x510 );
|
||||
if (GetBonus(attacker) == 0.0)
|
||||
{
|
||||
attacker.SendLocalizedMessage(1063101); // You were too close to your target to cause any additional damage.
|
||||
}
|
||||
else
|
||||
{
|
||||
attacker.FixedParticles(0x37BE, 1, 5, 0x26BD, 0x0, 0x1, EffectLayer.Waist);
|
||||
attacker.PlaySound(0x510);
|
||||
|
||||
attacker.SendLocalizedMessage( 1063100 ); // Your quick flight to your target causes extra damage as you strike!
|
||||
defender.FixedParticles( 0x37BE, 1, 5, 0x26BD, 0, 0x1, EffectLayer.Waist );
|
||||
attacker.SendLocalizedMessage(
|
||||
1063100); // Your quick flight to your target causes extra damage as you strike!
|
||||
defender.FixedParticles(0x37BE, 1, 5, 0x26BD, 0, 0x1, EffectLayer.Waist);
|
||||
|
||||
CheckGain( attacker );
|
||||
}
|
||||
CheckGain(attacker);
|
||||
}
|
||||
|
||||
ClearCurrentMove( attacker );
|
||||
}
|
||||
ClearCurrentMove(attacker);
|
||||
}
|
||||
|
||||
public override void OnClearMove( Mobile from )
|
||||
{
|
||||
KiAttackInfo info = m_Table[from] as KiAttackInfo;
|
||||
public override void OnClearMove(Mobile from)
|
||||
{
|
||||
KiAttackInfo info = m_Table[from] as KiAttackInfo;
|
||||
|
||||
if ( info != null )
|
||||
{
|
||||
info.m_Timer?.Stop();
|
||||
if (info != null)
|
||||
{
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
m_Table.Remove( info.m_Mobile );
|
||||
}
|
||||
}
|
||||
m_Table.Remove(info.m_Mobile);
|
||||
}
|
||||
}
|
||||
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
public static double GetBonus(Mobile from)
|
||||
{
|
||||
KiAttackInfo info = m_Table[from] as KiAttackInfo;
|
||||
|
||||
public static double GetBonus( Mobile from )
|
||||
{
|
||||
KiAttackInfo info = m_Table[from] as KiAttackInfo;
|
||||
if (info == null)
|
||||
return 0.0;
|
||||
|
||||
if ( info == null )
|
||||
return 0.0;
|
||||
int xDelta = info.m_Location.X - from.X;
|
||||
int yDelta = info.m_Location.Y - from.Y;
|
||||
|
||||
int xDelta = info.m_Location.X - from.X;
|
||||
int yDelta = info.m_Location.Y - from.Y;
|
||||
double bonus = Math.Sqrt(xDelta * xDelta + yDelta * yDelta);
|
||||
|
||||
double bonus = Math.Sqrt( (xDelta * xDelta) + (yDelta * yDelta) );
|
||||
if (bonus > 20.0)
|
||||
bonus = 20.0;
|
||||
|
||||
if ( bonus > 20.0 )
|
||||
bonus = 20.0;
|
||||
return bonus;
|
||||
}
|
||||
|
||||
return bonus;
|
||||
}
|
||||
private static void EndKiAttack(object state)
|
||||
{
|
||||
KiAttackInfo info = (KiAttackInfo)state;
|
||||
|
||||
private class KiAttackInfo
|
||||
{
|
||||
public Mobile m_Mobile;
|
||||
public Point3D m_Location;
|
||||
public Timer m_Timer;
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
public KiAttackInfo( Mobile m )
|
||||
{
|
||||
m_Mobile = m;
|
||||
m_Location = m.Location;
|
||||
}
|
||||
}
|
||||
ClearCurrentMove(info.m_Mobile);
|
||||
info.m_Mobile.SendLocalizedMessage(1063102); // You failed to complete your Ki Attack in time.
|
||||
|
||||
private static void EndKiAttack( object state )
|
||||
{
|
||||
KiAttackInfo info = (KiAttackInfo)state;
|
||||
m_Table.Remove(info.m_Mobile);
|
||||
}
|
||||
|
||||
info.m_Timer?.Stop();
|
||||
private class KiAttackInfo
|
||||
{
|
||||
public Point3D m_Location;
|
||||
public Mobile m_Mobile;
|
||||
public Timer m_Timer;
|
||||
|
||||
ClearCurrentMove( info.m_Mobile );
|
||||
info.m_Mobile.SendLocalizedMessage( 1063102 ); // You failed to complete your Ki Attack in time.
|
||||
|
||||
m_Table.Remove( info.m_Mobile );
|
||||
}
|
||||
}
|
||||
}
|
||||
public KiAttackInfo(Mobile m)
|
||||
{
|
||||
m_Mobile = m;
|
||||
m_Location = m.Location;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,262 +8,268 @@ using Server.Spells.Ninjitsu;
|
|||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class MirrorImage : NinjaSpell
|
||||
{
|
||||
private static Dictionary<Mobile, int> m_CloneCount = new Dictionary<Mobile, int>();
|
||||
public class MirrorImage : NinjaSpell
|
||||
{
|
||||
private static Dictionary<Mobile, int> m_CloneCount = new Dictionary<Mobile, int>();
|
||||
|
||||
public static bool HasClone( Mobile m )
|
||||
{
|
||||
return m_CloneCount.ContainsKey( m );
|
||||
}
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Mirror Image", null,
|
||||
-1,
|
||||
9002
|
||||
);
|
||||
|
||||
public static void AddClone( Mobile m )
|
||||
{
|
||||
if ( m == null )
|
||||
return;
|
||||
public MirrorImage(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
if ( m_CloneCount.ContainsKey( m ) )
|
||||
m_CloneCount[m]++;
|
||||
else
|
||||
m_CloneCount[m] = 1;
|
||||
}
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.5);
|
||||
|
||||
public static void RemoveClone( Mobile m )
|
||||
{
|
||||
if ( m == null )
|
||||
return;
|
||||
public override double RequiredSkill => Core.ML ? 20.0 : 40.0;
|
||||
public override int RequiredMana => 10;
|
||||
|
||||
if ( m_CloneCount.ContainsKey( m ) )
|
||||
{
|
||||
m_CloneCount[m]--;
|
||||
public override bool BlockedByAnimalForm => false;
|
||||
|
||||
if ( m_CloneCount[m] == 0 )
|
||||
m_CloneCount.Remove( m );
|
||||
}
|
||||
}
|
||||
public static bool HasClone(Mobile m)
|
||||
{
|
||||
return m_CloneCount.ContainsKey(m);
|
||||
}
|
||||
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Mirror Image", null,
|
||||
-1,
|
||||
9002
|
||||
);
|
||||
public static void AddClone(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.5 );
|
||||
if (m_CloneCount.ContainsKey(m))
|
||||
m_CloneCount[m]++;
|
||||
else
|
||||
m_CloneCount[m] = 1;
|
||||
}
|
||||
|
||||
public override double RequiredSkill => Core.ML ? 20.0 : 40.0;
|
||||
public override int RequiredMana => 10;
|
||||
public static void RemoveClone(Mobile m)
|
||||
{
|
||||
if (m == null)
|
||||
return;
|
||||
|
||||
public override bool BlockedByAnimalForm => false;
|
||||
if (m_CloneCount.ContainsKey(m))
|
||||
{
|
||||
m_CloneCount[m]--;
|
||||
|
||||
public MirrorImage( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
if (m_CloneCount[m] == 0)
|
||||
m_CloneCount.Remove(m);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if ( Caster.Mounted )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063132 ); // You cannot use this ability while mounted.
|
||||
return false;
|
||||
}
|
||||
public override bool CheckCast()
|
||||
{
|
||||
if (Caster.Mounted)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063132); // You cannot use this ability while mounted.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( (Caster.Followers + 1) > Caster.FollowersMax )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063133 ); // You cannot summon a mirror image because you have too many followers.
|
||||
return false;
|
||||
}
|
||||
if ( TransformationSpellHelper.UnderTransformation( Caster, typeof( HorrificBeastSpell ) ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1061091 ); // You cannot cast that spell in this form.
|
||||
return false;
|
||||
}
|
||||
if (Caster.Followers + 1 > Caster.FollowersMax)
|
||||
{
|
||||
Caster.SendLocalizedMessage(
|
||||
1063133); // You cannot summon a mirror image because you have too many followers.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
if (TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell)))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form.
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool CheckDisturb( DisturbType type, bool firstCircle, bool resistable )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
public override void OnBeginCast()
|
||||
{
|
||||
base.OnBeginCast();
|
||||
public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Caster.SendLocalizedMessage( 1063134 ); // You begin to summon a mirror image of yourself.
|
||||
}
|
||||
public override void OnBeginCast()
|
||||
{
|
||||
base.OnBeginCast();
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
if ( Caster.Mounted )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063132 ); // You cannot use this ability while mounted.
|
||||
}
|
||||
else if ( (Caster.Followers + 1) > Caster.FollowersMax )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063133 ); // You cannot summon a mirror image because you have too many followers.
|
||||
}
|
||||
else if ( TransformationSpellHelper.UnderTransformation( Caster, typeof( HorrificBeastSpell ) ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1061091 ); // You cannot cast that spell in this form.
|
||||
}
|
||||
else if ( CheckSequence() )
|
||||
{
|
||||
Caster.FixedParticles( 0x376A, 1, 14, 0x13B5, EffectLayer.Waist );
|
||||
Caster.PlaySound( 0x511 );
|
||||
Caster.SendLocalizedMessage(1063134); // You begin to summon a mirror image of yourself.
|
||||
}
|
||||
|
||||
new Clone( Caster ).MoveToWorld( Caster.Location, Caster.Map );
|
||||
}
|
||||
public override void OnCast()
|
||||
{
|
||||
if (Caster.Mounted)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063132); // You cannot use this ability while mounted.
|
||||
}
|
||||
else if (Caster.Followers + 1 > Caster.FollowersMax)
|
||||
{
|
||||
Caster.SendLocalizedMessage(
|
||||
1063133); // You cannot summon a mirror image because you have too many followers.
|
||||
}
|
||||
else if (TransformationSpellHelper.UnderTransformation(Caster, typeof(HorrificBeastSpell)))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1061091); // You cannot cast that spell in this form.
|
||||
}
|
||||
else if (CheckSequence())
|
||||
{
|
||||
Caster.FixedParticles(0x376A, 1, 14, 0x13B5, EffectLayer.Waist);
|
||||
Caster.PlaySound(0x511);
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
new Clone(Caster).MoveToWorld(Caster.Location, Caster.Map);
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class Clone : BaseCreature
|
||||
{
|
||||
private Mobile m_Caster;
|
||||
public class Clone : BaseCreature
|
||||
{
|
||||
private Mobile m_Caster;
|
||||
|
||||
public Clone( Mobile caster ) : base( AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4 )
|
||||
{
|
||||
m_Caster = caster;
|
||||
public Clone(Mobile caster) : base(AIType.AI_Melee, FightMode.None, 10, 1, 0.2, 0.4)
|
||||
{
|
||||
m_Caster = caster;
|
||||
|
||||
Body = caster.Body;
|
||||
Body = caster.Body;
|
||||
|
||||
Hue = caster.Hue;
|
||||
Female = caster.Female;
|
||||
Hue = caster.Hue;
|
||||
Female = caster.Female;
|
||||
|
||||
Name = caster.Name;
|
||||
NameHue = caster.NameHue;
|
||||
Name = caster.Name;
|
||||
NameHue = caster.NameHue;
|
||||
|
||||
Title = caster.Title;
|
||||
Kills = caster.Kills;
|
||||
Title = caster.Title;
|
||||
Kills = caster.Kills;
|
||||
|
||||
HairItemID = caster.HairItemID;
|
||||
HairHue = caster.HairHue;
|
||||
HairItemID = caster.HairItemID;
|
||||
HairHue = caster.HairHue;
|
||||
|
||||
FacialHairItemID = caster.FacialHairItemID;
|
||||
FacialHairHue = caster.FacialHairHue;
|
||||
FacialHairItemID = caster.FacialHairItemID;
|
||||
FacialHairHue = caster.FacialHairHue;
|
||||
|
||||
for ( int i = 0; i < caster.Skills.Length; ++i )
|
||||
{
|
||||
Skills[i].Base = caster.Skills[i].Base;
|
||||
Skills[i].Cap = caster.Skills[i].Cap;
|
||||
}
|
||||
for (int i = 0; i < caster.Skills.Length; ++i)
|
||||
{
|
||||
Skills[i].Base = caster.Skills[i].Base;
|
||||
Skills[i].Cap = caster.Skills[i].Cap;
|
||||
}
|
||||
|
||||
for( int i = 0; i < caster.Items.Count; i++ )
|
||||
{
|
||||
AddItem( CloneItem( caster.Items[i] ) );
|
||||
}
|
||||
for (int i = 0; i < caster.Items.Count; i++) AddItem(CloneItem(caster.Items[i]));
|
||||
|
||||
Warmode = true;
|
||||
Warmode = true;
|
||||
|
||||
Summoned = true;
|
||||
SummonMaster = caster;
|
||||
Summoned = true;
|
||||
SummonMaster = caster;
|
||||
|
||||
ControlOrder = OrderType.Follow;
|
||||
ControlTarget = caster;
|
||||
ControlOrder = OrderType.Follow;
|
||||
ControlTarget = caster;
|
||||
|
||||
TimeSpan duration = TimeSpan.FromSeconds( 30 + caster.Skills.Ninjitsu.Fixed / 40 );
|
||||
TimeSpan duration = TimeSpan.FromSeconds(30 + caster.Skills.Ninjitsu.Fixed / 40);
|
||||
|
||||
new UnsummonTimer( caster, this, duration ).Start();
|
||||
SummonEnd = DateTime.UtcNow + duration;
|
||||
new UnsummonTimer(caster, this, duration).Start();
|
||||
SummonEnd = DateTime.UtcNow + duration;
|
||||
|
||||
MirrorImage.AddClone( m_Caster );
|
||||
}
|
||||
MirrorImage.AddClone(m_Caster);
|
||||
}
|
||||
|
||||
protected override BaseAI ForcedAI => new CloneAI( this );
|
||||
public Clone(Serial serial) : base(serial)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsHumanInTown() { return false; }
|
||||
protected override BaseAI ForcedAI => new CloneAI(this);
|
||||
|
||||
private Item CloneItem( Item item )
|
||||
{
|
||||
Item newItem = new Item( item.ItemID );
|
||||
newItem.Hue = item.Hue;
|
||||
newItem.Layer = item.Layer;
|
||||
public override bool DeleteCorpseOnDeath => true;
|
||||
|
||||
return newItem;
|
||||
}
|
||||
public override bool IsDispellable => false;
|
||||
public override bool Commandable => false;
|
||||
|
||||
public override void OnDamage( int amount, Mobile from, bool willKill )
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
public override bool IsHumanInTown()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool DeleteCorpseOnDeath => true;
|
||||
private Item CloneItem(Item item)
|
||||
{
|
||||
Item newItem = new Item(item.ItemID);
|
||||
newItem.Hue = item.Hue;
|
||||
newItem.Layer = item.Layer;
|
||||
|
||||
public override void OnDelete()
|
||||
{
|
||||
Effects.SendLocationParticles( EffectItem.Create( Location, Map, EffectItem.DefaultDuration ), 0x3728, 10, 15, 5042 );
|
||||
return newItem;
|
||||
}
|
||||
|
||||
base.OnDelete();
|
||||
}
|
||||
public override void OnDamage(int amount, Mobile from, bool willKill)
|
||||
{
|
||||
Delete();
|
||||
}
|
||||
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
MirrorImage.RemoveClone( m_Caster );
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
public override void OnDelete()
|
||||
{
|
||||
Effects.SendLocationParticles(EffectItem.Create(Location, Map, EffectItem.DefaultDuration), 0x3728, 10, 15,
|
||||
5042);
|
||||
|
||||
public override bool IsDispellable => false;
|
||||
public override bool Commandable => false;
|
||||
base.OnDelete();
|
||||
}
|
||||
|
||||
public Clone( Serial serial ) : base( serial )
|
||||
{
|
||||
}
|
||||
public override void OnAfterDelete()
|
||||
{
|
||||
MirrorImage.RemoveClone(m_Caster);
|
||||
base.OnAfterDelete();
|
||||
}
|
||||
|
||||
public override void Serialize( GenericWriter writer )
|
||||
{
|
||||
base.Serialize( writer );
|
||||
public override void Serialize(GenericWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
|
||||
writer.WriteEncodedInt( 0 ); // version
|
||||
writer.WriteEncodedInt(0); // version
|
||||
|
||||
writer.Write( m_Caster );
|
||||
}
|
||||
writer.Write(m_Caster);
|
||||
}
|
||||
|
||||
public override void Deserialize( GenericReader reader )
|
||||
{
|
||||
base.Deserialize( reader );
|
||||
public override void Deserialize(GenericReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
|
||||
int version = reader.ReadEncodedInt();
|
||||
int version = reader.ReadEncodedInt();
|
||||
|
||||
m_Caster = reader.ReadMobile();
|
||||
m_Caster = reader.ReadMobile();
|
||||
|
||||
MirrorImage.AddClone( m_Caster );
|
||||
}
|
||||
}
|
||||
MirrorImage.AddClone(m_Caster);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Server.Mobiles
|
||||
{
|
||||
public class CloneAI : BaseAI
|
||||
{
|
||||
public CloneAI( Clone m ) : base ( m )
|
||||
{
|
||||
m.CurrentSpeed = m.ActiveSpeed;
|
||||
}
|
||||
public class CloneAI : BaseAI
|
||||
{
|
||||
public CloneAI(Clone m) : base(m)
|
||||
{
|
||||
m.CurrentSpeed = m.ActiveSpeed;
|
||||
}
|
||||
|
||||
public override bool Think()
|
||||
{
|
||||
// Clones only follow their owners
|
||||
Mobile master = m_Mobile.SummonMaster;
|
||||
public override bool CanDetectHidden => false;
|
||||
|
||||
if ( master != null && master.Map == m_Mobile.Map && master.InRange( m_Mobile, m_Mobile.RangePerception ) )
|
||||
{
|
||||
int iCurrDist = (int)m_Mobile.GetDistanceToSqrt( master );
|
||||
bool bRun = (iCurrDist > 5);
|
||||
public override bool Think()
|
||||
{
|
||||
// Clones only follow their owners
|
||||
Mobile master = m_Mobile.SummonMaster;
|
||||
|
||||
WalkMobileRange( master, 2, bRun, 0, 1 );
|
||||
}
|
||||
else
|
||||
WalkRandom( 2, 2, 1 );
|
||||
if (master != null && master.Map == m_Mobile.Map && master.InRange(m_Mobile, m_Mobile.RangePerception))
|
||||
{
|
||||
int iCurrDist = (int)m_Mobile.GetDistanceToSqrt(master);
|
||||
bool bRun = iCurrDist > 5;
|
||||
|
||||
return true;
|
||||
}
|
||||
WalkMobileRange(master, 2, bRun, 0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
WalkRandom(2, 2, 1);
|
||||
}
|
||||
|
||||
public override bool CanDetectHidden => false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
namespace Server.Spells
|
||||
{
|
||||
public class NinjaMove : SpecialMove
|
||||
{
|
||||
public override SkillName MoveSkill => SkillName.Ninjitsu;
|
||||
public class NinjaMove : SpecialMove
|
||||
{
|
||||
public override SkillName MoveSkill => SkillName.Ninjitsu;
|
||||
|
||||
public override void CheckGain( Mobile m )
|
||||
{
|
||||
m.CheckSkill( MoveSkill, RequiredSkill - 12.5, RequiredSkill + 37.5 ); //Per five on friday 02/16/07
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void CheckGain(Mobile m)
|
||||
{
|
||||
m.CheckSkill(MoveSkill, RequiredSkill - 12.5, RequiredSkill + 37.5); //Per five on friday 02/16/07
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,103 +1,106 @@
|
|||
using System;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public abstract class NinjaSpell : Spell
|
||||
{
|
||||
public abstract double RequiredSkill{ get; }
|
||||
public abstract int RequiredMana{ get; }
|
||||
public abstract class NinjaSpell : Spell
|
||||
{
|
||||
public NinjaSpell(Mobile caster, Item scroll, SpellInfo info) : base(caster, scroll, info)
|
||||
{
|
||||
}
|
||||
|
||||
public override SkillName CastSkill => SkillName.Ninjitsu;
|
||||
public override SkillName DamageSkill => SkillName.Ninjitsu;
|
||||
public abstract double RequiredSkill{ get; }
|
||||
public abstract int RequiredMana{ get; }
|
||||
|
||||
public override bool RevealOnCast => false;
|
||||
public override bool ClearHandsOnCast => false;
|
||||
public override bool ShowHandMovement => false;
|
||||
public override SkillName CastSkill => SkillName.Ninjitsu;
|
||||
public override SkillName DamageSkill => SkillName.Ninjitsu;
|
||||
|
||||
public override bool BlocksMovement => false;
|
||||
public override bool RevealOnCast => false;
|
||||
public override bool ClearHandsOnCast => false;
|
||||
public override bool ShowHandMovement => false;
|
||||
|
||||
//public override int CastDelayBase => 1;
|
||||
public override bool BlocksMovement => false;
|
||||
|
||||
public override int CastRecoveryBase => 7;
|
||||
//public override int CastDelayBase => 1;
|
||||
|
||||
public NinjaSpell( Mobile caster, Item scroll, SpellInfo info ) : base( caster, scroll, info )
|
||||
{
|
||||
}
|
||||
public override int CastRecoveryBase => 7;
|
||||
|
||||
public static bool CheckExpansion( Mobile from )
|
||||
{
|
||||
if ( !( from is PlayerMobile ) )
|
||||
return true;
|
||||
public static bool CheckExpansion(Mobile from)
|
||||
{
|
||||
if (!(from is PlayerMobile))
|
||||
return true;
|
||||
|
||||
if ( from.NetState == null )
|
||||
return false;
|
||||
if (from.NetState == null)
|
||||
return false;
|
||||
|
||||
return from.NetState.SupportsExpansion( Expansion.SE );
|
||||
}
|
||||
return from.NetState.SupportsExpansion(Expansion.SE);
|
||||
}
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
int mana = ScaleMana( RequiredMana );
|
||||
public override bool CheckCast()
|
||||
{
|
||||
int mana = ScaleMana(RequiredMana);
|
||||
|
||||
if ( !base.CheckCast() )
|
||||
return false;
|
||||
if (!base.CheckCast())
|
||||
return false;
|
||||
|
||||
if ( !CheckExpansion( Caster ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063456 ); // You must upgrade to Samurai Empire in order to use that ability.
|
||||
return false;
|
||||
}
|
||||
if (!CheckExpansion(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063456); // You must upgrade to Samurai Empire in order to use that ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Caster.Skills[CastSkill].Value < RequiredSkill )
|
||||
{
|
||||
string args = $"{RequiredSkill.ToString("F1")}\t{CastSkill.ToString()}\t ";
|
||||
Caster.SendLocalizedMessage( 1063013, args ); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability.
|
||||
return false;
|
||||
}
|
||||
if (Caster.Skills[CastSkill].Value < RequiredSkill)
|
||||
{
|
||||
string args = $"{RequiredSkill.ToString("F1")}\t{CastSkill.ToString()}\t ";
|
||||
Caster.SendLocalizedMessage(1063013,
|
||||
args); // You need at least ~1_SKILL_REQUIREMENT~ ~2_SKILL_NAME~ skill to use that ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Caster.Mana < mana )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
|
||||
return false;
|
||||
}
|
||||
if (Caster.Mana < mana)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1060174,
|
||||
mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckFizzle()
|
||||
{
|
||||
int mana = ScaleMana( RequiredMana );
|
||||
public override bool CheckFizzle()
|
||||
{
|
||||
int mana = ScaleMana(RequiredMana);
|
||||
|
||||
if ( Caster.Skills[CastSkill].Value < RequiredSkill )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063352, RequiredSkill.ToString( "F1" ) ); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
|
||||
return false;
|
||||
}
|
||||
if (Caster.Skills[CastSkill].Value < RequiredSkill)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063352,
|
||||
RequiredSkill.ToString("F1")); // You need ~1_SKILL_REQUIREMENT~ Ninjitsu skill to perform that attack!
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( Caster.Mana < mana )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1060174, mana.ToString() ); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
|
||||
return false;
|
||||
}
|
||||
if (Caster.Mana < mana)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1060174,
|
||||
mana.ToString()); // You must have at least ~1_MANA_REQUIREMENT~ Mana to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !base.CheckFizzle() )
|
||||
return false;
|
||||
if (!base.CheckFizzle())
|
||||
return false;
|
||||
|
||||
Caster.Mana -= mana;
|
||||
Caster.Mana -= mana;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void GetCastSkills( out double min, out double max )
|
||||
{
|
||||
min = RequiredSkill - 12.5; //Per 5 on friday 2/16/07
|
||||
max = RequiredSkill + 37.5;
|
||||
}
|
||||
public override void GetCastSkills(out double min, out double max)
|
||||
{
|
||||
min = RequiredSkill - 12.5; //Per 5 on friday 2/16/07
|
||||
max = RequiredSkill + 37.5;
|
||||
}
|
||||
|
||||
public override int GetMana()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
public override int GetMana()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,131 +1,137 @@
|
|||
using System;
|
||||
using Server.Factions;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Mobiles;
|
||||
using Server.Regions;
|
||||
using Server.SkillHandlers;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class Shadowjump : NinjaSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Shadowjump", null,
|
||||
-1,
|
||||
9002
|
||||
);
|
||||
public class Shadowjump : NinjaSpell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo(
|
||||
"Shadowjump", null,
|
||||
-1,
|
||||
9002
|
||||
);
|
||||
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds( 1.0 );
|
||||
public Shadowjump(Mobile caster, Item scroll) : base(caster, scroll, m_Info)
|
||||
{
|
||||
}
|
||||
|
||||
public override double RequiredSkill => 50.0;
|
||||
public override int RequiredMana => 15;
|
||||
public override TimeSpan CastDelayBase => TimeSpan.FromSeconds(1.0);
|
||||
|
||||
public override bool BlockedByAnimalForm => false;
|
||||
public override double RequiredSkill => 50.0;
|
||||
public override int RequiredMana => 15;
|
||||
|
||||
public Shadowjump( Mobile caster, Item scroll ) : base( caster, scroll, m_Info )
|
||||
{
|
||||
}
|
||||
public override bool BlockedByAnimalForm => false;
|
||||
|
||||
public override bool CheckCast()
|
||||
{
|
||||
PlayerMobile pm = Caster as PlayerMobile; // IsStealthing should be moved to Server.Mobiles
|
||||
if ( !pm.IsStealthing )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063087 ); // You must be in stealth mode to use this ability.
|
||||
return false;
|
||||
}
|
||||
public override bool CheckCast()
|
||||
{
|
||||
PlayerMobile pm = Caster as PlayerMobile; // IsStealthing should be moved to Server.Mobiles
|
||||
if (!pm.IsStealthing)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
return base.CheckCast();
|
||||
}
|
||||
return base.CheckCast();
|
||||
}
|
||||
|
||||
public override bool CheckDisturb( DisturbType type, bool firstCircle, bool resistable )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public override bool CheckDisturb(DisturbType type, bool firstCircle, bool resistable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063088 ); // You prepare to perform a Shadowjump.
|
||||
Caster.Target = new InternalTarget( this );
|
||||
}
|
||||
public override void OnCast()
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063088); // You prepare to perform a Shadowjump.
|
||||
Caster.Target = new InternalTarget(this);
|
||||
}
|
||||
|
||||
public void Target( IPoint3D p )
|
||||
{
|
||||
IPoint3D orig = p;
|
||||
Map map = Caster.Map;
|
||||
public void Target(IPoint3D p)
|
||||
{
|
||||
IPoint3D orig = p;
|
||||
Map map = Caster.Map;
|
||||
|
||||
SpellHelper.GetSurfaceTop( ref p );
|
||||
SpellHelper.GetSurfaceTop(ref p);
|
||||
|
||||
Point3D from = Caster.Location;
|
||||
Point3D to = new Point3D( p );
|
||||
Point3D from = Caster.Location;
|
||||
Point3D to = new Point3D(p);
|
||||
|
||||
PlayerMobile pm = Caster as PlayerMobile; // IsStealthing should be moved to Server.Mobiles
|
||||
PlayerMobile pm = Caster as PlayerMobile; // IsStealthing should be moved to Server.Mobiles
|
||||
|
||||
if ( !pm.IsStealthing )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1063087 ); // You must be in stealth mode to use this ability.
|
||||
}
|
||||
else if ( Factions.Sigil.ExistsOn( Caster ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1061632 ); // You can't do that while carrying the sigil.
|
||||
}
|
||||
else if ( Misc.WeightOverloading.IsOverloaded( Caster ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 502359, "", 0x22 ); // Thou art too encumbered to move.
|
||||
}
|
||||
else if ( !SpellHelper.CheckTravel( Caster, TravelCheckType.TeleportFrom ) || !SpellHelper.CheckTravel( Caster, map, to, TravelCheckType.TeleportTo ))
|
||||
{
|
||||
}
|
||||
else if ( map == null || !map.CanSpawnMobile( p.X, p.Y, p.Z ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 502831 ); // Cannot teleport to that spot.
|
||||
}
|
||||
else if ( SpellHelper.CheckMulti( to, map, true, 5 ) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 502831 ); // Cannot teleport to that spot.
|
||||
}
|
||||
else if ( Region.Find( to, map ).GetRegion( typeof( HouseRegion ) ) != null )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 502829 ); // Cannot teleport to that spot.
|
||||
}
|
||||
else if ( CheckSequence() )
|
||||
{
|
||||
SpellHelper.Turn( Caster, orig );
|
||||
if (!pm.IsStealthing)
|
||||
{
|
||||
Caster.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability.
|
||||
}
|
||||
else if (Sigil.ExistsOn(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(1061632); // You can't do that while carrying the sigil.
|
||||
}
|
||||
else if (WeightOverloading.IsOverloaded(Caster))
|
||||
{
|
||||
Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move.
|
||||
}
|
||||
else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom) ||
|
||||
!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo))
|
||||
{
|
||||
}
|
||||
else if (map == null || !map.CanSpawnMobile(p.X, p.Y, p.Z))
|
||||
{
|
||||
Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot.
|
||||
}
|
||||
else if (SpellHelper.CheckMulti(to, map, true, 5))
|
||||
{
|
||||
Caster.SendLocalizedMessage(502831); // Cannot teleport to that spot.
|
||||
}
|
||||
else if (Region.Find(to, map).GetRegion(typeof(HouseRegion)) != null)
|
||||
{
|
||||
Caster.SendLocalizedMessage(502829); // Cannot teleport to that spot.
|
||||
}
|
||||
else if (CheckSequence())
|
||||
{
|
||||
SpellHelper.Turn(Caster, orig);
|
||||
|
||||
Mobile m = Caster;
|
||||
Mobile m = Caster;
|
||||
|
||||
m.Location = to;
|
||||
m.ProcessDelta();
|
||||
m.Location = to;
|
||||
m.ProcessDelta();
|
||||
|
||||
Effects.SendLocationParticles( EffectItem.Create( from, m.Map, EffectItem.DefaultDuration ), 0x3728, 10, 10, 2023 );
|
||||
Effects.SendLocationParticles(EffectItem.Create(from, m.Map, EffectItem.DefaultDuration), 0x3728, 10, 10,
|
||||
2023);
|
||||
|
||||
m.PlaySound( 0x512 );
|
||||
m.PlaySound(0x512);
|
||||
|
||||
SkillHandlers.Stealth.OnUse( m ); // stealth check after the a jump
|
||||
}
|
||||
Stealth.OnUse(m); // stealth check after the a jump
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private Shadowjump m_Owner;
|
||||
FinishSequence();
|
||||
}
|
||||
|
||||
public InternalTarget( Shadowjump owner ) : base( 11, true, TargetFlags.None )
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
public class InternalTarget : Target
|
||||
{
|
||||
private Shadowjump m_Owner;
|
||||
|
||||
protected override void OnTarget( Mobile from, object o )
|
||||
{
|
||||
IPoint3D p = o as IPoint3D;
|
||||
public InternalTarget(Shadowjump owner) : base(11, true, TargetFlags.None)
|
||||
{
|
||||
m_Owner = owner;
|
||||
}
|
||||
|
||||
if ( p != null )
|
||||
m_Owner.Target( p );
|
||||
}
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
IPoint3D p = o as IPoint3D;
|
||||
|
||||
protected override void OnTargetFinish( Mobile from )
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p != null)
|
||||
m_Owner.Target(p);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
m_Owner.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,125 +4,119 @@ using Server.SkillHandlers;
|
|||
|
||||
namespace Server.Spells.Ninjitsu
|
||||
{
|
||||
public class SurpriseAttack : NinjaMove
|
||||
{
|
||||
public SurpriseAttack()
|
||||
{
|
||||
}
|
||||
public class SurpriseAttack : NinjaMove
|
||||
{
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
|
||||
public override int BaseMana => 20;
|
||||
public override double RequiredSkill => Core.ML ? 60.0 : 30.0;
|
||||
public override int BaseMana => 20;
|
||||
public override double RequiredSkill => Core.ML ? 60.0 : 30.0;
|
||||
|
||||
public override TextDefinition AbilityMessage => new TextDefinition( 1063128 ); // You prepare to surprise your prey.
|
||||
public override TextDefinition AbilityMessage => new TextDefinition(1063128); // You prepare to surprise your prey.
|
||||
|
||||
public override bool Validate( Mobile from )
|
||||
{
|
||||
if ( !from.Hidden || from.AllowedStealthSteps <= 0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1063087 ); // You must be in stealth mode to use this ability.
|
||||
return false;
|
||||
}
|
||||
public override bool ValidatesDuringHit => false;
|
||||
|
||||
return base.Validate( from );
|
||||
}
|
||||
public override bool Validate(Mobile from)
|
||||
{
|
||||
if (!from.Hidden || from.AllowedStealthSteps <= 0)
|
||||
{
|
||||
from.SendLocalizedMessage(1063087); // You must be in stealth mode to use this ability.
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool OnBeforeSwing( Mobile attacker, Mobile defender )
|
||||
{
|
||||
bool valid = Validate( attacker ) && CheckMana( attacker, true );
|
||||
return base.Validate(from);
|
||||
}
|
||||
|
||||
if ( valid )
|
||||
{
|
||||
attacker.BeginAction( typeof( Stealth ) );
|
||||
Timer.DelayCall( TimeSpan.FromSeconds( 5.0 ), delegate { attacker.EndAction( typeof( Stealth ) ); } );
|
||||
}
|
||||
public override bool OnBeforeSwing(Mobile attacker, Mobile defender)
|
||||
{
|
||||
bool valid = Validate(attacker) && CheckMana(attacker, true);
|
||||
|
||||
return valid;
|
||||
if (valid)
|
||||
{
|
||||
attacker.BeginAction(typeof(Stealth));
|
||||
Timer.DelayCall(TimeSpan.FromSeconds(5.0), delegate { attacker.EndAction(typeof(Stealth)); });
|
||||
}
|
||||
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
public override bool ValidatesDuringHit => false;
|
||||
public override void OnHit(Mobile attacker, Mobile defender, int damage)
|
||||
{
|
||||
//Validates before swing
|
||||
|
||||
public override void OnHit( Mobile attacker, Mobile defender, int damage )
|
||||
{
|
||||
//Validates before swing
|
||||
ClearCurrentMove(attacker);
|
||||
|
||||
ClearCurrentMove( attacker );
|
||||
attacker.SendLocalizedMessage(1063129); // You catch your opponent off guard with your Surprise Attack!
|
||||
defender.SendLocalizedMessage(1063130); // Your defenses are lowered as your opponent surprises you!
|
||||
|
||||
attacker.SendLocalizedMessage( 1063129 ); // You catch your opponent off guard with your Surprise Attack!
|
||||
defender.SendLocalizedMessage( 1063130 ); // Your defenses are lowered as your opponent surprises you!
|
||||
defender.FixedParticles(0x37B9, 1, 5, 0x26DA, 0, 3, EffectLayer.Head);
|
||||
|
||||
defender.FixedParticles( 0x37B9, 1, 5, 0x26DA, 0, 3, EffectLayer.Head );
|
||||
attacker.RevealingAction();
|
||||
|
||||
attacker.RevealingAction();
|
||||
SurpriseAttackInfo info;
|
||||
|
||||
SurpriseAttackInfo info;
|
||||
if (m_Table.Contains(defender))
|
||||
{
|
||||
info = (SurpriseAttackInfo)m_Table[defender];
|
||||
|
||||
if ( m_Table.Contains( defender ) )
|
||||
{
|
||||
info = (SurpriseAttackInfo)m_Table[defender];
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
info.m_Timer?.Stop();
|
||||
m_Table.Remove(defender);
|
||||
}
|
||||
|
||||
m_Table.Remove( defender );
|
||||
}
|
||||
int ninjitsu = attacker.Skills[SkillName.Ninjitsu].Fixed;
|
||||
|
||||
int ninjitsu = attacker.Skills[SkillName.Ninjitsu].Fixed;
|
||||
int malus = ninjitsu / 60 + (int)Tracking.GetStalkingBonus(attacker, defender);
|
||||
|
||||
int malus = ninjitsu / 60 + (int)Tracking.GetStalkingBonus( attacker, defender );
|
||||
info = new SurpriseAttackInfo(defender, malus);
|
||||
info.m_Timer = Timer.DelayCall(TimeSpan.FromSeconds(8.0), new TimerStateCallback(EndSurprise), info);
|
||||
|
||||
info = new SurpriseAttackInfo( defender, malus );
|
||||
info.m_Timer = Timer.DelayCall( TimeSpan.FromSeconds( 8.0 ), new TimerStateCallback( EndSurprise ), info );
|
||||
m_Table[defender] = info;
|
||||
|
||||
m_Table[defender] = info;
|
||||
CheckGain(attacker);
|
||||
}
|
||||
|
||||
CheckGain( attacker );
|
||||
}
|
||||
public override void OnMiss(Mobile attacker, Mobile defender)
|
||||
{
|
||||
ClearCurrentMove(attacker);
|
||||
|
||||
public override void OnMiss( Mobile attacker, Mobile defender )
|
||||
{
|
||||
ClearCurrentMove( attacker );
|
||||
attacker.SendLocalizedMessage(1063161); // You failed to properly use the element of surprise.
|
||||
|
||||
attacker.SendLocalizedMessage( 1063161 ); // You failed to properly use the element of surprise.
|
||||
attacker.RevealingAction();
|
||||
}
|
||||
|
||||
attacker.RevealingAction();
|
||||
}
|
||||
public static bool GetMalus(Mobile target, ref int malus)
|
||||
{
|
||||
SurpriseAttackInfo info = m_Table[target] as SurpriseAttackInfo;
|
||||
|
||||
if (info == null)
|
||||
return false;
|
||||
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
malus = info.m_Malus;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool GetMalus( Mobile target, ref int malus )
|
||||
{
|
||||
SurpriseAttackInfo info = m_Table[target] as SurpriseAttackInfo;
|
||||
private static void EndSurprise(object state)
|
||||
{
|
||||
SurpriseAttackInfo info = (SurpriseAttackInfo)state;
|
||||
|
||||
if ( info == null )
|
||||
return false;
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
malus = info.m_Malus;
|
||||
return true;
|
||||
}
|
||||
info.m_Target.SendLocalizedMessage(1063131); // Your defenses have returned to normal.
|
||||
|
||||
private class SurpriseAttackInfo
|
||||
{
|
||||
public Mobile m_Target;
|
||||
public int m_Malus;
|
||||
public Timer m_Timer;
|
||||
m_Table.Remove(info.m_Target);
|
||||
}
|
||||
|
||||
public SurpriseAttackInfo( Mobile target, int effect )
|
||||
{
|
||||
m_Target = target;
|
||||
m_Malus = effect;
|
||||
}
|
||||
}
|
||||
private class SurpriseAttackInfo
|
||||
{
|
||||
public int m_Malus;
|
||||
public Mobile m_Target;
|
||||
public Timer m_Timer;
|
||||
|
||||
private static void EndSurprise( object state )
|
||||
{
|
||||
SurpriseAttackInfo info = (SurpriseAttackInfo)state;
|
||||
|
||||
info.m_Timer?.Stop();
|
||||
|
||||
info.m_Target.SendLocalizedMessage( 1063131 ); // Your defenses have returned to normal.
|
||||
|
||||
m_Table.Remove( info.m_Target );
|
||||
}
|
||||
}
|
||||
}
|
||||
public SurpriseAttackInfo(Mobile target, int effect)
|
||||
{
|
||||
m_Target = target;
|
||||
m_Malus = effect;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue