#W# Initial Commit: Avatars Conquest
This commit is contained in:
commit
5df497787a
7510 changed files with 416048 additions and 0 deletions
232
Scripts/Skills/Discordance.cs
Normal file
232
Scripts/Skills/Discordance.cs
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server.Items;
|
||||
using Server.Targeting;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Discordance
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Discordance].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
BaseInstrument.PickInstrument( m, new InstrumentPickedCallback( OnPickedInstrument ) );
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 ); // Cannot use another skill for 1 second
|
||||
}
|
||||
|
||||
public static void OnPickedInstrument( Mobile from, BaseInstrument instrument )
|
||||
{
|
||||
from.RevealingAction();
|
||||
from.SendLocalizedMessage( 1049541 ); // Choose the target for your song of discordance.
|
||||
from.Target = new DiscordanceTarget( from, instrument );
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 6.0 );
|
||||
}
|
||||
|
||||
private class DiscordanceInfo
|
||||
{
|
||||
public Mobile m_From;
|
||||
public Mobile m_Creature;
|
||||
public DateTime m_EndTime;
|
||||
public bool m_Ending;
|
||||
public Timer m_Timer;
|
||||
public int m_Effect;
|
||||
public ArrayList m_Mods;
|
||||
|
||||
public DiscordanceInfo( Mobile from, Mobile creature, int effect, ArrayList mods )
|
||||
{
|
||||
m_From = from;
|
||||
m_Creature = creature;
|
||||
m_EndTime = DateTime.Now;
|
||||
m_Ending = false;
|
||||
m_Effect = effect;
|
||||
m_Mods = mods;
|
||||
|
||||
Apply();
|
||||
}
|
||||
|
||||
public void Apply()
|
||||
{
|
||||
for ( int i = 0; i < m_Mods.Count; ++i )
|
||||
{
|
||||
object mod = m_Mods[i];
|
||||
|
||||
if ( mod is StatMod )
|
||||
m_Creature.AddStatMod( (StatMod) mod );
|
||||
else if ( mod is SkillMod )
|
||||
m_Creature.AddSkillMod( (SkillMod) mod );
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
for ( int i = 0; i < m_Mods.Count; ++i )
|
||||
{
|
||||
object mod = m_Mods[i];
|
||||
|
||||
if ( mod is StatMod )
|
||||
m_Creature.RemoveStatMod( ((StatMod) mod).Name );
|
||||
else if ( mod is SkillMod )
|
||||
m_Creature.RemoveSkillMod( (SkillMod) mod );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Hashtable m_Table = new Hashtable();
|
||||
|
||||
public static bool GetEffect( Mobile targ, ref int effect )
|
||||
{
|
||||
DiscordanceInfo info = m_Table[targ] as DiscordanceInfo;
|
||||
|
||||
if ( info == null )
|
||||
return false;
|
||||
|
||||
effect = info.m_Effect;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ProcessDiscordance( DiscordanceInfo info )
|
||||
{
|
||||
Mobile from = info.m_From;
|
||||
Mobile targ = info.m_Creature;
|
||||
bool ends = false;
|
||||
|
||||
// According to uoherald bard must remain alive, visible, and
|
||||
// within range of the target or the effect ends in 15 seconds.
|
||||
if ( !targ.Alive || targ.Deleted || !from.Alive || from.Hidden )
|
||||
ends = true;
|
||||
else
|
||||
{
|
||||
int range = (int) targ.GetDistanceToSqrt( from );
|
||||
int maxRange = BaseInstrument.GetBardRange( from, SkillName.Discordance );
|
||||
|
||||
if ( from.Map != targ.Map || range > maxRange )
|
||||
ends = true;
|
||||
}
|
||||
|
||||
if ( ends && info.m_Ending && info.m_EndTime < DateTime.Now )
|
||||
{
|
||||
if ( info.m_Timer != null )
|
||||
info.m_Timer.Stop();
|
||||
|
||||
info.Clear();
|
||||
m_Table.Remove( targ );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ends && !info.m_Ending )
|
||||
{
|
||||
info.m_Ending = true;
|
||||
info.m_EndTime = DateTime.Now + TimeSpan.FromSeconds( 15 );
|
||||
}
|
||||
else if ( !ends )
|
||||
{
|
||||
info.m_Ending = false;
|
||||
info.m_EndTime = DateTime.Now;
|
||||
}
|
||||
|
||||
targ.FixedEffect( 0x376A, 1, 32 );
|
||||
}
|
||||
}
|
||||
|
||||
public class DiscordanceTarget : Target
|
||||
{
|
||||
private BaseInstrument m_Instrument;
|
||||
|
||||
public DiscordanceTarget( Mobile from, BaseInstrument inst ) : base( BaseInstrument.GetBardRange( from, SkillName.Discordance ), false, TargetFlags.None )
|
||||
{
|
||||
m_Instrument = inst;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object target )
|
||||
{
|
||||
from.RevealingAction();
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 1.0 );
|
||||
|
||||
if ( !m_Instrument.IsChildOf( from.Backpack ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1062488 ); // The instrument you are trying to play is no longer in your backpack!
|
||||
}
|
||||
else if ( target is Mobile )
|
||||
{
|
||||
Mobile targ = (Mobile)target;
|
||||
|
||||
if ( targ == from || (targ is BaseCreature && ( ((BaseCreature)targ).BardImmune || !from.CanBeHarmful( targ, false ) ) && ((BaseCreature)targ).ControlMaster != from) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049535 ); // A song of discord would have no effect on that.
|
||||
}
|
||||
else if ( m_Table.Contains( targ ) ) //Already discorded
|
||||
{
|
||||
from.SendLocalizedMessage( 1049537 );// Your target is already in discord.
|
||||
}
|
||||
else if ( !targ.Player )
|
||||
{
|
||||
double diff = m_Instrument.GetDifficultyFor( targ ) - 10.0;
|
||||
double music = from.Skills[SkillName.Musicianship].Value;
|
||||
|
||||
if ( music > 100.0 )
|
||||
diff -= (music - 100.0) * 0.5;
|
||||
|
||||
if ( !BaseInstrument.CheckMusicianship( from ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 500612 ); // You play poorly, and there is no effect.
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else if ( from.CheckTargetSkill( SkillName.Discordance, target, diff-25.0, diff+25.0 ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049539 ); // You play the song surpressing your targets strength
|
||||
m_Instrument.PlayInstrumentWell( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
|
||||
ArrayList mods = new ArrayList();
|
||||
int effect;
|
||||
double scalar;
|
||||
|
||||
effect = (int)( from.Skills[SkillName.Discordance].Value / -5.0 );
|
||||
scalar = effect * 0.01;
|
||||
|
||||
mods.Add( new StatMod( StatType.Str, "DiscordanceStr", (int)(targ.RawStr * scalar), TimeSpan.Zero ) );
|
||||
mods.Add( new StatMod( StatType.Int, "DiscordanceInt", (int)(targ.RawInt * scalar), TimeSpan.Zero ) );
|
||||
mods.Add( new StatMod( StatType.Dex, "DiscordanceDex", (int)(targ.RawDex * scalar), TimeSpan.Zero ) );
|
||||
|
||||
for ( int i = 0; i < targ.Skills.Length; ++i )
|
||||
{
|
||||
if ( targ.Skills[i].Value > 0 )
|
||||
mods.Add( new DefaultSkillMod( (SkillName)i, true, targ.Skills[i].Value * scalar ) );
|
||||
}
|
||||
|
||||
DiscordanceInfo info = new DiscordanceInfo( from, targ, Math.Abs( effect ), mods );
|
||||
info.m_Timer = Timer.DelayCall<DiscordanceInfo>( TimeSpan.Zero, TimeSpan.FromSeconds( 1.25 ), new TimerStateCallback<DiscordanceInfo>( ProcessDiscordance ), info );
|
||||
|
||||
m_Table[targ] = info;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1049540 );// You fail to disrupt your target
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 12.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1049535 ); // A song of discord would have no effect on that.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Scripts/Skills/Hiding.cs
Normal file
109
Scripts/Skills/Hiding.cs
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Multis;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Hiding
|
||||
{
|
||||
private static bool m_CombatOverride;
|
||||
|
||||
public static bool CombatOverride
|
||||
{
|
||||
get{ return m_CombatOverride; }
|
||||
set{ m_CombatOverride = value; }
|
||||
}
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[11].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
if ( m.Spell != null )
|
||||
{
|
||||
m.SendLocalizedMessage( 501238 ); // You are busy doing something else and cannot hide.
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
double bonus = 0.0;
|
||||
|
||||
BaseHouse house = BaseHouse.FindHouseAt( m );
|
||||
|
||||
if ( house != null && house.IsFriend( m ) )
|
||||
{
|
||||
bonus = 100.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( house == null )
|
||||
house = BaseHouse.FindHouseAt( new Point3D( m.X - 1, m.Y, 127 ), m.Map, 16 );
|
||||
|
||||
if ( house == null )
|
||||
house = BaseHouse.FindHouseAt( new Point3D( m.X + 1, m.Y, 127 ), m.Map, 16 );
|
||||
|
||||
if ( house == null )
|
||||
house = BaseHouse.FindHouseAt( new Point3D( m.X, m.Y - 1, 127 ), m.Map, 16 );
|
||||
|
||||
if ( house == null )
|
||||
house = BaseHouse.FindHouseAt( new Point3D( m.X, m.Y + 1, 127 ), m.Map, 16 );
|
||||
|
||||
if ( house != null )
|
||||
bonus = 50.0;
|
||||
}
|
||||
|
||||
//int range = 18 - (int)(m.Skills[SkillName.Hiding].Value / 10);
|
||||
int range = Math.Min( (int)((100 - m.Skills[SkillName.Hiding].Value)/2) + 8, 18 ); //Cap of 18 not OSI-exact, intentional difference
|
||||
|
||||
bool badCombat = ( !m_CombatOverride && m.Combatant != null && m.InRange( m.Combatant.Location, range ) && m.Combatant.InLOS( m ) );
|
||||
bool ok = ( !badCombat /*&& m.CheckSkill( SkillName.Hiding, 0.0 - bonus, 100.0 - bonus )*/ );
|
||||
|
||||
if ( ok )
|
||||
{
|
||||
if ( !m_CombatOverride )
|
||||
{
|
||||
foreach ( Mobile check in m.GetMobilesInRange( range ) )
|
||||
{
|
||||
if ( check.InLOS( m ) && check.Combatant == m )
|
||||
{
|
||||
badCombat = true;
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ok = ( !badCombat && m.CheckSkill( SkillName.Hiding, 0.0 - bonus, 100.0 - bonus ) );
|
||||
}
|
||||
|
||||
if ( badCombat )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
m.LocalOverheadMessage( MessageType.Regular, 0x22, 501237 ); // You can't seem to hide right now.
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ok )
|
||||
{
|
||||
m.Hidden = true;
|
||||
m.Warmode = false;
|
||||
m.LocalOverheadMessage( MessageType.Regular, 0x1F4, 501240 ); // You have hidden yourself well.
|
||||
}
|
||||
else
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
m.LocalOverheadMessage( MessageType.Regular, 0x22, 501241 ); // You can't seem to hide here.
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
74
Scripts/Skills/Meditation.cs
Normal file
74
Scripts/Skills/Meditation.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
class Meditation
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[15].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static bool CheckOkayHolding( Item item )
|
||||
{
|
||||
if ( item == null )
|
||||
return true;
|
||||
|
||||
if ( item is Spellbook )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
if ( m.Target != null )
|
||||
{
|
||||
m.SendLocalizedMessage( 501845 ); // You are busy doing something else and cannot focus.
|
||||
|
||||
return TimeSpan.FromSeconds( 5.0 );
|
||||
}
|
||||
else if ( m.Mana >= m.ManaMax )
|
||||
{
|
||||
m.SendLocalizedMessage( 501846 ); // You are at peace.
|
||||
|
||||
return TimeSpan.FromSeconds( 5.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Item oneHanded = m.FindItemOnLayer( Layer.OneHanded );
|
||||
Item twoHanded = m.FindItemOnLayer( Layer.TwoHanded );
|
||||
|
||||
if ( !CheckOkayHolding( oneHanded ) || !CheckOkayHolding( twoHanded ) )
|
||||
{
|
||||
m.SendLocalizedMessage( 502626 ); // Your hands must be free to cast spells or meditate.
|
||||
|
||||
return TimeSpan.FromSeconds( 2.5 );
|
||||
}
|
||||
|
||||
double skillVal = m.Skills[SkillName.Meditation].Value;
|
||||
double chance = (50.0 + (( skillVal - ( m.ManaMax - m.Mana ) ) * 2)) / 100;
|
||||
|
||||
if ( chance > Utility.RandomDouble() )
|
||||
{
|
||||
m.CheckSkill( SkillName.Meditation, 0.0, 100.0 );
|
||||
|
||||
m.SendLocalizedMessage( 501851 ); // You enter a meditative trance.
|
||||
m.Meditating = true;
|
||||
|
||||
if ( m.Player || m.Body.IsHuman )
|
||||
m.PlaySound( 0xF9 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m.SendLocalizedMessage( 501850 ); // You cannot focus your concentration.
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
199
Scripts/Skills/Peacemaking.cs
Normal file
199
Scripts/Skills/Peacemaking.cs
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Peacemaking
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Peacemaking].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
BaseInstrument.PickInstrument( m, new InstrumentPickedCallback( OnPickedInstrument ) );
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 ); // Cannot use another skill for 1 second
|
||||
}
|
||||
|
||||
public static void OnPickedInstrument( Mobile from, BaseInstrument instrument )
|
||||
{
|
||||
from.RevealingAction();
|
||||
from.SendLocalizedMessage( 1049525 ); // Whom do you wish to calm?
|
||||
from.Target = new InternalTarget( from, instrument );
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromHours( 6.0 );
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private BaseInstrument m_Instrument;
|
||||
private bool m_SetSkillTime = true;
|
||||
|
||||
public InternalTarget( Mobile from, BaseInstrument instrument ) : base( BaseInstrument.GetBardRange( from, SkillName.Peacemaking ), false, TargetFlags.None )
|
||||
{
|
||||
m_Instrument = instrument;
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile from )
|
||||
{
|
||||
if ( m_SetSkillTime )
|
||||
from.NextSkillTime = DateTime.Now;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
from.RevealingAction();
|
||||
|
||||
if ( !(targeted is Mobile) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049528 ); // You cannot calm that!
|
||||
}
|
||||
else if ( !m_Instrument.IsChildOf( from.Backpack ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1062488 ); // The instrument you are trying to play is no longer in your backpack!
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SetSkillTime = false;
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 10.0 );
|
||||
|
||||
if ( targeted == from )
|
||||
{
|
||||
// Standard mode : reset combatants for everyone in the area
|
||||
|
||||
if ( !BaseInstrument.CheckMusicianship( from ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 500612 ); // You play poorly, and there is no effect.
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else if ( !from.CheckSkill( SkillName.Peacemaking, 0.0, 120.0 ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 500613 ); // You attempt to calm everyone, but fail.
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 5.0 );
|
||||
m_Instrument.PlayInstrumentWell( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if ( map != null )
|
||||
{
|
||||
int range = BaseInstrument.GetBardRange( from, SkillName.Peacemaking );
|
||||
|
||||
bool calmed = false;
|
||||
|
||||
foreach ( Mobile m in from.GetMobilesInRange( range ) )
|
||||
{
|
||||
if ((m is BaseCreature && ((BaseCreature)m).Uncalmable) || (m is BaseCreature && ((BaseCreature)m).AreaPeaceImmune) || m == from || !from.CanBeHarmful ( m, false ))
|
||||
continue;
|
||||
|
||||
calmed = true;
|
||||
|
||||
m.SendLocalizedMessage( 500616 ); // You hear lovely music, and forget to continue battling!
|
||||
m.Combatant = null;
|
||||
m.Warmode = false;
|
||||
|
||||
if ( m is BaseCreature && !((BaseCreature)m).BardPacified )
|
||||
((BaseCreature)m).Pacify( from, DateTime.Now + TimeSpan.FromSeconds( 1.0 ) );
|
||||
}
|
||||
|
||||
if ( !calmed )
|
||||
from.SendLocalizedMessage( 1049648 ); // You play hypnotic music, but there is nothing in range for you to calm.
|
||||
else
|
||||
from.SendLocalizedMessage( 500615 ); // You play your hypnotic music, stopping the battle.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Target mode : pacify a single target for a longer duration
|
||||
|
||||
Mobile targ = (Mobile)targeted;
|
||||
|
||||
if ( !from.CanBeHarmful( targ, false ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049528 );
|
||||
m_SetSkillTime = true;
|
||||
}
|
||||
else if ( targ is BaseCreature && ((BaseCreature)targ).Uncalmable )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049526 ); // You have no chance of calming that creature.
|
||||
m_SetSkillTime = true;
|
||||
}
|
||||
else if ( targ is BaseCreature && ((BaseCreature)targ).BardPacified )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049527 ); // That creature is already being calmed.
|
||||
m_SetSkillTime = true;
|
||||
}
|
||||
else if ( !BaseInstrument.CheckMusicianship( from ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 500612 ); // You play poorly, and there is no effect.
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 5.0 );
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
double diff = m_Instrument.GetDifficultyFor( targ ) - 10.0;
|
||||
double music = from.Skills[SkillName.Musicianship].Value;
|
||||
|
||||
if ( music > 100.0 )
|
||||
diff -= (music - 100.0) * 0.5;
|
||||
|
||||
if ( !from.CheckTargetSkill( SkillName.Peacemaking, targ, diff - 25.0, diff + 25.0 ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049531 ); // You attempt to calm your target, but fail.
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Instrument.PlayInstrumentWell( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 5.0 );
|
||||
if ( targ is BaseCreature )
|
||||
{
|
||||
BaseCreature bc = (BaseCreature)targ;
|
||||
|
||||
from.SendLocalizedMessage( 1049532 ); // You play hypnotic music, calming your target.
|
||||
|
||||
targ.Combatant = null;
|
||||
targ.Warmode = false;
|
||||
|
||||
double seconds = 100 - (diff / 1.5);
|
||||
|
||||
if ( seconds > 120 )
|
||||
seconds = 120;
|
||||
else if ( seconds < 10 )
|
||||
seconds = 10;
|
||||
|
||||
bc.Pacify( from, DateTime.Now + TimeSpan.FromSeconds( seconds ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1049532 ); // You play hypnotic music, calming your target.
|
||||
|
||||
targ.SendLocalizedMessage( 500616 ); // You hear lovely music, and forget to continue battling!
|
||||
targ.Combatant = null;
|
||||
targ.Warmode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
154
Scripts/Skills/Poisoning.cs
Normal file
154
Scripts/Skills/Poisoning.cs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Poisoning
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Poisoning].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.Target = new InternalTargetPoison();
|
||||
|
||||
m.SendLocalizedMessage( 502137 ); // Select the poison you wish to use
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 ); // 10 second delay before beign able to re-use a skill
|
||||
}
|
||||
|
||||
private class InternalTargetPoison : Target
|
||||
{
|
||||
public InternalTargetPoison() : base ( 2, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( targeted is BasePoisonPotion )
|
||||
{
|
||||
from.SendLocalizedMessage( 502142 ); // To what do you wish to apply the poison?
|
||||
from.Target = new InternalTarget( (BasePoisonPotion)targeted );
|
||||
}
|
||||
else // Not a Poison Potion
|
||||
{
|
||||
from.SendLocalizedMessage( 502139 ); // That is not a poison potion.
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private BasePoisonPotion m_Potion;
|
||||
|
||||
public InternalTarget( BasePoisonPotion potion ) : base ( 2, false, TargetFlags.None )
|
||||
{
|
||||
m_Potion = potion;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( m_Potion.Deleted )
|
||||
return;
|
||||
|
||||
bool startTimer = false;
|
||||
|
||||
if ( targeted is Food )
|
||||
{
|
||||
startTimer = true;
|
||||
}
|
||||
else if ( targeted is BaseWeapon )
|
||||
{
|
||||
BaseWeapon weapon = (BaseWeapon)targeted;
|
||||
|
||||
if ( weapon.Layer == Layer.OneHanded )
|
||||
{
|
||||
// Only Bladed or Piercing weapon can be poisoned
|
||||
startTimer = ( weapon.Type == WeaponType.Slashing || weapon.Type == WeaponType.Piercing );
|
||||
}
|
||||
}
|
||||
|
||||
if ( startTimer )
|
||||
{
|
||||
new InternalTimer( from, (Item)targeted, m_Potion ).Start();
|
||||
|
||||
from.PlaySound( 0x4F );
|
||||
|
||||
m_Potion.Consume();
|
||||
from.AddToBackpack( new Bottle() );
|
||||
}
|
||||
else // Target can't be poisoned
|
||||
{
|
||||
from.SendLocalizedMessage( 502145 ); // You cannot poison that! You can only poison bladed or piercing weapons, food or drink.
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private Mobile m_From;
|
||||
private Item m_Target;
|
||||
private Poison m_Poison;
|
||||
private double m_MinSkill, m_MaxSkill;
|
||||
|
||||
public InternalTimer( Mobile from, Item target, BasePoisonPotion potion ) : base( TimeSpan.FromSeconds( 2.0 ) )
|
||||
{
|
||||
m_From = from;
|
||||
m_Target = target;
|
||||
m_Poison = potion.Poison;
|
||||
m_MinSkill = potion.MinPoisoningSkill;
|
||||
m_MaxSkill = potion.MaxPoisoningSkill;
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( m_From.CheckTargetSkill( SkillName.Poisoning, m_Target, m_MinSkill, m_MaxSkill ) )
|
||||
{
|
||||
if ( m_Target is Food )
|
||||
{
|
||||
((Food)m_Target).Poison = m_Poison;
|
||||
}
|
||||
else if ( m_Target is BaseWeapon )
|
||||
{
|
||||
((BaseWeapon)m_Target).Poison = m_Poison;
|
||||
((BaseWeapon)m_Target).PoisonCharges = 18 - (m_Poison.Level * 2);
|
||||
}
|
||||
|
||||
m_From.SendLocalizedMessage( 1010517 ); // You apply the poison
|
||||
|
||||
Misc.Titles.AwardKarma( m_From, -20, true );
|
||||
}
|
||||
else // Failed
|
||||
{
|
||||
// 5% of chance of getting poisoned if failed
|
||||
if ( m_From.Skills[SkillName.Poisoning].Base < 80.0 && Utility.Random( 20 ) == 0 )
|
||||
{
|
||||
m_From.SendLocalizedMessage( 502148 ); // You make a grave mistake while applying the poison.
|
||||
m_From.ApplyPoison( m_From, m_Poison );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_Target is BaseWeapon )
|
||||
{
|
||||
BaseWeapon weapon = (BaseWeapon)m_Target;
|
||||
|
||||
if ( weapon.Type == WeaponType.Slashing )
|
||||
m_From.SendLocalizedMessage( 1010516 ); // You fail to apply a sufficient dose of poison on the blade
|
||||
else
|
||||
m_From.SendLocalizedMessage( 1010518 ); // You fail to apply a sufficient dose of poison
|
||||
}
|
||||
else
|
||||
{
|
||||
m_From.SendLocalizedMessage( 1010518 ); // You fail to apply a sufficient dose of poison
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
160
Scripts/Skills/Provocation.cs
Normal file
160
Scripts/Skills/Provocation.cs
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Provocation
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Provocation].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
BaseInstrument.PickInstrument( m, new InstrumentPickedCallback( OnPickedInstrument ) );
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 ); // Cannot use another skill for 1 second
|
||||
}
|
||||
|
||||
public static void OnPickedInstrument( Mobile from, BaseInstrument instrument )
|
||||
{
|
||||
from.RevealingAction();
|
||||
from.SendLocalizedMessage( 501587 ); // Whom do you wish to incite?
|
||||
from.Target = new InternalFirstTarget( from, instrument );
|
||||
}
|
||||
|
||||
private class InternalFirstTarget : Target
|
||||
{
|
||||
private BaseInstrument m_Instrument;
|
||||
|
||||
public InternalFirstTarget( Mobile from, BaseInstrument instrument ) : base( BaseInstrument.GetBardRange( from, SkillName.Provocation ), false, TargetFlags.None )
|
||||
{
|
||||
m_Instrument = instrument;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
from.RevealingAction();
|
||||
|
||||
if ( targeted is BaseCreature && from.CanBeHarmful( (Mobile)targeted, true ) )
|
||||
{
|
||||
BaseCreature creature = (BaseCreature)targeted;
|
||||
|
||||
if ( !m_Instrument.IsChildOf( from.Backpack ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1062488 ); // The instrument you are trying to play is no longer in your backpack!
|
||||
}
|
||||
else if ( creature.Controlled )
|
||||
{
|
||||
from.SendLocalizedMessage( 501590 ); // They are too loyal to their master to be provoked.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.RevealingAction();
|
||||
m_Instrument.PlayInstrumentWell( from );
|
||||
from.SendLocalizedMessage( 1008085 ); // You play your music and your target becomes angered. Whom do you wish them to attack?
|
||||
from.Target = new InternalSecondTarget( from, m_Instrument, creature );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501589 ); // You can't incite that!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalSecondTarget : Target
|
||||
{
|
||||
private BaseCreature m_Creature;
|
||||
private BaseInstrument m_Instrument;
|
||||
|
||||
public InternalSecondTarget( Mobile from, BaseInstrument instrument, BaseCreature creature ) : base( BaseInstrument.GetBardRange( from, SkillName.Provocation ), false, TargetFlags.None )
|
||||
{
|
||||
m_Instrument = instrument;
|
||||
m_Creature = creature;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
from.RevealingAction();
|
||||
|
||||
if ( targeted is BaseCreature )
|
||||
{
|
||||
BaseCreature creature = (BaseCreature)targeted;
|
||||
|
||||
if ( !m_Instrument.IsChildOf( from.Backpack ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1062488 ); // The instrument you are trying to play is no longer in your backpack!
|
||||
}
|
||||
else if ( m_Creature.Unprovokable )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049446 ); // You have no chance of provoking those creatures.
|
||||
}
|
||||
else if ( creature.Unprovokable )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049446 ); // You have no chance of provoking those creatures.
|
||||
}
|
||||
else if ( m_Creature.Map != creature.Map || !m_Creature.InRange( creature, BaseInstrument.GetBardRange( from, SkillName.Provocation ) ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049450 ); // The creatures you are trying to provoke are too far away from each other for your music to have an effect.
|
||||
}
|
||||
else if ( m_Creature != creature )
|
||||
{
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 10.0 );
|
||||
|
||||
double diff = ((m_Instrument.GetDifficultyFor( m_Creature ) + m_Instrument.GetDifficultyFor( creature )) * 0.5) - 5.0;
|
||||
double music = from.Skills[SkillName.Musicianship].Value;
|
||||
|
||||
if ( music > 100.0 )
|
||||
diff -= (music - 100.0) * 0.5;
|
||||
|
||||
if ( from.CanBeHarmful( m_Creature, true ) && from.CanBeHarmful( creature, true ) )
|
||||
{
|
||||
if ( !BaseInstrument.CheckMusicianship( from ) )
|
||||
{
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 5.0 );
|
||||
from.SendLocalizedMessage( 500612 ); // You play poorly, and there is no effect.
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
//from.DoHarmful( m_Creature );
|
||||
//from.DoHarmful( creature );
|
||||
|
||||
if ( !from.CheckTargetSkill( SkillName.Provocation, creature, diff-25.0, diff+25.0 ) )
|
||||
{
|
||||
from.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 5.0 );
|
||||
from.SendLocalizedMessage( 501599 ); // Your music fails to incite enough anger.
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501602 ); // Your music succeeds, as you start a fight.
|
||||
m_Instrument.PlayInstrumentWell( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
m_Creature.Provoke( from, creature, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501593 ); // You can't tell someone to attack themselves!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501589 ); // You can't incite that!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
98
Scripts/Skills/RemoveTrap.cs
Normal file
98
Scripts/Skills/RemoveTrap.cs
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class RemoveTrap
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.RemoveTrap].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.Target = new InternalTarget();
|
||||
|
||||
m.SendLocalizedMessage( 502368 ); // Wich trap will you attempt to disarm?
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 ); // 10 second delay before beign able to re-use a skill
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base ( 2, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( targeted is LootChest )
|
||||
((LootChest)targeted).Setup();
|
||||
|
||||
if ( targeted is Mobile )
|
||||
{
|
||||
from.SendLocalizedMessage( 502816 ); // You feel that such an action would be inappropriate
|
||||
}
|
||||
else if ( targeted is TrapableContainer )
|
||||
{
|
||||
TrapableContainer targ = (TrapableContainer)targeted;
|
||||
|
||||
from.Direction = from.GetDirectionTo( targ );
|
||||
|
||||
if ( targ.TrapType == TrapType.None )
|
||||
{
|
||||
from.SendLocalizedMessage( 502373 ); // That doesn't appear to be trapped
|
||||
return;
|
||||
}
|
||||
|
||||
from.PlaySound( 0x241 );
|
||||
|
||||
if ( from.CheckTargetSkill( SkillName.RemoveTrap, targ, targ.TrapPower, targ.TrapPower + 30 ) )
|
||||
{
|
||||
targ.TrapPower = 0;
|
||||
targ.TrapLevel = 0;
|
||||
targ.TrapType = TrapType.None;
|
||||
from.SendLocalizedMessage( 502377 ); // You successfully render the trap harmless
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 502372 ); // You fail to disarm the trap... but you don't set it off
|
||||
}
|
||||
}
|
||||
else if ( targeted is BaseDoor )
|
||||
{
|
||||
BaseDoor targ = (BaseDoor)targeted;
|
||||
|
||||
from.Direction = from.GetDirectionTo( targ );
|
||||
|
||||
if ( targ.TrapType == TrapType.None )
|
||||
{
|
||||
from.SendLocalizedMessage( 502373 ); // That doesn't appear to be trapped
|
||||
return;
|
||||
}
|
||||
|
||||
from.PlaySound( 0x241 );
|
||||
|
||||
if ( from.CheckTargetSkill( SkillName.RemoveTrap, targ, targ.TrapPower, targ.TrapPower + 30 ) )
|
||||
{
|
||||
targ.TrapPower = 0;
|
||||
targ.TrapLevel = 0;
|
||||
targ.TrapType = TrapType.None;
|
||||
from.SendLocalizedMessage( 502377 ); // You successfully render the trap harmless
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 502372 ); // You fail to disarm the trap... but you don't set it off
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 502373 ); // That does'nt appear to be trapped
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
134
Scripts/Skills/Searching.cs
Normal file
134
Scripts/Skills/Searching.cs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Multis;
|
||||
using Server.Targeting;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Searching
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Searching].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile src )
|
||||
{
|
||||
src.SendLocalizedMessage( 500819 );//Where will you search?
|
||||
src.Target = new InternalTarget();
|
||||
|
||||
return TimeSpan.FromSeconds( 6.0 );
|
||||
}
|
||||
|
||||
public static int TotalSearchSkill( Mobile m )
|
||||
{
|
||||
m.CheckSkill( SkillName.Searching, -5.0, 110.0 ); // Passive Check
|
||||
|
||||
int skill = (int)(m.Skills[SkillName.Searching].Value/2);
|
||||
|
||||
if ( m.Region is DungeonRegion )
|
||||
{
|
||||
skill = (int)(m.Skills[SkillName.Searching].Value);
|
||||
|
||||
if ( !( m.BeginAction( typeof( LightCycle ) ) ) )
|
||||
skill = skill + 25;
|
||||
|
||||
if ( m.FindItemOnLayer( Layer.TwoHanded ) != null )
|
||||
{
|
||||
Item item = m.FindItemOnLayer( Layer.TwoHanded );
|
||||
|
||||
if ( item is BaseEquipableLight && ( item.ItemID == 0xA15 || item.ItemID == 0xA17 || item.ItemID == 0xA22 || item.ItemID == 0xA0F || item.ItemID == 0xA12 ) )
|
||||
skill = skill + 25;
|
||||
}
|
||||
}
|
||||
|
||||
return skill;
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base( 12, true, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile src, object targ )
|
||||
{
|
||||
bool foundAnyone = false;
|
||||
|
||||
Point3D p;
|
||||
if ( targ is Mobile )
|
||||
p = ((Mobile)targ).Location;
|
||||
else if ( targ is Item )
|
||||
p = ((Item)targ).Location;
|
||||
else if ( targ is IPoint3D )
|
||||
p = new Point3D( (IPoint3D)targ );
|
||||
else
|
||||
p = src.Location;
|
||||
|
||||
double srcSkill = src.Skills[SkillName.Searching].Value;
|
||||
int range = (int)(srcSkill / 10.0);
|
||||
|
||||
if ( !src.CheckSkill( SkillName.Searching, 0.0, 100.0 ) )
|
||||
range /= 2;
|
||||
|
||||
BaseHouse house = BaseHouse.FindHouseAt( p, src.Map, 16 );
|
||||
|
||||
bool inHouse = ( house != null && house.IsFriend( src ) );
|
||||
|
||||
if ( inHouse )
|
||||
range = 22;
|
||||
|
||||
if ( range > 0 )
|
||||
{
|
||||
IPooledEnumerable inRange = src.Map.GetMobilesInRange( p, range );
|
||||
|
||||
foreach ( Mobile trg in inRange )
|
||||
{
|
||||
if ( trg.Hidden && src != trg )
|
||||
{
|
||||
double ss = srcSkill + Utility.Random( 21 ) - 10;
|
||||
double ts = trg.Skills[SkillName.Hiding].Value + Utility.Random( 21 ) - 10;
|
||||
|
||||
if ( src.AccessLevel >= trg.AccessLevel && ( ss >= ts || ( inHouse && house.IsInside( trg ) ) ) )
|
||||
{
|
||||
trg.RevealingAction();
|
||||
trg.SendLocalizedMessage( 500814 ); // You have been revealed!
|
||||
foundAnyone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inRange.Free();
|
||||
|
||||
IPooledEnumerable inArea = src.Map.GetItemsInRange( p, range );
|
||||
|
||||
foreach ( Item trg in inArea )
|
||||
{
|
||||
if (
|
||||
trg is SecretBookDoor ||
|
||||
trg is SecretStoneDoor1 ||
|
||||
trg is SecretDungeonDoor ||
|
||||
trg is SecretStoneDoor2 ||
|
||||
trg is SecretWoodenDoor ||
|
||||
trg is SecretLightWoodDoor ||
|
||||
trg is SecretStoneDoor3 )
|
||||
{
|
||||
BaseDoor door = (BaseDoor)trg;
|
||||
door.OnDoubleClick(src);
|
||||
foundAnyone = true;
|
||||
}
|
||||
}
|
||||
|
||||
inArea.Free();
|
||||
}
|
||||
|
||||
if ( !foundAnyone )
|
||||
{
|
||||
src.SendLocalizedMessage( 500817 ); // You can see nothing hidden there.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
574
Scripts/Skills/SkillCheck.cs
Normal file
574
Scripts/Skills/SkillCheck.cs
Normal file
|
|
@ -0,0 +1,574 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Misc
|
||||
{
|
||||
public enum Trades
|
||||
{
|
||||
Alchemy = 0,
|
||||
Blacksmith = 1,
|
||||
Carpentry = 2,
|
||||
Cartography = 3,
|
||||
Cooking = 4,
|
||||
Fishing = 5,
|
||||
Fletching = 6,
|
||||
Inscribe = 7,
|
||||
Lumberjacking = 8,
|
||||
Mining = 9,
|
||||
Tailoring = 10,
|
||||
Tinkering = 11,
|
||||
Musicianship = 12,
|
||||
Magery = 13
|
||||
}
|
||||
|
||||
public class SkillCheck
|
||||
{
|
||||
private static readonly bool AntiMacroCode = Server.Misc.Settings.AllowMacroing();
|
||||
|
||||
public static TimeSpan AntiMacroExpire = TimeSpan.FromMinutes( 5.0 ); //How long do we remember targets/locations?
|
||||
public const int Allowance = 3; //How many times may we use the same location/target for gain
|
||||
private const int LocationSize = 5; //The size of eeach location, make this smaller so players dont have to move as far
|
||||
private static bool[] UseAntiMacro = new bool[]
|
||||
{
|
||||
// true if this skill uses the anti-macro code, false if it does not
|
||||
|
||||
false,// Archery
|
||||
false,// Bludgeoning
|
||||
false,// Fencing
|
||||
false,// Swords
|
||||
false,// Tactics
|
||||
false,// Parry
|
||||
false,// Concentration
|
||||
true,// Discordance
|
||||
false,// Dodging
|
||||
false,// Hand-to-Hand
|
||||
true,// Healing
|
||||
true,// Hiding
|
||||
true,// Lockpicking
|
||||
true,// Magery
|
||||
true,// MagicResist
|
||||
true,// Meditation
|
||||
true,// Musicianship
|
||||
true,// Peacemaking
|
||||
true,// Poisoning
|
||||
true,// Provocation
|
||||
true,// RemoveTrap
|
||||
true,// Searching
|
||||
true,// Stealing
|
||||
true,// Stealth
|
||||
true// Tracking
|
||||
};
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Mobile.SkillCheckLocationHandler = new SkillCheckLocationHandler( Mobile_SkillCheckLocation );
|
||||
Mobile.SkillCheckDirectLocationHandler = new SkillCheckDirectLocationHandler( Mobile_SkillCheckDirectLocation );
|
||||
|
||||
Mobile.SkillCheckTargetHandler = new SkillCheckTargetHandler( Mobile_SkillCheckTarget );
|
||||
Mobile.SkillCheckDirectTargetHandler = new SkillCheckDirectTargetHandler( Mobile_SkillCheckDirectTarget );
|
||||
}
|
||||
|
||||
public static string TradeName( Trades trade )
|
||||
{
|
||||
if ( trade == Trades.Alchemy ){ return "Alchemy"; }
|
||||
else if ( trade == Trades.Blacksmith ){ return "Blacksmithing"; }
|
||||
else if ( trade == Trades.Carpentry ){ return "Carpentry"; }
|
||||
else if ( trade == Trades.Cartography ){ return "Cartography"; }
|
||||
else if ( trade == Trades.Cooking ){ return "Cooking"; }
|
||||
else if ( trade == Trades.Fishing ){ return "Fishing"; }
|
||||
else if ( trade == Trades.Fletching ){ return "Fletching"; }
|
||||
else if ( trade == Trades.Inscribe ){ return "Inscription"; }
|
||||
else if ( trade == Trades.Lumberjacking ){ return "Lumberjacking"; }
|
||||
else if ( trade == Trades.Mining ){ return "Mining"; }
|
||||
else if ( trade == Trades.Tailoring ){ return "Tailoring"; }
|
||||
else if ( trade == Trades.Tinkering ){ return "Tinkering"; }
|
||||
else if ( trade == Trades.Magery ){ return "Magery"; }
|
||||
else if ( trade == Trades.Musicianship ){ return "Musicianship"; }
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static double TradeSkill( Mobile m, Trades trade, bool raw )
|
||||
{
|
||||
double value = 10.0;
|
||||
|
||||
if ( m is PlayerMobile )
|
||||
{
|
||||
PlayerMobile pm = (PlayerMobile)m;
|
||||
|
||||
if ( trade == Trades.Alchemy ){ value += (m.Int*0.75)+(m.Dex*0.25); if ( !raw && pm.NpcGuild == NpcGuild.AlchemistsGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Blacksmith ){ value += (m.Str*0.85)+(m.Dex*0.15); if ( !raw && pm.NpcGuild == NpcGuild.BlacksmithsGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Carpentry ){ value += (m.Dex*0.6)+(m.Str*0.4); if ( !raw && pm.NpcGuild == NpcGuild.CarpentryGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Cartography ){ value += (m.Int*0.7)+(m.Dex*0.3); if ( !raw && pm.NpcGuild == NpcGuild.LibrariansGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Cooking ){ value += (m.Int*0.75)+(m.Dex*0.25); if ( !raw ){ value += 10; } }
|
||||
else if ( trade == Trades.Fishing ){ value += (m.Str*0.6)+(m.Dex*0.4); if ( !raw && pm.NpcGuild == NpcGuild.MarinersGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Fletching ){ value += (m.Dex*0.7)+(m.Str*0.3); if ( !raw && pm.NpcGuild == NpcGuild.RangersGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Inscribe ){ value += (m.Int*0.85)+(m.Dex*0.15); if ( !raw && pm.NpcGuild == NpcGuild.LibrariansGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Lumberjacking ){ value += (m.Str*0.8)+(m.Dex*0.2); if ( !raw && pm.NpcGuild == NpcGuild.CarpentryGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Mining ){ value += (double)(m.Str); if ( !raw && pm.NpcGuild == NpcGuild.BlacksmithsGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Tailoring ){ value += (m.Dex*0.65)+(m.Int*0.35); if ( !raw && pm.NpcGuild == NpcGuild.TailorsGuild ){ value += 20; } }
|
||||
else if ( trade == Trades.Tinkering ){ value += (m.Dex*0.5)+(m.Int*0.5); if ( !raw && pm.NpcGuild == NpcGuild.TinkersGuild ){ value += 20; } }
|
||||
}
|
||||
|
||||
if ( value > 100 )
|
||||
value = 100;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static string TradeStat( Trades trade )
|
||||
{
|
||||
string stat = "STR";
|
||||
|
||||
if ( trade == Trades.Alchemy ){ if ( Utility.RandomMinMax(1,100) <= 75 ){ stat = "INT"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Blacksmith ){ if ( Utility.RandomMinMax(1,100) <= 85 ){ stat = "STR"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Carpentry ){ if ( Utility.RandomMinMax(1,100) <= 60 ){ stat = "DEX"; } else { stat = "STR"; } }
|
||||
else if ( trade == Trades.Cartography ){ if ( Utility.RandomMinMax(1,100) <= 70 ){ stat = "INT"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Cooking ){ if ( Utility.RandomMinMax(1,100) <= 75 ){ stat = "INT"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Fishing ){ if ( Utility.RandomMinMax(1,100) <= 60 ){ stat = "STR"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Fletching ){ if ( Utility.RandomMinMax(1,100) <= 70 ){ stat = "DEX"; } else { stat = "STR"; } }
|
||||
else if ( trade == Trades.Inscribe ){ if ( Utility.RandomMinMax(1,100) <= 85 ){ stat = "INT"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Lumberjacking ){ if ( Utility.RandomMinMax(1,100) <= 80 ){ stat = "STR"; } else { stat = "DEX"; } }
|
||||
else if ( trade == Trades.Mining ){ stat = "STR"; }
|
||||
else if ( trade == Trades.Tailoring ){ if ( Utility.RandomMinMax(1,100) <= 65 ){ stat = "DEX"; } else { stat = "INT"; } }
|
||||
else if ( trade == Trades.Tinkering ){ if ( Utility.RandomMinMax(1,100) <= 50 ){ stat = "DEX"; } else { stat = "INT"; } }
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
public static double GetRandomNumber( double minimum, double maximum )
|
||||
{
|
||||
Random random = new Random();
|
||||
return random.NextDouble() * (maximum - minimum) + minimum;
|
||||
}
|
||||
|
||||
public static bool TestTrade( Mobile m, Trades trade, double min, double max )
|
||||
{
|
||||
if ( trade == Trades.Magery )
|
||||
{
|
||||
if ( m.Skills[SkillName.Magery].Value >= GetRandomNumber( min, max ) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if ( trade == Trades.Musicianship )
|
||||
{
|
||||
if ( m.Skills[SkillName.Musicianship].Value >= GetRandomNumber( min, max ) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if ( TradeSkill( m, trade, false ) >= GetRandomNumber( min, max ) )
|
||||
{
|
||||
double gc = (double)(m.Skills.Cap - m.Skills.Total) / m.Skills.Cap;
|
||||
gc += ( 100 - TradeSkill( m, trade, true ) ) / 100;
|
||||
gc /= 2;
|
||||
|
||||
gc += 0.5;
|
||||
gc /= 2;
|
||||
|
||||
gc *= 1.0;
|
||||
|
||||
if ( gc < 0.01 )
|
||||
gc = 0.01;
|
||||
|
||||
if ( gc >= Utility.RandomDouble() )
|
||||
TradeStatGain( m, TradeStat( trade ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void TradeStatGain( Mobile from, string stat )
|
||||
{
|
||||
if ( stat == "STR" && from.StrLock == StatLockType.Up && (0.5 / 33.3) > Utility.RandomDouble() )
|
||||
GainStat( from, Stat.Str );
|
||||
else if ( stat == "DEX" && from.DexLock == StatLockType.Up && (0.5 / 33.3) > Utility.RandomDouble() )
|
||||
GainStat( from, Stat.Dex );
|
||||
else if ( stat == "INT" && from.IntLock == StatLockType.Up && (0.5 / 33.3) > Utility.RandomDouble() )
|
||||
GainStat( from, Stat.Int );
|
||||
}
|
||||
|
||||
public static bool IsGuildSkill( Mobile from, SkillName skillName )
|
||||
{
|
||||
if ( from is PlayerMobile )
|
||||
{
|
||||
PlayerMobile pm = (PlayerMobile)from;
|
||||
|
||||
if ( pm.NpcGuild == NpcGuild.MagesGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Concentration ){ return true; }
|
||||
else if ( skillName == SkillName.Magery ){ return true; }
|
||||
else if ( skillName == SkillName.Meditation ){ return true; }
|
||||
}
|
||||
else if ( pm.NpcGuild == NpcGuild.WarriorsGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Fencing ){ return true; }
|
||||
else if ( skillName == SkillName.Bludgeoning ){ return true; }
|
||||
else if ( skillName == SkillName.Parry ){ return true; }
|
||||
else if ( skillName == SkillName.Swords ){ return true; }
|
||||
else if ( skillName == SkillName.Tactics ){ return true; }
|
||||
}
|
||||
else if ( pm.NpcGuild == NpcGuild.ThievesGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Hiding ){ return true; }
|
||||
else if ( skillName == SkillName.Lockpicking ){ return true; }
|
||||
else if ( skillName == SkillName.Stealing ){ return true; }
|
||||
else if ( skillName == SkillName.Stealth ){ return true; }
|
||||
}
|
||||
else if ( pm.NpcGuild == NpcGuild.RangersGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Archery ){ return true; }
|
||||
else if ( skillName == SkillName.Tracking ){ return true; }
|
||||
else if ( skillName == SkillName.Tactics ){ return true; }
|
||||
}
|
||||
else if ( pm.NpcGuild == NpcGuild.HealersGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Healing ){ return true; }
|
||||
}
|
||||
else if ( pm.NpcGuild == NpcGuild.BardsGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Discordance ){ return true; }
|
||||
else if ( skillName == SkillName.Musicianship ){ return true; }
|
||||
else if ( skillName == SkillName.Peacemaking ){ return true; }
|
||||
else if ( skillName == SkillName.Provocation ){ return true; }
|
||||
}
|
||||
else if ( pm.NpcGuild == NpcGuild.AssassinsGuild )
|
||||
{
|
||||
if ( skillName == SkillName.Fencing ){ return true; }
|
||||
else if ( skillName == SkillName.Hiding ){ return true; }
|
||||
else if ( skillName == SkillName.Poisoning ){ return true; }
|
||||
else if ( skillName == SkillName.Stealth ){ return true; }
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsHealSkill( Mobile from, SkillName skillName )
|
||||
{
|
||||
if ( from is PlayerMobile )
|
||||
{
|
||||
PlayerMobile pm = (PlayerMobile)from;
|
||||
|
||||
if ( pm.NpcGuild == NpcGuild.HealersGuild )
|
||||
if ( skillName == SkillName.Healing ){ return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckLocation( Mobile from, SkillName skillName, double minSkill, double maxSkill )
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if ( skill == null )
|
||||
return false;
|
||||
|
||||
double value = skill.Value;
|
||||
|
||||
if ( value < minSkill )
|
||||
return false; // Too difficult
|
||||
else if ( value >= maxSkill )
|
||||
return true; // No challenge
|
||||
|
||||
double chance = (value - minSkill) / (maxSkill - minSkill);
|
||||
|
||||
Point2D loc = new Point2D( from.Location.X / LocationSize, from.Location.Y / LocationSize );
|
||||
return CheckSkill( from, skill, loc, chance );
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckDirectLocation( Mobile from, SkillName skillName, double chance )
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if ( skill == null )
|
||||
return false;
|
||||
|
||||
if ( chance < 0.0 )
|
||||
return false; // Too difficult
|
||||
else if ( chance >= 1.0 )
|
||||
return true; // No challenge
|
||||
|
||||
Point2D loc = new Point2D( from.Location.X / LocationSize, from.Location.Y / LocationSize );
|
||||
return CheckSkill( from, skill, loc, chance );
|
||||
}
|
||||
|
||||
public static bool CheckSkill( Mobile from, Skill skill, object amObj, double chance )
|
||||
{
|
||||
SkillName skillName = skill.SkillName;
|
||||
|
||||
if ( from.Skills.Cap == 0 )
|
||||
return false;
|
||||
|
||||
double gainer = 2.0;
|
||||
|
||||
if ( from is PlayerMobile )
|
||||
{
|
||||
if ( IsGuildSkill( from, skillName ) )
|
||||
{
|
||||
switch( Utility.RandomMinMax( 0, 5 ) )
|
||||
{
|
||||
case 0: gainer = 1.5; break;
|
||||
case 1: gainer = 1.4; break;
|
||||
case 2: gainer = 1.3; break;
|
||||
case 3: gainer = 1.2; break;
|
||||
case 4: gainer = 1.1; break;
|
||||
case 5: gainer = 1.0; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( IsHealSkill( from, skillName ) )
|
||||
gainer = 1.0;
|
||||
|
||||
bool success = ( chance >= Utility.RandomDouble() );
|
||||
double gc = (double)(from.Skills.Cap - from.Skills.Total) / from.Skills.Cap;
|
||||
gc += ( skill.Cap - skill.Base ) / skill.Cap;
|
||||
gc /= gainer;
|
||||
|
||||
gc += ( 1.0 - chance ) * ( success ? 0.5 : 0.2 );
|
||||
gc /= gainer;
|
||||
|
||||
gc *= skill.Info.GainFactor;
|
||||
|
||||
if ( gc < 0.01 )
|
||||
gc = 0.01;
|
||||
|
||||
if ( from is BaseCreature && ((BaseCreature)from).Controlled )
|
||||
gc *= 2;
|
||||
|
||||
if ( from.Alive && ( ( gc >= Utility.RandomDouble() && AllowGain( from, skill, amObj ) ) || skill.Base < 10.0 ) )
|
||||
Gain( from, skill );
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckTarget( Mobile from, SkillName skillName, object target, double minSkill, double maxSkill )
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if ( skill == null )
|
||||
return false;
|
||||
|
||||
double value = skill.Value;
|
||||
|
||||
if ( value < minSkill )
|
||||
return false; // Too difficult
|
||||
else if ( value >= maxSkill )
|
||||
return true; // No challenge
|
||||
|
||||
double chance = (value - minSkill) / (maxSkill - minSkill);
|
||||
|
||||
return CheckSkill( from, skill, target, chance );
|
||||
}
|
||||
|
||||
public static bool Mobile_SkillCheckDirectTarget( Mobile from, SkillName skillName, object target, double chance )
|
||||
{
|
||||
Skill skill = from.Skills[skillName];
|
||||
|
||||
if ( skill == null )
|
||||
return false;
|
||||
|
||||
if ( chance < 0.0 )
|
||||
return false; // Too difficult
|
||||
else if ( chance >= 1.0 )
|
||||
return true; // No challenge
|
||||
|
||||
return CheckSkill( from, skill, target, chance );
|
||||
}
|
||||
|
||||
private static bool AllowGain( Mobile from, Skill skill, object obj )
|
||||
{
|
||||
if ( AntiMacroCode && from is PlayerMobile && UseAntiMacro[skill.Info.SkillID] )
|
||||
return ((PlayerMobile)from).AntiMacroCheck( skill, obj );
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
public enum Stat { Str, Dex, Int }
|
||||
|
||||
public static void Gain( Mobile from, Skill skill )
|
||||
{
|
||||
if ( from is BaseCreature && ((BaseCreature)from).IsDeadPet )
|
||||
return;
|
||||
|
||||
if ( skill.Base < skill.Cap && skill.Lock == SkillLock.Up )
|
||||
{
|
||||
int toGain = 1;
|
||||
|
||||
if ( skill.Base <= 10.0 )
|
||||
toGain = Utility.Random( 4 ) + 1;
|
||||
|
||||
Skills skills = from.Skills;
|
||||
|
||||
if ( from.Player && ( skills.Total / skills.Cap ) >= Utility.RandomDouble() )//( skills.Total >= skills.Cap )
|
||||
{
|
||||
for ( int i = 0; i < skills.Length; ++i )
|
||||
{
|
||||
Skill toLower = skills[i];
|
||||
|
||||
if ( toLower != skill && toLower.Lock == SkillLock.Down && toLower.BaseFixedPoint >= toGain )
|
||||
{
|
||||
toLower.BaseFixedPoint -= toGain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !from.Player || (skills.Total + toGain) <= skills.Cap )
|
||||
{
|
||||
skill.BaseFixedPoint += toGain;
|
||||
}
|
||||
}
|
||||
|
||||
if ( skill.Lock == SkillLock.Up )
|
||||
{
|
||||
SkillInfo info = skill.Info;
|
||||
|
||||
if ( from.StrLock == StatLockType.Up && (info.StrGain / 33.3) > Utility.RandomDouble() )
|
||||
GainStat( from, Stat.Str );
|
||||
else if ( from.DexLock == StatLockType.Up && (info.DexGain / 33.3) > Utility.RandomDouble() )
|
||||
GainStat( from, Stat.Dex );
|
||||
else if ( from.IntLock == StatLockType.Up && (info.IntGain / 33.3) > Utility.RandomDouble() )
|
||||
GainStat( from, Stat.Int );
|
||||
}
|
||||
}
|
||||
|
||||
public static bool CanLower( Mobile from, Stat stat )
|
||||
{
|
||||
switch ( stat )
|
||||
{
|
||||
case Stat.Str: return ( from.StrLock == StatLockType.Down && from.RawStr > 10 );
|
||||
case Stat.Dex: return ( from.DexLock == StatLockType.Down && from.RawDex > 10 );
|
||||
case Stat.Int: return ( from.IntLock == StatLockType.Down && from.RawInt > 10 );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool CanRaise( Mobile from, Stat stat )
|
||||
{
|
||||
if ( !(from is BaseCreature && ((BaseCreature)from).Controlled) )
|
||||
{
|
||||
if ( from.RawStatTotal >= from.StatCap )
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ( stat )
|
||||
{
|
||||
case Stat.Str: return ( from.StrLock == StatLockType.Up && from.RawStr < 125 );
|
||||
case Stat.Dex: return ( from.DexLock == StatLockType.Up && from.RawDex < 125 );
|
||||
case Stat.Int: return ( from.IntLock == StatLockType.Up && from.RawInt < 125 );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void IncreaseStat( Mobile from, Stat stat, bool atrophy )
|
||||
{
|
||||
atrophy = atrophy || (from.RawStatTotal >= from.StatCap);
|
||||
|
||||
switch ( stat )
|
||||
{
|
||||
case Stat.Str:
|
||||
{
|
||||
if ( atrophy )
|
||||
{
|
||||
if ( CanLower( from, Stat.Dex ) && (from.RawDex < from.RawInt || !CanLower( from, Stat.Int )) )
|
||||
--from.RawDex;
|
||||
else if ( CanLower( from, Stat.Int ) )
|
||||
--from.RawInt;
|
||||
}
|
||||
|
||||
if ( CanRaise( from, Stat.Str ) )
|
||||
++from.RawStr;
|
||||
|
||||
break;
|
||||
}
|
||||
case Stat.Dex:
|
||||
{
|
||||
if ( atrophy )
|
||||
{
|
||||
if ( CanLower( from, Stat.Str ) && (from.RawStr < from.RawInt || !CanLower( from, Stat.Int )) )
|
||||
--from.RawStr;
|
||||
else if ( CanLower( from, Stat.Int ) )
|
||||
--from.RawInt;
|
||||
}
|
||||
|
||||
if ( CanRaise( from, Stat.Dex ) )
|
||||
++from.RawDex;
|
||||
|
||||
break;
|
||||
}
|
||||
case Stat.Int:
|
||||
{
|
||||
if ( atrophy )
|
||||
{
|
||||
if ( CanLower( from, Stat.Str ) && (from.RawStr < from.RawDex || !CanLower( from, Stat.Dex )) )
|
||||
--from.RawStr;
|
||||
else if ( CanLower( from, Stat.Dex ) )
|
||||
--from.RawDex;
|
||||
}
|
||||
|
||||
if ( CanRaise( from, Stat.Int ) )
|
||||
++from.RawInt;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static TimeSpan m_StatGainDelay = TimeSpan.FromMinutes( 15.0 );
|
||||
private static TimeSpan m_PetStatGainDelay = TimeSpan.FromMinutes( 5.0 );
|
||||
|
||||
public static void GainStat( Mobile from, Stat stat )
|
||||
{
|
||||
switch( stat )
|
||||
{
|
||||
case Stat.Str:
|
||||
{
|
||||
if ( from is BaseCreature && ((BaseCreature)from).Controlled ) {
|
||||
if ( (from.LastStrGain + m_PetStatGainDelay) >= DateTime.Now )
|
||||
return;
|
||||
}
|
||||
else if( (from.LastStrGain + m_StatGainDelay) >= DateTime.Now )
|
||||
return;
|
||||
|
||||
from.LastStrGain = DateTime.Now;
|
||||
break;
|
||||
}
|
||||
case Stat.Dex:
|
||||
{
|
||||
if ( from is BaseCreature && ((BaseCreature)from).Controlled ) {
|
||||
if ( (from.LastDexGain + m_PetStatGainDelay) >= DateTime.Now )
|
||||
return;
|
||||
}
|
||||
else if( (from.LastDexGain + m_StatGainDelay) >= DateTime.Now )
|
||||
return;
|
||||
|
||||
from.LastDexGain = DateTime.Now;
|
||||
break;
|
||||
}
|
||||
case Stat.Int:
|
||||
{
|
||||
if ( from is BaseCreature && ((BaseCreature)from).Controlled ) {
|
||||
if ( (from.LastIntGain + m_PetStatGainDelay) >= DateTime.Now )
|
||||
return;
|
||||
}
|
||||
|
||||
else if( (from.LastIntGain + m_StatGainDelay) >= DateTime.Now )
|
||||
return;
|
||||
|
||||
from.LastIntGain = DateTime.Now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool atrophy = ( (from.RawStatTotal / (double)from.StatCap) >= Utility.RandomDouble() );
|
||||
|
||||
IncreaseStat( from, stat, atrophy );
|
||||
}
|
||||
}
|
||||
}
|
||||
457
Scripts/Skills/Stealing.cs
Normal file
457
Scripts/Skills/Stealing.cs
Normal file
|
|
@ -0,0 +1,457 @@
|
|||
using System;
|
||||
using Server;
|
||||
using System.Collections;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Spells.Seventh;
|
||||
using Server.Spells.Fifth;
|
||||
using Server.Spells;
|
||||
using Server.Misc;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Stealing
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[22].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static readonly bool ClassicMode = true;
|
||||
public static readonly bool SuspendOnMurder = false;
|
||||
|
||||
public static bool IsInGuild( Mobile m )
|
||||
{
|
||||
return ( m is PlayerMobile && ((PlayerMobile)m).NpcGuild == NpcGuild.ThievesGuild );
|
||||
}
|
||||
|
||||
public static bool IsInnocentTo( Mobile from, Mobile to )
|
||||
{
|
||||
return ( Notoriety.Compute( from, (Mobile)to ) == Notoriety.Innocent );
|
||||
}
|
||||
|
||||
private class StealingTarget : Target
|
||||
{
|
||||
private Mobile m_Thief;
|
||||
|
||||
public StealingTarget( Mobile thief ) : base ( 1, false, TargetFlags.None )
|
||||
{
|
||||
m_Thief = thief;
|
||||
|
||||
AllowNonlocal = true;
|
||||
}
|
||||
|
||||
private Item TryStealItem( Item toSteal, ref bool caught )
|
||||
{
|
||||
Item stolen = null;
|
||||
|
||||
object root = toSteal.RootParent;
|
||||
|
||||
if ( !IsEmptyHanded( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005584 ); // Both hands must be free to steal.
|
||||
}
|
||||
else if ( root is Mobile && ((Mobile)root).Invulnerable )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005598 ); // You can't steal from them.
|
||||
}
|
||||
else if ( root is PlayerVendor )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502709 ); // You can't steal from vendors.
|
||||
}
|
||||
else if ( !m_Thief.CanSee( toSteal ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 500237 ); // Target can not be seen.
|
||||
}
|
||||
else if ( m_Thief.Backpack == null || !m_Thief.Backpack.CheckHold( m_Thief, toSteal, false, true ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1048147 ); // Your backpack can't hold anything else.
|
||||
}
|
||||
else if ( toSteal.Parent == null || !toSteal.Movable )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
else if ( !m_Thief.InRange( toSteal.GetWorldLocation(), 1 ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502703 ); // You must be standing next to an item to steal it.
|
||||
}
|
||||
else if ( toSteal.Parent is Mobile )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005585 ); // You cannot steal items which are equiped.
|
||||
}
|
||||
else if ( root == m_Thief )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502704 ); // You catch yourself red-handed.
|
||||
}
|
||||
else if ( root is Mobile && ((Mobile)root).AccessLevel > AccessLevel.Player )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
else if ( root is Mobile && !m_Thief.CanBeHarmful( (Mobile)root ) )
|
||||
{
|
||||
}
|
||||
else if ( root is Corpse )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
else
|
||||
{
|
||||
double w = toSteal.Weight + toSteal.TotalWeight;
|
||||
|
||||
if ( w > 10 )
|
||||
{
|
||||
m_Thief.SendMessage( "That is too heavy to steal." );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( toSteal.Stackable && toSteal.Amount > 1 )
|
||||
{
|
||||
int maxAmount = (int)((m_Thief.Skills[SkillName.Stealing].Value / 10.0) / toSteal.Weight);
|
||||
|
||||
if ( maxAmount < 1 )
|
||||
maxAmount = 1;
|
||||
else if ( maxAmount > toSteal.Amount )
|
||||
maxAmount = toSteal.Amount;
|
||||
|
||||
int amount = Utility.RandomMinMax( 1, maxAmount );
|
||||
|
||||
if ( amount >= toSteal.Amount )
|
||||
{
|
||||
int pileWeight = (int)Math.Ceiling( toSteal.Weight * toSteal.Amount );
|
||||
pileWeight *= 10;
|
||||
|
||||
if ( m_Thief.CheckTargetSkill( SkillName.Stealing, toSteal, pileWeight - 22.5, pileWeight + 27.5 ) )
|
||||
stolen = toSteal;
|
||||
}
|
||||
else
|
||||
{
|
||||
int pileWeight = (int)Math.Ceiling( toSteal.Weight * amount );
|
||||
pileWeight *= 10;
|
||||
|
||||
if ( m_Thief.CheckTargetSkill( SkillName.Stealing, toSteal, pileWeight - 22.5, pileWeight + 27.5 ) )
|
||||
{
|
||||
stolen = Mobile.LiftItemDupe( toSteal, toSteal.Amount - amount );
|
||||
|
||||
if ( stolen == null )
|
||||
stolen = toSteal;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int iw = (int)Math.Ceiling( w );
|
||||
iw *= 10;
|
||||
|
||||
if ( m_Thief.CheckTargetSkill( SkillName.Stealing, toSteal, iw - 22.5, iw + 27.5 ) )
|
||||
stolen = toSteal;
|
||||
}
|
||||
|
||||
if ( stolen != null )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502724 ); // You succesfully steal the item.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502723 ); // You fail to steal the item.
|
||||
}
|
||||
|
||||
caught = ( m_Thief.Skills[SkillName.Stealing].Value < Utility.Random( 150 ) );
|
||||
}
|
||||
}
|
||||
|
||||
return stolen;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object target )
|
||||
{
|
||||
from.RevealingAction();
|
||||
|
||||
Item stolen = null;
|
||||
object root = null;
|
||||
bool caught = false;
|
||||
|
||||
if ( target is Item )
|
||||
{
|
||||
root = ((Item)target).RootParent;
|
||||
stolen = TryStealItem( (Item)target, ref caught );
|
||||
}
|
||||
else if ( target is Mobile )
|
||||
{
|
||||
Container pack = ((Mobile)target).Backpack;
|
||||
|
||||
if ( pack != null && pack.Items.Count > 0 )
|
||||
{
|
||||
int randomIndex = Utility.Random( pack.Items.Count );
|
||||
|
||||
root = target;
|
||||
stolen = TryStealItem( pack.Items[randomIndex], ref caught );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
|
||||
if ( stolen != null )
|
||||
{
|
||||
from.AddToBackpack( stolen );
|
||||
|
||||
StolenItem.Add( stolen, m_Thief, root as Mobile );
|
||||
}
|
||||
|
||||
if ( caught )
|
||||
{
|
||||
if ( root == null )
|
||||
{
|
||||
m_Thief.CriminalAction( false );
|
||||
}
|
||||
else if ( root is Corpse && ((Corpse)root).IsCriminalAction( m_Thief ) )
|
||||
{
|
||||
m_Thief.CriminalAction( false );
|
||||
}
|
||||
else if ( root is Mobile )
|
||||
{
|
||||
Mobile mobRoot = (Mobile)root;
|
||||
|
||||
if ( !IsInGuild( mobRoot ) && IsInnocentTo( m_Thief, mobRoot ) )
|
||||
m_Thief.CriminalAction( false );
|
||||
|
||||
string message = String.Format( "You notice {0} trying to steal from {1}.", m_Thief.Name, mobRoot.Name );
|
||||
|
||||
foreach ( NetState ns in m_Thief.GetClientsInRange( 8 ) )
|
||||
{
|
||||
if ( ns.Mobile != m_Thief )
|
||||
ns.Mobile.SendMessage( message );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( root is Corpse && ((Corpse)root).IsCriminalAction( m_Thief ) )
|
||||
{
|
||||
m_Thief.CriminalAction( false );
|
||||
}
|
||||
|
||||
if ( root is Mobile && ((Mobile)root).Player && m_Thief is PlayerMobile && IsInnocentTo( m_Thief, (Mobile)root ) && !IsInGuild( (Mobile)root ) )
|
||||
{
|
||||
PlayerMobile pm = (PlayerMobile)m_Thief;
|
||||
|
||||
pm.PermaFlags.Add( (Mobile)root );
|
||||
pm.Delta( MobileDelta.Noto );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsEmptyHanded( Mobile from )
|
||||
{
|
||||
if ( Server.Misc.Settings.CanStealWhileHoldingThings() )
|
||||
return true;
|
||||
|
||||
if ( from.FindItemOnLayer( Layer.OneHanded ) != null )
|
||||
return false;
|
||||
|
||||
if ( from.FindItemOnLayer( Layer.TwoHanded ) != null )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
if ( !IsEmptyHanded( m ) )
|
||||
{
|
||||
m.SendLocalizedMessage( 1005584 ); // Both hands must be free to steal.
|
||||
}
|
||||
else
|
||||
{
|
||||
m.Target = new Stealing.StealingTarget( m );
|
||||
m.RevealingAction();
|
||||
|
||||
m.SendLocalizedMessage( 502698 ); // Which item do you want to steal?
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
}
|
||||
|
||||
public class StolenItem
|
||||
{
|
||||
public static readonly TimeSpan StealTime = TimeSpan.FromMinutes( 2.0 );
|
||||
|
||||
private Item m_Stolen;
|
||||
private Mobile m_Thief;
|
||||
private Mobile m_Victim;
|
||||
private DateTime m_Expires;
|
||||
|
||||
public Item Stolen{ get{ return m_Stolen; } }
|
||||
public Mobile Thief{ get{ return m_Thief; } }
|
||||
public Mobile Victim{ get{ return m_Victim; } }
|
||||
public DateTime Expires{ get{ return m_Expires; } }
|
||||
|
||||
public bool IsExpired{ get{ return ( DateTime.Now >= m_Expires ); } }
|
||||
|
||||
public StolenItem( Item stolen, Mobile thief, Mobile victim )
|
||||
{
|
||||
m_Stolen = stolen;
|
||||
m_Thief = thief;
|
||||
m_Victim = victim;
|
||||
|
||||
m_Expires = DateTime.Now + StealTime;
|
||||
}
|
||||
|
||||
private static Queue m_Queue = new Queue();
|
||||
|
||||
public static void Add( Item item, Mobile thief, Mobile victim )
|
||||
{
|
||||
Clean();
|
||||
|
||||
m_Queue.Enqueue( new StolenItem( item, thief, victim ) );
|
||||
}
|
||||
|
||||
public static bool IsStolen( Item item )
|
||||
{
|
||||
Mobile victim = null;
|
||||
|
||||
return IsStolen( item, ref victim );
|
||||
}
|
||||
|
||||
public static bool IsStolen( Item item, ref Mobile victim )
|
||||
{
|
||||
Clean();
|
||||
|
||||
foreach ( StolenItem si in m_Queue )
|
||||
{
|
||||
if ( si.m_Stolen == item && !si.IsExpired )
|
||||
{
|
||||
victim = si.m_Victim;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void ReturnOnDeath( Mobile killed, Container corpse )
|
||||
{
|
||||
Clean();
|
||||
|
||||
foreach ( StolenItem si in m_Queue )
|
||||
{
|
||||
if ( si.m_Stolen.RootParent == corpse && si.m_Victim != null && !si.IsExpired )
|
||||
{
|
||||
if ( si.m_Victim.AddToBackpack( si.m_Stolen ) )
|
||||
si.m_Victim.SendLocalizedMessage( 1010464 ); // the item that was stolen is returned to you.
|
||||
else
|
||||
si.m_Victim.SendLocalizedMessage( 1010463 ); // the item that was stolen from you falls to the ground.
|
||||
|
||||
si.m_Expires = DateTime.Now; // such a hack
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Clean()
|
||||
{
|
||||
while ( m_Queue.Count > 0 )
|
||||
{
|
||||
StolenItem si = (StolenItem) m_Queue.Peek();
|
||||
|
||||
if ( si.IsExpired )
|
||||
m_Queue.Dequeue();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Snooping
|
||||
{
|
||||
public static void Configure()
|
||||
{
|
||||
Container.SnoopHandler = new ContainerSnoopHandler( Container_Snoop );
|
||||
}
|
||||
|
||||
public static bool CheckSnoopAllowed( Mobile from, Mobile to )
|
||||
{
|
||||
Map map = from.Map;
|
||||
|
||||
if ( to.Player )
|
||||
return from.CanBeHarmful( to, false, true ); // normal restrictions
|
||||
|
||||
if ( map != null && (map.Rules & MapRules.HarmfulRestrictions) == 0 )
|
||||
return true;
|
||||
|
||||
BaseCreature cret = to as BaseCreature;
|
||||
|
||||
if ( to.Body.IsHuman && (cret == null || (!cret.AlwaysAttackable && !cret.AlwaysMurderer)) )
|
||||
return false; // in town we cannot snoop blue human npcs
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Container_Snoop( Container cont, Mobile from )
|
||||
{
|
||||
if ( from.AccessLevel > AccessLevel.Player || from.InRange( cont.GetWorldLocation(), 1 ) )
|
||||
{
|
||||
Mobile root = cont.RootParent as Mobile;
|
||||
|
||||
if ( root != null && !root.Alive )
|
||||
return;
|
||||
|
||||
if ( root != null && root.AccessLevel > AccessLevel.Player && from.AccessLevel == AccessLevel.Player )
|
||||
{
|
||||
from.SendLocalizedMessage( 500209 ); // You can not peek into the container.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( root != null && from.AccessLevel == AccessLevel.Player && !CheckSnoopAllowed( from, root ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1001018 ); // You cannot perform negative acts on your target.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( root != null && from.AccessLevel == AccessLevel.Player && from.Skills[SkillName.Stealing].Value < Utility.Random( 100 ) )
|
||||
{
|
||||
Map map = from.Map;
|
||||
|
||||
if ( map != null )
|
||||
{
|
||||
string message = String.Format( "You notice {0} attempting to peek into {1}'s belongings.", from.Name, root.Name );
|
||||
|
||||
IPooledEnumerable eable = map.GetClientsInRange( from.Location, 8 );
|
||||
|
||||
foreach ( NetState ns in eable )
|
||||
{
|
||||
if ( ns.Mobile != from )
|
||||
ns.Mobile.SendMessage( message );
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
if ( from.AccessLevel == AccessLevel.Player )
|
||||
Titles.AwardKarma( from, -4, true );
|
||||
|
||||
if ( from.AccessLevel > AccessLevel.Player || from.CheckTargetSkill( SkillName.Stealing, cont, 0.0, 50.0 ) )
|
||||
{
|
||||
if ( cont is TrapableContainer && ((TrapableContainer)cont).ExecuteTrap( from ) )
|
||||
return;
|
||||
|
||||
cont.DisplayTo( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500210 ); // You failed to peek into the container.
|
||||
|
||||
if ( from.Skills[SkillName.Hiding].Value / 2 < Utility.Random( 100 ) )
|
||||
from.RevealingAction();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500446 ); // That is too far away.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
Scripts/Skills/Stealth.cs
Normal file
67
Scripts/Skills/Stealth.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Stealth
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Stealth].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
if ( !m.Hidden )
|
||||
{
|
||||
m.SendLocalizedMessage( 502725 ); // You must hide first
|
||||
}
|
||||
else if ( m.Skills[SkillName.Hiding].Value < Utility.Random(101) )
|
||||
{
|
||||
m.SendLocalizedMessage( 502731 ); // You fail in your attempt to move unnoticed.
|
||||
m.RevealingAction();
|
||||
}
|
||||
else if( !m.CanBeginAction( typeof( Stealth ) ) )
|
||||
{
|
||||
m.SendLocalizedMessage( 1063086 ); // You cannot use this skill right now.
|
||||
m.RevealingAction();
|
||||
}
|
||||
else
|
||||
{
|
||||
int armorRating = (int)( BaseWeapon.ArmorRating( m ) / 2 );
|
||||
|
||||
if( armorRating >= 26 )
|
||||
{
|
||||
m.SendLocalizedMessage( 502727 ); // You could not hope to move quietly wearing this much armor.
|
||||
m.RevealingAction();
|
||||
}
|
||||
else if( m.CheckSkill( SkillName.Stealth, -20.0 + (armorRating * 2), 80.0 + (armorRating * 2) ) )
|
||||
{
|
||||
int steps = (int)(m.Skills[SkillName.Stealth].Value / 10.0);
|
||||
|
||||
if( steps < 1 )
|
||||
steps = 1;
|
||||
|
||||
m.AllowedStealthSteps = steps;
|
||||
|
||||
PlayerMobile pm = m as PlayerMobile; // IsStealthing should be moved to Server.Mobiles
|
||||
|
||||
if( pm != null )
|
||||
pm.IsStealthing = true;
|
||||
|
||||
m.SendLocalizedMessage( 502730 ); // You begin to move quietly.
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
m.SendLocalizedMessage( 502731 ); // You fail in your attempt to move unnoticed.
|
||||
m.RevealingAction();
|
||||
}
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
428
Scripts/Skills/Tracking.cs
Normal file
428
Scripts/Skills/Tracking.cs
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Server.Spells;
|
||||
using Server.Mobiles;
|
||||
using Server.Items;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Tracking
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Tracking].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.SendLocalizedMessage( 1011350 ); // What do you wish to track?
|
||||
|
||||
m.CloseGump( typeof( TrackWhatGump ) );
|
||||
m.CloseGump( typeof( TrackWhoGump ) );
|
||||
m.SendGump( new TrackWhatGump( m ) );
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 ); // 10 second delay before beign able to re-use a skill
|
||||
}
|
||||
|
||||
public class TrackingInfo
|
||||
{
|
||||
public Mobile m_Tracker;
|
||||
public Mobile m_Target;
|
||||
public Point2D m_Location;
|
||||
public Map m_Map;
|
||||
|
||||
public TrackingInfo( Mobile tracker, Mobile target )
|
||||
{
|
||||
m_Tracker = tracker;
|
||||
m_Target = target;
|
||||
m_Location = new Point2D( target.X, target.Y );
|
||||
m_Map = target.Map;
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<Mobile, TrackingInfo> m_Table = new Dictionary<Mobile, TrackingInfo>();
|
||||
|
||||
public static void AddInfo( Mobile tracker, Mobile target )
|
||||
{
|
||||
TrackingInfo info = new TrackingInfo( tracker, target );
|
||||
m_Table[tracker] = info;
|
||||
}
|
||||
|
||||
public static double GetStalkingBonus( Mobile tracker, Mobile target )
|
||||
{
|
||||
TrackingInfo info = null;
|
||||
m_Table.TryGetValue( tracker, out info );
|
||||
|
||||
if ( info == null || info.m_Target != target || info.m_Map != target.Map )
|
||||
return 0.0;
|
||||
|
||||
int xDelta = info.m_Location.X - target.X;
|
||||
int yDelta = info.m_Location.Y - target.Y;
|
||||
|
||||
double bonus = Math.Sqrt( (xDelta * xDelta) + (yDelta * yDelta) );
|
||||
|
||||
m_Table.Remove( tracker );
|
||||
|
||||
return bonus;
|
||||
}
|
||||
|
||||
|
||||
public static void ClearTrackingInfo( Mobile tracker )
|
||||
{
|
||||
m_Table.Remove( tracker );
|
||||
}
|
||||
}
|
||||
|
||||
public class TrackWhatGump : Gump
|
||||
{
|
||||
private Mobile m_From;
|
||||
private bool m_Success;
|
||||
|
||||
public TrackWhatGump( Mobile from ) : base( 20, 30 )
|
||||
{
|
||||
m_From = from;
|
||||
m_Success = from.CheckSkill( SkillName.Tracking, 0.0, 21.1 );
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
AddBackground( 0, 0, 440, 135, 5054 );
|
||||
|
||||
AddBackground( 10, 10, 420, 75, 2620 );
|
||||
AddBackground( 10, 85, 420, 25, 3000 );
|
||||
|
||||
AddItem( 20, 20, 9682 );
|
||||
AddButton( 20, 110, 4005, 4007, 1, GumpButtonType.Reply, 0 );
|
||||
AddHtmlLocalized( 20, 90, 100, 20, 1018087, false, false ); // Animals
|
||||
|
||||
AddItem( 120, 20, 9607 );
|
||||
AddButton( 120, 110, 4005, 4007, 2, GumpButtonType.Reply, 0 );
|
||||
AddHtmlLocalized( 120, 90, 100, 20, 1018088, false, false ); // Monsters
|
||||
|
||||
AddItem( 220, 20, 8454 );
|
||||
AddButton( 220, 110, 4005, 4007, 3, GumpButtonType.Reply, 0 );
|
||||
AddHtmlLocalized( 220, 90, 100, 20, 1018089, false, false ); // Human NPCs
|
||||
|
||||
AddItem( 320, 20, 8455 );
|
||||
AddButton( 320, 110, 4005, 4007, 4, GumpButtonType.Reply, 0 );
|
||||
AddHtmlLocalized( 320, 90, 100, 20, 1018090, false, false ); // Players
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState state, RelayInfo info )
|
||||
{
|
||||
if ( info.ButtonID >= 1 && info.ButtonID <= 4 )
|
||||
TrackWhoGump.DisplayTo( m_Success, m_From, info.ButtonID - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
public delegate bool TrackTypeDelegate( Mobile m );
|
||||
|
||||
public class TrackWhoGump : Gump
|
||||
{
|
||||
private Mobile m_From;
|
||||
private int m_Range;
|
||||
|
||||
private static TrackTypeDelegate[] m_Delegates = new TrackTypeDelegate[]
|
||||
{
|
||||
new TrackTypeDelegate( IsAnimal ),
|
||||
new TrackTypeDelegate( IsMonster ),
|
||||
new TrackTypeDelegate( IsHumanNPC ),
|
||||
new TrackTypeDelegate( IsPlayer )
|
||||
};
|
||||
|
||||
private class InternalSorter : IComparer<Mobile>
|
||||
{
|
||||
private Mobile m_From;
|
||||
|
||||
public InternalSorter( Mobile from )
|
||||
{
|
||||
m_From = from;
|
||||
}
|
||||
|
||||
public int Compare( Mobile x, Mobile y )
|
||||
{
|
||||
if ( x == null && y == null )
|
||||
return 0;
|
||||
else if ( x == null )
|
||||
return -1;
|
||||
else if ( y == null )
|
||||
return 1;
|
||||
|
||||
return m_From.GetDistanceToSqrt( x ).CompareTo( m_From.GetDistanceToSqrt( y ) );
|
||||
}
|
||||
}
|
||||
|
||||
public static void DisplayTo( bool success, Mobile from, int type )
|
||||
{
|
||||
if ( !success )
|
||||
{
|
||||
from.SendLocalizedMessage( 1018092 ); // You see no evidence of those in the area.
|
||||
return;
|
||||
}
|
||||
|
||||
Map map = from.Map;
|
||||
|
||||
if ( map == null )
|
||||
return;
|
||||
|
||||
TrackTypeDelegate check = m_Delegates[type];
|
||||
|
||||
from.CheckSkill( SkillName.Tracking, 21.1, 100.0 ); // Passive gain
|
||||
|
||||
int range = 10 + (int)(from.Skills[SkillName.Tracking].Value / 10);
|
||||
|
||||
List<Mobile> list = new List<Mobile>();
|
||||
|
||||
foreach ( Mobile m in from.GetMobilesInRange( range ) )
|
||||
{
|
||||
if ( ( m.Map == Map.Underworld || m.Region is GraveRegion ) && m is BaseCreature && m.Hidden )
|
||||
list.Add( m );
|
||||
else if ( m != from && (!m.Hidden || m.AccessLevel == AccessLevel.Player || from.AccessLevel > m.AccessLevel) && check( m ) && CheckDifficulty( from, m ) )
|
||||
list.Add( m );
|
||||
}
|
||||
|
||||
if ( list.Count > 0 )
|
||||
{
|
||||
list.Sort( new InternalSorter( from ) );
|
||||
|
||||
from.SendGump( new TrackWhoGump( from, list, range ) );
|
||||
from.SendLocalizedMessage( 1018093 ); // Select the one you would like to track.
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( type == 0 )
|
||||
from.SendLocalizedMessage( 502991 ); // You see no evidence of animals in the area.
|
||||
else if ( type == 1 )
|
||||
from.SendLocalizedMessage( 502993 ); // You see no evidence of creatures in the area.
|
||||
else
|
||||
from.SendLocalizedMessage( 502995 ); // You see no evidence of people in the area.
|
||||
}
|
||||
}
|
||||
|
||||
// Tracking players uses tracking and detect hidden vs. hiding and stealth
|
||||
private static bool CheckDifficulty( Mobile from, Mobile m )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsAnimal( Mobile m )
|
||||
{
|
||||
return ( !m.Player && m.Body.IsAnimal );
|
||||
}
|
||||
|
||||
private static bool IsMonster( Mobile m )
|
||||
{
|
||||
return ( !m.Player && m.Body.IsMonster );
|
||||
}
|
||||
|
||||
private static bool IsHumanNPC( Mobile m )
|
||||
{
|
||||
return ( !m.Player && m.Body.IsHuman );
|
||||
}
|
||||
|
||||
private static bool IsPlayer( Mobile m )
|
||||
{
|
||||
return m.Player;
|
||||
}
|
||||
|
||||
private List<Mobile> m_List;
|
||||
|
||||
private TrackWhoGump( Mobile from, List<Mobile> list, int range ) : base( 20, 30 )
|
||||
{
|
||||
m_From = from;
|
||||
m_List = list;
|
||||
m_Range = range;
|
||||
|
||||
AddPage( 0 );
|
||||
|
||||
AddBackground( 0, 0, 440, 155, 5054 );
|
||||
|
||||
AddBackground( 10, 10, 420, 75, 2620 );
|
||||
AddBackground( 10, 85, 420, 45, 3000 );
|
||||
|
||||
if ( list.Count > 4 )
|
||||
{
|
||||
AddBackground( 0, 155, 440, 155, 5054 );
|
||||
|
||||
AddBackground( 10, 165, 420, 75, 2620 );
|
||||
AddBackground( 10, 240, 420, 45, 3000 );
|
||||
|
||||
if ( list.Count > 8 )
|
||||
{
|
||||
AddBackground( 0, 310, 440, 155, 5054 );
|
||||
|
||||
AddBackground( 10, 320, 420, 75, 2620 );
|
||||
AddBackground( 10, 395, 420, 45, 3000 );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < list.Count && i < 12; ++i )
|
||||
{
|
||||
Mobile m = list[i];
|
||||
|
||||
string name = m.Name;
|
||||
int icon = Utility.RandomList( 0x208E, 0x208F, 0x2090 ); // general icon
|
||||
|
||||
if ( m is PlayerMobile )
|
||||
{
|
||||
if ( m.Female )
|
||||
icon = Utility.RandomList( 0x208C, 0x208D );
|
||||
else
|
||||
icon = Utility.RandomList( 0x208A, 0x208B );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m.Body.IsHuman )
|
||||
{
|
||||
if ( m.Female )
|
||||
icon = Utility.RandomList( 0x209C, 0x209D, 0x209E );
|
||||
else
|
||||
icon = Utility.RandomList( 0x2099, 0x209A, 0x209B );
|
||||
}
|
||||
else if ( IsGiant( m ) ){ icon = 0x208F; }
|
||||
else if ( IsOgre( m ) ){ icon = 0x2092; }
|
||||
else if ( IsOrc( m ) ){ icon = 0x2093; }
|
||||
else if ( IsTroll( m ) ){ icon = 0x2092; }
|
||||
else if ( IsUndead( m ) ){ icon = 0x2098; }
|
||||
else if ( IsNature( m ) ){ icon = 0x2094; }
|
||||
else if ( IsElemental( m ) ){ icon = 0x2088; }
|
||||
else if ( IsDemon( m ) ){ icon = 0x2082; }
|
||||
else if ( IsArachnids( m ) ){ icon = 0x2097; }
|
||||
else if ( IsPlant( m ) ){ icon = 0x20A0; }
|
||||
else if ( IsGoblin( m ) ){ icon = 0x209F; }
|
||||
else if ( IsDragon( m ) ){ icon = 0x2087; }
|
||||
else if ( IsSnake( m ) || IsSerpent( m ) ){ icon = 0x2096; }
|
||||
else if ( IsReptile( m ) ){ icon = 0x2091; }
|
||||
else if ( IsOcean( m ) ){ icon = 0x2095; }
|
||||
else if ( m is Slime || m is Sludge ){ icon = 0x20A1; }
|
||||
else if ( m is EvilMage || m is EvilMageLord ){ icon = 0x2089; }
|
||||
else if ( m is BaseCreature && ((BaseCreature)m).Feathers > 0 ){ icon = 0x2081; }
|
||||
else if ( m.Body.IsAnimal ){ icon = 0x2080; }
|
||||
}
|
||||
|
||||
AddItem( 20 + ((i % 4) * 100), 26 + ((i / 4) * 155), icon );
|
||||
|
||||
AddButton( 20 + ((i % 4) * 100), 130 + ((i / 4) * 155), 4005, 4007, i + 1, GumpButtonType.Reply, 0 );
|
||||
|
||||
if ( m.Name != null )
|
||||
{
|
||||
if ( m.HiddenTitle != null )
|
||||
name = name + " " + m.HiddenTitle;
|
||||
else if ( m.Title != null )
|
||||
name = name + " " + m.Title;
|
||||
}
|
||||
|
||||
AddHtml( 20 + ((i % 4) * 100), 90 + ((i / 4) * 155), 90, 40, name, false, false );
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsOgre( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.OgreTrashing )).Slays(m); }
|
||||
private static bool IsOrc( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.OrcSlaying )).Slays(m); }
|
||||
private static bool IsTroll( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.TrollSlaughter )).Slays(m); }
|
||||
private static bool IsUndead( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.UndeadDoom )).Slays(m); }
|
||||
private static bool IsNature( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.NaturesFury )).Slays(m); }
|
||||
private static bool IsElemental( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.ElementalBan )).Slays(m); }
|
||||
private static bool IsDemon( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.Exorcism )).Slays(m); }
|
||||
private static bool IsArachnids( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.BugButcher )).Slays(m); }
|
||||
private static bool IsReptile( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.ReptilianDeath )).Slays(m); }
|
||||
private static bool IsDragon( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.DragonSlaying )).Slays(m); }
|
||||
private static bool IsSnake( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.SerpentBane )).Slays(m); }
|
||||
private static bool IsSerpent( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.SerpentoidMassacre )).Slays(m); }
|
||||
private static bool IsOcean( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.SeaSlaughter )).Slays(m); }
|
||||
private static bool IsGoblin( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.GoblinoidHunter )).Slays(m); }
|
||||
private static bool IsPlant( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.WeedWrecker )).Slays(m); }
|
||||
private static bool IsGiant( Mobile m ){ return (SlayerGroup.GetEntryByName( SlayerName.GiantsFall )).Slays(m); }
|
||||
|
||||
public override void OnResponse( NetState state, RelayInfo info )
|
||||
{
|
||||
int index = info.ButtonID - 1;
|
||||
|
||||
if ( index >= 0 && index < m_List.Count && index < 12 )
|
||||
{
|
||||
Mobile m = m_List[index];
|
||||
|
||||
m_From.QuestArrow = new TrackArrow( m_From, m, m_Range * 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TrackArrow : QuestArrow
|
||||
{
|
||||
private Mobile m_From;
|
||||
private Timer m_Timer;
|
||||
|
||||
public TrackArrow( Mobile from, Mobile target, int range ) : base( from, target )
|
||||
{
|
||||
m_From = from;
|
||||
m_Timer = new TrackTimer( from, target, range, this );
|
||||
m_Timer.Start();
|
||||
}
|
||||
|
||||
public override void OnClick( bool rightClick )
|
||||
{
|
||||
if ( rightClick )
|
||||
{
|
||||
Tracking.ClearTrackingInfo( m_From );
|
||||
|
||||
m_From = null;
|
||||
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnStop()
|
||||
{
|
||||
m_Timer.Stop();
|
||||
|
||||
if ( m_From != null )
|
||||
{
|
||||
Tracking.ClearTrackingInfo( m_From );
|
||||
|
||||
m_From.SendLocalizedMessage( 503177 ); // You have lost your quarry.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TrackTimer : Timer
|
||||
{
|
||||
private Mobile m_From, m_Target;
|
||||
private int m_Range;
|
||||
private int m_LastX, m_LastY;
|
||||
private QuestArrow m_Arrow;
|
||||
|
||||
public TrackTimer( Mobile from, Mobile target, int range, QuestArrow arrow ) : base( TimeSpan.FromSeconds( 0.25 ), TimeSpan.FromSeconds( 2.5 ) )
|
||||
{
|
||||
m_From = from;
|
||||
m_Target = target;
|
||||
m_Range = range;
|
||||
|
||||
m_Arrow = arrow;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
if ( !m_Arrow.Running )
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
else if ( m_From.NetState == null || m_From.Deleted || m_Target.Deleted || m_From.Map != m_Target.Map || !m_From.InRange( m_Target, m_Range ) )
|
||||
{
|
||||
m_Arrow.Stop();
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_LastX != m_Target.X || m_LastY != m_Target.Y )
|
||||
{
|
||||
m_LastX = m_Target.X;
|
||||
m_LastY = m_Target.Y;
|
||||
|
||||
m_Arrow.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
80
Scripts/Skills/TradesGump.cs
Normal file
80
Scripts/Skills/TradesGump.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
using Server.Misc;
|
||||
using Server.Commands;
|
||||
|
||||
namespace Server.Gumps
|
||||
{
|
||||
public class TradesGump : Gump
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
CommandSystem.Register("Trades", AccessLevel.Player, Trades_OnCommand);
|
||||
}
|
||||
|
||||
[Usage("Trades")]
|
||||
[Description("Opens the trades skill gump.")]
|
||||
public static void Trades_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
Mobile m = e.Mobile;
|
||||
m.CloseGump(typeof(TradesGump));
|
||||
m.SendGump(new TradesGump(m));
|
||||
}
|
||||
public TradesGump( Mobile m ) : base( 50, 50 )
|
||||
{
|
||||
string name = "";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Alchemy ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Blacksmith ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Carpentry ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Cartography ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Cooking ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Fishing ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Fletching ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Inscribe ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Lumberjacking ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Mining ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Tailoring ) + "<BR>";
|
||||
name = name + "" + SkillCheck.TradeName( Trades.Tinkering ) + "<BR>";
|
||||
|
||||
string level = "";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Alchemy, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Blacksmith, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Carpentry, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Cartography, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Cooking, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Fishing, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Fletching, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Inscribe, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Lumberjacking, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Mining, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Tailoring, false )).ToString("0.0") + "<BR>";
|
||||
level = level + "" + (SkillCheck.TradeSkill( m, Trades.Tinkering, false )).ToString("0.0") + "<BR>";
|
||||
|
||||
this.Closable=true;
|
||||
this.Disposable=true;
|
||||
this.Dragable=true;
|
||||
this.Resizable=false;
|
||||
|
||||
AddPage(0);
|
||||
AddImage(21, 313, 2083);
|
||||
AddImage(19, 106, 2082);
|
||||
AddImage(19, 244, 2081);
|
||||
AddImage(18, 36, 2081);
|
||||
AddImage(0, 0, 2080);
|
||||
AddImage(42, 38, 2091);
|
||||
AddImage(42, 293, 2091);
|
||||
AddImage(19, 174, 2082);
|
||||
AddHtml( 38, 58, 137, 226, @"<BODY><BASEFONT Color=#5c4c32><BIG>" + name + "</BIG></BASEFONT></BODY>", (bool)false, (bool)false);
|
||||
AddHtml( 205, 58, 48, 226, @"<BODY><BASEFONT Color=#5c4c32><BIG><RIGHT>" + level + "</RIGHT></BIG></BASEFONT></BODY>", (bool)false, (bool)false);
|
||||
|
||||
AddHtml( 38, 8, 231, 20, @"<BODY><BASEFONT Color=#111f5f><BIG><CENTER>TRADES</CENTER></BIG></BASEFONT></BODY>", (bool)false, (bool)false);
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState sender, RelayInfo info )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue