This commit is contained in:
commit
47711d616e
2644 changed files with 479454 additions and 0 deletions
87
Scripts/Skills/Anatomy.cs
Normal file
87
Scripts/Skills/Anatomy.cs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Anatomy
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Anatomy].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.Target = new Anatomy.InternalTarget();
|
||||
|
||||
m.SendLocalizedMessage( 500321 ); // Whom shall I examine?
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base ( 8, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( from == targeted )
|
||||
{
|
||||
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500324 ); // You know yourself quite well enough already.
|
||||
}
|
||||
else if ( targeted is TownCrier )
|
||||
{
|
||||
((TownCrier)targeted).PrivateOverheadMessage( MessageType.Regular, 0x3B2, 500322, from.NetState ); // This person looks fine to me, though he may have some news...
|
||||
}
|
||||
else if ( targeted is BaseVendor && ((BaseVendor)targeted).IsInvulnerable )
|
||||
{
|
||||
((BaseVendor)targeted).PrivateOverheadMessage( MessageType.Regular, 0x3B2, 500326, from.NetState ); // That can not be inspected.
|
||||
}
|
||||
else if ( targeted is Mobile )
|
||||
{
|
||||
Mobile targ = (Mobile)targeted;
|
||||
|
||||
int marginOfError = Math.Max( 0, 25 - (int)(from.Skills[SkillName.Anatomy].Value / 4) );
|
||||
|
||||
int str = targ.Str + Utility.RandomMinMax( -marginOfError, +marginOfError );
|
||||
int dex = targ.Dex + Utility.RandomMinMax( -marginOfError, +marginOfError );
|
||||
int stm = ((targ.Stam * 100) / Math.Max( targ.StamMax, 1 )) + Utility.RandomMinMax( -marginOfError, +marginOfError );
|
||||
|
||||
int strMod = str / 10;
|
||||
int dexMod = dex / 10;
|
||||
int stmMod = stm / 10;
|
||||
|
||||
if ( strMod < 0 ) strMod = 0;
|
||||
else if ( strMod > 10 ) strMod = 10;
|
||||
|
||||
if ( dexMod < 0 ) dexMod = 0;
|
||||
else if ( dexMod > 10 ) dexMod = 10;
|
||||
|
||||
if ( stmMod > 10 ) stmMod = 10;
|
||||
else if ( stmMod < 0 ) stmMod = 0;
|
||||
|
||||
if ( from.CheckTargetSkill( SkillName.Anatomy, targ, 0, 100 ) )
|
||||
{
|
||||
targ.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1038045 + (strMod * 11) + dexMod, from.NetState ); // That looks [strong] and [dexterous].
|
||||
|
||||
if ( from.Skills[SkillName.Anatomy].Base >= 65.0 )
|
||||
targ.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1038303 + stmMod, from.NetState ); // That being is at [10,20,...] percent endurance.
|
||||
}
|
||||
else
|
||||
{
|
||||
targ.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1042666, from.NetState ); // You can not quite get a sense of their physical characteristics.
|
||||
}
|
||||
}
|
||||
else if ( targeted is Item )
|
||||
{
|
||||
((Item)targeted).SendLocalizedMessageTo( from, 500323, "" ); // Only living things have anatomies!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
356
Scripts/Skills/AnimalLore.cs
Normal file
356
Scripts/Skills/AnimalLore.cs
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class AnimalLore
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.AnimalLore].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse(Mobile m)
|
||||
{
|
||||
m.Target = new InternalTarget();
|
||||
|
||||
m.SendLocalizedMessage( 500328 ); // What animal should I look at?
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base( 8, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( !from.Alive )
|
||||
{
|
||||
from.SendLocalizedMessage( 500331 ); // The spirits of the dead are not the province of animal lore.
|
||||
}
|
||||
else if ( targeted is BaseCreature )
|
||||
{
|
||||
BaseCreature c = (BaseCreature)targeted;
|
||||
|
||||
if ( !c.IsDeadPet )
|
||||
{
|
||||
if ( c.Body.IsAnimal || c.Body.IsMonster || c.Body.IsSea )
|
||||
{
|
||||
if ( (!c.Controlled || !c.Tamable) && from.Skills[SkillName.AnimalLore].Base < 100.0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049674 ); // At your skill level, you can only lore tamed creatures.
|
||||
}
|
||||
else if ( !c.Tamable && from.Skills[SkillName.AnimalLore].Base < 110.0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049675 ); // At your skill level, you can only lore tamed or tameable creatures.
|
||||
}
|
||||
else if ( !from.CheckTargetSkill( SkillName.AnimalLore, c, 0.0, 120.0 ) )
|
||||
{
|
||||
from.SendLocalizedMessage( 500334 ); // You can't think of anything you know offhand.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.CloseGump( typeof( AnimalLoreGump ) );
|
||||
from.SendGump( new AnimalLoreGump( c ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500329 ); // That's not an animal!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500331 ); // The spirits of the dead are not the province of animal lore.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500329 ); // That's not an animal!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AnimalLoreGump : Gump
|
||||
{
|
||||
private static string FormatSkill( BaseCreature c, SkillName name )
|
||||
{
|
||||
Skill skill = c.Skills[name];
|
||||
|
||||
if ( skill.Base < 10.0 )
|
||||
return "<div align=right>---</div>";
|
||||
|
||||
return String.Format( "<div align=right>{0:F1}</div>", skill.Base );
|
||||
}
|
||||
|
||||
private static string FormatAttributes( int cur, int max )
|
||||
{
|
||||
if ( max == 0 )
|
||||
return "<div align=right>---</div>";
|
||||
|
||||
return String.Format( "<div align=right>{0}/{1}</div>", cur, max );
|
||||
}
|
||||
|
||||
private static string FormatStat( int val )
|
||||
{
|
||||
if ( val == 0 )
|
||||
return "<div align=right>---</div>";
|
||||
|
||||
return String.Format( "<div align=right>{0}</div>", val );
|
||||
}
|
||||
|
||||
private static string FormatDouble( double val )
|
||||
{
|
||||
if ( val == 0 )
|
||||
return "<div align=right>---</div>";
|
||||
|
||||
return String.Format( "<div align=right>{0:F1}</div>", val );
|
||||
}
|
||||
|
||||
private static string FormatElement( int val )
|
||||
{
|
||||
if ( val <= 0 )
|
||||
return "<div align=right>---</div>";
|
||||
|
||||
return String.Format( "<div align=right>{0}%</div>", val );
|
||||
}
|
||||
|
||||
private const int LabelColor = 0x24E5;
|
||||
|
||||
public AnimalLoreGump( BaseCreature c ) : base( 250, 50 )
|
||||
{
|
||||
AddPage( 0 );
|
||||
|
||||
AddImage( 100, 100, 2080 );
|
||||
AddImage( 118, 137, 2081 );
|
||||
AddImage( 118, 207, 2081 );
|
||||
AddImage( 118, 277, 2081 );
|
||||
AddImage( 118, 347, 2083 );
|
||||
|
||||
AddHtml( 147, 108, 210, 18, String.Format( "<center><i>{0}</i></center>", c.Name ), false, false );
|
||||
|
||||
AddButton( 240, 77, 2093, 2093, 2, GumpButtonType.Reply, 0 );
|
||||
|
||||
AddImage( 140, 138, 2091 );
|
||||
AddImage( 140, 335, 2091 );
|
||||
|
||||
int pages = ( Core.AOS ? 5 : 3 );
|
||||
int page = 0;
|
||||
|
||||
|
||||
#region Attributes
|
||||
AddPage( ++page );
|
||||
|
||||
AddImage( 128, 152, 2086 );
|
||||
AddHtmlLocalized( 147, 150, 160, 18, 1049593, 200, false, false ); // Attributes
|
||||
|
||||
AddHtmlLocalized( 153, 168, 160, 18, 1049578, LabelColor, false, false ); // Hits
|
||||
AddHtml( 280, 168, 75, 18, FormatAttributes( c.Hits, c.HitsMax ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 186, 160, 18, 1049579, LabelColor, false, false ); // Stamina
|
||||
AddHtml( 280, 186, 75, 18, FormatAttributes( c.Stam, c.StamMax ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 204, 160, 18, 1049580, LabelColor, false, false ); // Mana
|
||||
AddHtml( 280, 204, 75, 18, FormatAttributes( c.Mana, c.ManaMax ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 222, 160, 18, 1028335, LabelColor, false, false ); // Strength
|
||||
AddHtml( 320, 222, 35, 18, FormatStat( c.Str ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 240, 160, 18, 3000113, LabelColor, false, false ); // Dexterity
|
||||
AddHtml( 320, 240, 35, 18, FormatStat( c.Dex ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 258, 160, 18, 3000112, LabelColor, false, false ); // Intelligence
|
||||
AddHtml( 320, 258, 35, 18, FormatStat( c.Int ), false, false );
|
||||
|
||||
if ( Core.AOS )
|
||||
{
|
||||
int y = 276;
|
||||
|
||||
if ( Core.SE )
|
||||
{
|
||||
double bd = Items.BaseInstrument.GetBaseDifficulty( c );
|
||||
if ( c.Uncalmable )
|
||||
bd = 0;
|
||||
|
||||
AddHtmlLocalized( 153, 276, 160, 18, 1070793, LabelColor, false, false ); // Barding Difficulty
|
||||
AddHtml( 320, y, 35, 18, FormatDouble( bd ), false, false );
|
||||
|
||||
y += 18;
|
||||
}
|
||||
|
||||
AddImage( 128, y + 2, 2086 );
|
||||
AddHtmlLocalized( 147, y, 160, 18, 1049594, 200, false, false ); // Loyalty Rating
|
||||
y += 18;
|
||||
|
||||
AddHtmlLocalized( 153, y, 160, 18, (!c.Controlled || c.Loyalty == 0) ? 1061643 : 1049595 + (c.Loyalty / 10), LabelColor, false, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
AddImage( 128, 278, 2086 );
|
||||
AddHtmlLocalized( 147, 276, 160, 18, 3001016, 200, false, false ); // Miscellaneous
|
||||
|
||||
AddHtmlLocalized( 153, 294, 160, 18, 1049581, LabelColor, false, false ); // Armor Rating
|
||||
AddHtml( 320, 294, 35, 18, FormatStat( c.VirtualArmor ), false, false );
|
||||
}
|
||||
|
||||
AddButton( 340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1 );
|
||||
AddButton( 317, 358, 5603, 5607, 0, GumpButtonType.Page, pages );
|
||||
#endregion
|
||||
|
||||
#region Resistances
|
||||
if ( Core.AOS )
|
||||
{
|
||||
AddPage( ++page );
|
||||
|
||||
AddImage( 128, 152, 2086 );
|
||||
AddHtmlLocalized( 147, 150, 160, 18, 1061645, 200, false, false ); // Resistances
|
||||
|
||||
AddHtmlLocalized( 153, 168, 160, 18, 1061646, LabelColor, false, false ); // Physical
|
||||
AddHtml( 320, 168, 35, 18, FormatElement( c.PhysicalResistance ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 186, 160, 18, 1061647, LabelColor, false, false ); // Fire
|
||||
AddHtml( 320, 186, 35, 18, FormatElement( c.FireResistance ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 204, 160, 18, 1061648, LabelColor, false, false ); // Cold
|
||||
AddHtml( 320, 204, 35, 18, FormatElement( c.ColdResistance ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 222, 160, 18, 1061649, LabelColor, false, false ); // Poison
|
||||
AddHtml( 320, 222, 35, 18, FormatElement( c.PoisonResistance ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 240, 160, 18, 1061650, LabelColor, false, false ); // Energy
|
||||
AddHtml( 320, 240, 35, 18, FormatElement( c.EnergyResistance ), false, false );
|
||||
|
||||
AddButton( 340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1 );
|
||||
AddButton( 317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1 );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Damage
|
||||
if ( Core.AOS )
|
||||
{
|
||||
AddPage( ++page );
|
||||
|
||||
AddImage( 128, 152, 2086 );
|
||||
AddHtmlLocalized( 147, 150, 160, 18, 1017319, 200, false, false ); // Damage
|
||||
|
||||
AddHtmlLocalized( 153, 168, 160, 18, 1061646, LabelColor, false, false ); // Physical
|
||||
AddHtml( 320, 168, 35, 18, FormatElement( c.PhysicalDamage ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 186, 160, 18, 1061647, LabelColor, false, false ); // Fire
|
||||
AddHtml( 320, 186, 35, 18, FormatElement( c.FireDamage ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 204, 160, 18, 1061648, LabelColor, false, false ); // Cold
|
||||
AddHtml( 320, 204, 35, 18, FormatElement( c.ColdDamage ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 222, 160, 18, 1061649, LabelColor, false, false ); // Poison
|
||||
AddHtml( 320, 222, 35, 18, FormatElement( c.PoisonDamage ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 240, 160, 18, 1061650, LabelColor, false, false ); // Energy
|
||||
AddHtml( 320, 240, 35, 18, FormatElement( c.EnergyDamage ), false, false );
|
||||
|
||||
AddButton( 340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1 );
|
||||
AddButton( 317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1 );
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Skills
|
||||
AddPage( ++page );
|
||||
|
||||
AddImage( 128, 152, 2086 );
|
||||
AddHtmlLocalized( 147, 150, 160, 18, 3001030, 200, false, false ); // Combat Ratings
|
||||
|
||||
AddHtmlLocalized( 153, 168, 160, 18, 1044103, LabelColor, false, false ); // Wrestling
|
||||
AddHtml( 320, 168, 35, 18, FormatSkill( c, SkillName.Wrestling ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 186, 160, 18, 1044087, LabelColor, false, false ); // Tactics
|
||||
AddHtml( 320, 186, 35, 18, FormatSkill( c, SkillName.Tactics ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 204, 160, 18, 1044086, LabelColor, false, false ); // Magic Resistance
|
||||
AddHtml( 320, 204, 35, 18, FormatSkill( c, SkillName.MagicResist ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 222, 160, 18, 1044061, LabelColor, false, false ); // Anatomy
|
||||
AddHtml( 320, 222, 35, 18, FormatSkill( c, SkillName.Anatomy ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 240, 160, 18, 1044090, LabelColor, false, false ); // Poisoning
|
||||
AddHtml( 320, 240, 35, 18, FormatSkill( c, SkillName.Poisoning ), false, false );
|
||||
|
||||
AddImage( 128, 260, 2086 );
|
||||
AddHtmlLocalized( 147, 258, 160, 18, 3001032, 200, false, false ); // Lore & Knowledge
|
||||
|
||||
AddHtmlLocalized( 153, 276, 160, 18, 1044085, LabelColor, false, false ); // Magery
|
||||
AddHtml( 320, 276, 35, 18, FormatSkill( c, SkillName.Magery ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 294, 160, 18, 1044076, LabelColor, false, false ); // Evaluating Intelligence
|
||||
AddHtml( 320, 294, 35, 18,FormatSkill( c, SkillName.EvalInt ), false, false );
|
||||
|
||||
AddHtmlLocalized( 153, 312, 160, 18, 1044106, LabelColor, false, false ); // Meditation
|
||||
AddHtml( 320, 312, 35, 18, FormatSkill( c, SkillName.Meditation ), false, false );
|
||||
|
||||
AddButton( 340, 358, 5601, 5605, 0, GumpButtonType.Page, page + 1 );
|
||||
AddButton( 317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1 );
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
AddPage( ++page );
|
||||
|
||||
AddImage( 128, 152, 2086 );
|
||||
AddHtmlLocalized( 147, 150, 160, 18, 1049563, 200, false, false ); // Preferred Foods
|
||||
|
||||
int foodPref = 3000340;
|
||||
|
||||
if ( (c.FavoriteFood & FoodType.FruitsAndVegies) != 0 )
|
||||
foodPref = 1049565; // Fruits and Vegetables
|
||||
else if ( (c.FavoriteFood & FoodType.GrainsAndHay) != 0 )
|
||||
foodPref = 1049566; // Grains and Hay
|
||||
else if ( (c.FavoriteFood & FoodType.Fish) != 0 )
|
||||
foodPref = 1049568; // Fish
|
||||
else if ( (c.FavoriteFood & FoodType.Meat) != 0 )
|
||||
foodPref = 1049564; // Meat
|
||||
|
||||
AddHtmlLocalized( 153, 168, 160, 18, foodPref, LabelColor, false, false );
|
||||
|
||||
AddImage( 128, 188, 2086 );
|
||||
AddHtmlLocalized( 147, 186, 160, 18, 1049569, 200, false, false ); // Pack Instincts
|
||||
|
||||
int packInstinct = 3000340;
|
||||
|
||||
if ( (c.PackInstinct & PackInstinct.Canine) != 0 )
|
||||
packInstinct = 1049570; // Canine
|
||||
else if ( (c.PackInstinct & PackInstinct.Ostard) != 0 )
|
||||
packInstinct = 1049571; // Ostard
|
||||
else if ( (c.PackInstinct & PackInstinct.Feline) != 0 )
|
||||
packInstinct = 1049572; // Feline
|
||||
else if ( (c.PackInstinct & PackInstinct.Arachnid) != 0 )
|
||||
packInstinct = 1049573; // Arachnid
|
||||
else if ( (c.PackInstinct & PackInstinct.Daemon) != 0 )
|
||||
packInstinct = 1049574; // Daemon
|
||||
else if ( (c.PackInstinct & PackInstinct.Bear) != 0 )
|
||||
packInstinct = 1049575; // Bear
|
||||
else if ( (c.PackInstinct & PackInstinct.Equine) != 0 )
|
||||
packInstinct = 1049576; // Equine
|
||||
else if ( (c.PackInstinct & PackInstinct.Bull) != 0 )
|
||||
packInstinct = 1049577; // Bull
|
||||
|
||||
AddHtmlLocalized( 153, 204, 160, 18, packInstinct, LabelColor, false, false );
|
||||
|
||||
if ( !Core.AOS )
|
||||
{
|
||||
AddImage( 128, 224, 2086 );
|
||||
AddHtmlLocalized( 147, 222, 160, 18, 1049594, 200, false, false ); // Loyalty Rating
|
||||
|
||||
AddHtmlLocalized( 153, 240, 160, 18, (!c.Controlled || c.Loyalty == 0) ? 1061643 : 1049595 + (c.Loyalty / 10), LabelColor, false, false );
|
||||
}
|
||||
|
||||
AddButton( 340, 358, 5601, 5605, 0, GumpButtonType.Page, 1 );
|
||||
AddButton( 317, 358, 5603, 5607, 0, GumpButtonType.Page, page - 1 );
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
363
Scripts/Skills/AnimalTaming.cs
Normal file
363
Scripts/Skills/AnimalTaming.cs
Normal file
|
|
@ -0,0 +1,363 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
using Server.Factions;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class AnimalTaming
|
||||
{
|
||||
private static Hashtable m_BeingTamed = new Hashtable();
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.AnimalTaming].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
private static bool m_DisableMessage;
|
||||
|
||||
public static bool DisableMessage
|
||||
{
|
||||
get{ return m_DisableMessage; }
|
||||
set{ m_DisableMessage = value; }
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
m.Target = new InternalTarget();
|
||||
m.RevealingAction();
|
||||
|
||||
if ( !m_DisableMessage )
|
||||
m.SendLocalizedMessage( 502789 ); // Tame which animal?
|
||||
|
||||
return TimeSpan.FromHours( 6.0 );
|
||||
}
|
||||
|
||||
public static bool CheckMastery( Mobile tamer, BaseCreature creature )
|
||||
{
|
||||
BaseCreature familiar = (BaseCreature)Spells.Necromancy.SummonFamiliarSpell.Table[tamer];
|
||||
|
||||
if ( familiar != null && !familiar.Deleted && familiar is DarkWolfFamiliar )
|
||||
{
|
||||
if ( creature is DireWolf || creature is GreyWolf || creature is TimberWolf || creature is WhiteWolf )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool MustBeSubdued( BaseCreature bc )
|
||||
{
|
||||
return bc.SubdueBeforeTame && (bc.Hits > (bc.HitsMax / 10));
|
||||
}
|
||||
|
||||
public static void ScaleStats( BaseCreature bc, double scalar )
|
||||
{
|
||||
if ( bc.RawStr > 0 )
|
||||
bc.RawStr = (int)Math.Max( 1, bc.RawStr * scalar );
|
||||
|
||||
if ( bc.RawDex > 0 )
|
||||
bc.RawDex = (int)Math.Max( 1, bc.RawDex * scalar );
|
||||
|
||||
if ( bc.RawInt > 0 )
|
||||
bc.RawInt = (int)Math.Max( 1, bc.RawInt * scalar );
|
||||
|
||||
if ( bc.HitsMaxSeed > 0 )
|
||||
{
|
||||
bc.HitsMaxSeed = (int)Math.Max( 1, bc.HitsMaxSeed * scalar );
|
||||
bc.Hits = bc.Hits;
|
||||
}
|
||||
|
||||
if ( bc.StamMaxSeed > 0 )
|
||||
{
|
||||
bc.StamMaxSeed = (int)Math.Max( 1, bc.StamMaxSeed * scalar );
|
||||
bc.Stam = bc.Stam;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ScaleSkills( BaseCreature bc, double scalar )
|
||||
{
|
||||
for ( int i = 0; i < bc.Skills.Length; ++i )
|
||||
{
|
||||
bc.Skills[i].Base *= scalar;
|
||||
if ( bc.Skills[i].Base > 100.0 )
|
||||
bc.Skills[i].Cap = bc.Skills[i].Base;
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private bool m_SetSkillTime = true;
|
||||
|
||||
public InternalTarget() : base ( 2, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
if ( targeted is BaseCreature )
|
||||
{
|
||||
BaseCreature creature = (BaseCreature)targeted;
|
||||
|
||||
if ( !creature.Tamable )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1049655, from.NetState ); // That creature cannot be tamed.
|
||||
}
|
||||
else if ( creature.Controlled )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502804, from.NetState ); // That animal looks tame already.
|
||||
}
|
||||
else if ( from.Female && !creature.AllowFemaleTamer )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1049653, from.NetState ); // That creature can only be tamed by males.
|
||||
}
|
||||
else if ( !from.Female && !creature.AllowMaleTamer )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1049652, from.NetState ); // That creature can only be tamed by females.
|
||||
}
|
||||
else if ( from.Followers + creature.ControlSlots > from.FollowersMax )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049611 ); // You have too many followers to tame that creature.
|
||||
}
|
||||
else if ( creature.Owners.Count >= BaseCreature.MaxOwners && !creature.Owners.Contains( from ) )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1005615, from.NetState ); // This animal has had too many owners and is too upset for you to tame.
|
||||
}
|
||||
else if ( MustBeSubdued( creature ) )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1054025, from.NetState ); // You must subdue this creature before you can tame it!
|
||||
}
|
||||
else if ( CheckMastery( from, creature ) || from.Skills[SkillName.AnimalTaming].Value >= creature.MinTameSkill )
|
||||
{
|
||||
FactionWarHorse warHorse = creature as FactionWarHorse;
|
||||
|
||||
if ( warHorse != null )
|
||||
{
|
||||
Faction faction = Faction.Find( from );
|
||||
|
||||
if ( faction == null || faction != warHorse.Faction )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1042590, from.NetState ); // You cannot tame this creature.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_BeingTamed.Contains( targeted ) )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502802, from.NetState ); // Someone else is already taming this.
|
||||
}
|
||||
else if ( creature.CanAngerOnTame && 0.95 >= Utility.RandomDouble() )
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502805, from.NetState ); // You seem to anger the beast!
|
||||
creature.PlaySound( creature.GetAngerSound() );
|
||||
creature.Direction = creature.GetDirectionTo( from );
|
||||
creature.Combatant = from;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BeingTamed[targeted] = from;
|
||||
|
||||
from.LocalOverheadMessage( MessageType.Emote, 0x59, 1010597 ); // You start to tame the creature.
|
||||
from.NonlocalOverheadMessage( MessageType.Emote, 0x59, 1010598 ); // *begins taming a creature.*
|
||||
|
||||
new InternalTimer( from, creature, Utility.Random( 3, 2 ) ).Start();
|
||||
|
||||
m_SetSkillTime = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502806, from.NetState ); // You have no chance of taming this creature.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
((Mobile)targeted).PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502469, from.NetState ); // That being cannot be tamed.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 502801 ); // You can't tame that!
|
||||
}
|
||||
}
|
||||
public static void AdjustSkillCaps( BaseCreature bc )
|
||||
{
|
||||
for ( int i = 0; i < bc.Skills.Length; ++i )
|
||||
{
|
||||
if ( bc.Skills[i].Base > bc.Skills[i].Cap )
|
||||
bc.Skills[i].Cap = bc.Skills[i].Base;
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private Mobile m_Tamer;
|
||||
private BaseCreature m_Creature;
|
||||
private int m_MaxCount;
|
||||
private int m_Count;
|
||||
private bool m_Paralyzed;
|
||||
private DateTime m_StartTime;
|
||||
|
||||
public InternalTimer( Mobile tamer, BaseCreature creature, int count ) : base( TimeSpan.FromSeconds( 3.0 ), TimeSpan.FromSeconds( 3.0 ), count )
|
||||
{
|
||||
m_Tamer = tamer;
|
||||
m_Creature = creature;
|
||||
m_MaxCount = count;
|
||||
m_Paralyzed = creature.Paralyzed;
|
||||
m_StartTime = DateTime.Now;
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Count++;
|
||||
|
||||
DamageEntry de = m_Creature.FindMostRecentDamageEntry( false );
|
||||
bool alreadyOwned = m_Creature.Owners.Contains( m_Tamer );
|
||||
|
||||
if ( !m_Tamer.InRange( m_Creature, 6 ) )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502795, m_Tamer.NetState ); // You are too far away to continue taming.
|
||||
Stop();
|
||||
}
|
||||
else if ( !m_Tamer.CheckAlive() )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502796, m_Tamer.NetState ); // You are dead, and cannot continue taming.
|
||||
Stop();
|
||||
}
|
||||
else if ( !m_Tamer.CanSee( m_Creature ) || !m_Tamer.InLOS( m_Creature ) )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1049654, m_Tamer.NetState ); // You do not have a clear path to the animal you are taming, and must cease your attempt.
|
||||
Stop();
|
||||
}
|
||||
else if ( !m_Creature.Tamable )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1049655, m_Tamer.NetState ); // That creature cannot be tamed.
|
||||
Stop();
|
||||
}
|
||||
else if ( m_Creature.Controlled )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502804, m_Tamer.NetState ); // That animal looks tame already.
|
||||
Stop();
|
||||
}
|
||||
else if ( m_Creature.Owners.Count >= BaseCreature.MaxOwners && !m_Creature.Owners.Contains( m_Tamer ) )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1005615, m_Tamer.NetState ); // This animal has had too many owners and is too upset for you to tame.
|
||||
Stop();
|
||||
}
|
||||
else if ( MustBeSubdued( m_Creature ) )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1054025, m_Tamer.NetState ); // You must subdue this creature before you can tame it!
|
||||
Stop();
|
||||
}
|
||||
else if ( de != null && de.LastDamage > m_StartTime )
|
||||
{
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502794, m_Tamer.NetState ); // The animal is too angry to continue taming.
|
||||
Stop();
|
||||
}
|
||||
else if ( m_Count < m_MaxCount )
|
||||
{
|
||||
m_Tamer.RevealingAction();
|
||||
|
||||
switch ( Utility.Random( 3 ) )
|
||||
{
|
||||
case 0: m_Tamer.PublicOverheadMessage( MessageType.Regular, 0x3B2, Utility.Random( 502790, 4 ) ); break;
|
||||
case 1: m_Tamer.PublicOverheadMessage( MessageType.Regular, 0x3B2, Utility.Random( 1005608, 6 ) ); break;
|
||||
case 2: m_Tamer.PublicOverheadMessage( MessageType.Regular, 0x3B2, Utility.Random( 1010593, 4 ) ); break;
|
||||
}
|
||||
|
||||
if ( !alreadyOwned ) // Passively check animal lore for gain
|
||||
m_Tamer.CheckTargetSkill( SkillName.AnimalLore, m_Creature, 0.0, 120.0 );
|
||||
|
||||
if ( m_Creature.Paralyzed )
|
||||
m_Paralyzed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Tamer.RevealingAction();
|
||||
m_Tamer.NextSkillTime = DateTime.Now;
|
||||
m_BeingTamed.Remove( m_Creature );
|
||||
|
||||
if ( m_Creature.Paralyzed )
|
||||
m_Paralyzed = true;
|
||||
|
||||
if ( !alreadyOwned ) // Passively check animal lore for gain
|
||||
m_Tamer.CheckTargetSkill( SkillName.AnimalLore, m_Creature, 0.0, 120.0 );
|
||||
|
||||
double minSkill = m_Creature.MinTameSkill + (m_Creature.Owners.Count * 6.0);
|
||||
|
||||
if ( minSkill > -24.9 && CheckMastery( m_Tamer, m_Creature ) )
|
||||
minSkill = -24.9; // 50% at 0.0?
|
||||
|
||||
minSkill += 24.9;
|
||||
|
||||
if ( alreadyOwned || m_Tamer.CheckTargetSkill( SkillName.AnimalTaming, m_Creature, minSkill - 25.0, minSkill + 25.0 ) )
|
||||
{
|
||||
if ( m_Creature.Owners.Count == 0 ) // First tame
|
||||
{
|
||||
if ( m_Paralyzed )
|
||||
ScaleSkills( m_Creature, 0.86 ); // 86% of original skills if they were paralyzed during the taming
|
||||
else
|
||||
ScaleSkills( m_Creature, 0.90 ); // 90% of original skills
|
||||
|
||||
if ( m_Creature.StatLossAfterTame )
|
||||
ScaleStats( m_Creature, 0.50 );
|
||||
|
||||
if( Core.SE )
|
||||
AdjustSkillCaps( m_Creature );
|
||||
}
|
||||
|
||||
if ( alreadyOwned )
|
||||
{
|
||||
m_Tamer.SendLocalizedMessage( 502797 ); // That wasn't even challenging.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502799, m_Tamer.NetState ); // It seems to accept you as master.
|
||||
m_Creature.Owners.Add( m_Tamer );
|
||||
}
|
||||
|
||||
m_Creature.SetControlMaster( m_Tamer );
|
||||
m_Creature.IsBonded = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Creature.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 502798, m_Tamer.NetState ); // You fail to tame the creature.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
167
Scripts/Skills/ArmsLore.cs
Normal file
167
Scripts/Skills/ArmsLore.cs
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class ArmsLore
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.ArmsLore].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse(Mobile m)
|
||||
{
|
||||
m.Target = new InternalTarget();
|
||||
|
||||
m.SendLocalizedMessage( 500349 ); // What item do you wish to get information about?
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
[PlayerVendorTarget]
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base( 2, false, TargetFlags.None )
|
||||
{
|
||||
AllowNonlocal = true;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( targeted is BaseWeapon )
|
||||
{
|
||||
if ( from.CheckTargetSkill( SkillName.ArmsLore, targeted, 0, 100 ) )
|
||||
{
|
||||
BaseWeapon weap = (BaseWeapon)targeted;
|
||||
|
||||
if ( weap.MaxHitPoints != 0 )
|
||||
{
|
||||
int hp = (int)((weap.HitPoints / (double)weap.MaxHitPoints) * 10);
|
||||
|
||||
if ( hp < 0 )
|
||||
hp = 0;
|
||||
else if ( hp > 9 )
|
||||
hp = 9;
|
||||
|
||||
from.SendLocalizedMessage( 1038285 + hp );
|
||||
}
|
||||
|
||||
int damage = (weap.MaxDamage + weap.MinDamage) / 2;
|
||||
int hand = (weap.Layer == Layer.OneHanded ? 0 : 1);
|
||||
|
||||
if ( damage < 3 )
|
||||
damage = 0;
|
||||
else
|
||||
damage = (int)Math.Ceiling( Math.Min( damage, 30 ) / 5.0 );
|
||||
/*
|
||||
else if ( damage < 6 )
|
||||
damage = 1;
|
||||
else if ( damage < 11 )
|
||||
damage = 2;
|
||||
else if ( damage < 16 )
|
||||
damage = 3;
|
||||
else if ( damage < 21 )
|
||||
damage = 4;
|
||||
else if ( damage < 26 )
|
||||
damage = 5;
|
||||
else
|
||||
damage = 6;
|
||||
* */
|
||||
|
||||
WeaponType type = weap.Type;
|
||||
|
||||
if ( type == WeaponType.Ranged )
|
||||
from.SendLocalizedMessage( 1038224 + (damage * 9) );
|
||||
else if ( type == WeaponType.Piercing )
|
||||
from.SendLocalizedMessage( 1038218 + hand + (damage * 9) );
|
||||
else if ( type == WeaponType.Slashing )
|
||||
from.SendLocalizedMessage( 1038220 + hand + (damage * 9) );
|
||||
else if ( type == WeaponType.Bashing )
|
||||
from.SendLocalizedMessage( 1038222 + hand + (damage * 9) );
|
||||
else
|
||||
from.SendLocalizedMessage( 1038216 + hand + (damage * 9) );
|
||||
|
||||
if ( weap.Poison != null && weap.PoisonCharges > 0 )
|
||||
from.SendLocalizedMessage( 1038284 ); // It appears to have poison smeared on it.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500353 ); // You are not certain...
|
||||
}
|
||||
}
|
||||
else if(targeted is BaseArmor)
|
||||
{
|
||||
if( from.CheckTargetSkill(SkillName.ArmsLore, targeted, 0, 100) )
|
||||
{
|
||||
BaseArmor arm = (BaseArmor)targeted;
|
||||
|
||||
if ( arm.MaxHitPoints != 0 )
|
||||
{
|
||||
int hp = (int)((arm.HitPoints / (double)arm.MaxHitPoints) * 10);
|
||||
|
||||
if ( hp < 0 )
|
||||
hp = 0;
|
||||
else if ( hp > 9 )
|
||||
hp = 9;
|
||||
|
||||
from.SendLocalizedMessage( 1038285 + hp );
|
||||
}
|
||||
|
||||
|
||||
from.SendLocalizedMessage( 1038295 + (int)Math.Ceiling( Math.Min( arm.ArmorRating, 35 ) / 5.0 ) );
|
||||
/*
|
||||
if ( arm.ArmorRating < 1 )
|
||||
from.SendLocalizedMessage( 1038295 ); // This armor offers no defense against attackers.
|
||||
else if ( arm.ArmorRating < 6 )
|
||||
from.SendLocalizedMessage( 1038296 ); // This armor provides almost no protection.
|
||||
else if ( arm.ArmorRating < 11 )
|
||||
from.SendLocalizedMessage( 1038297 ); // This armor provides very little protection.
|
||||
else if ( arm.ArmorRating < 16 )
|
||||
from.SendLocalizedMessage( 1038298 ); // This armor offers some protection against blows.
|
||||
else if ( arm.ArmorRating < 21 )
|
||||
from.SendLocalizedMessage( 1038299 ); // This armor serves as sturdy protection.
|
||||
else if ( arm.ArmorRating < 26 )
|
||||
from.SendLocalizedMessage( 1038300 ); // This armor is a superior defense against attack.
|
||||
else if ( arm.ArmorRating < 31 )
|
||||
from.SendLocalizedMessage( 1038301 ); // This armor offers excellent protection.
|
||||
else
|
||||
from.SendLocalizedMessage( 1038302 ); // This armor is superbly crafted to provide maximum protection.
|
||||
* */
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500353 ); // You are not certain...
|
||||
}
|
||||
}
|
||||
else if ( targeted is SwampDragon && ((SwampDragon)targeted).HasBarding )
|
||||
{
|
||||
SwampDragon pet = (SwampDragon)targeted;
|
||||
|
||||
if ( from.CheckTargetSkill( SkillName.ArmsLore, targeted, 0, 100 ) )
|
||||
{
|
||||
int perc = (4 * pet.BardingHP) / pet.BardingMaxHP;
|
||||
|
||||
if ( perc < 0 )
|
||||
perc = 0;
|
||||
else if ( perc > 4 )
|
||||
perc = 4;
|
||||
|
||||
pet.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1053021 - perc, from.NetState );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500353 ); // You are not certain...
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500352 ); // This is neither weapon nor armor.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
175
Scripts/Skills/Begging.cs
Normal file
175
Scripts/Skills/Begging.cs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Misc;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Begging
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Begging].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.RevealingAction();
|
||||
|
||||
m.Target = new InternalTarget();
|
||||
m.RevealingAction();
|
||||
|
||||
m.SendLocalizedMessage( 500397 ); // To whom do you wish to grovel?
|
||||
|
||||
return TimeSpan.FromHours( 6.0 );
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
private bool m_SetSkillTime = true;
|
||||
|
||||
public InternalTarget() : base ( 12, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile from )
|
||||
{
|
||||
if ( m_SetSkillTime )
|
||||
from.NextSkillTime = DateTime.Now;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
from.RevealingAction();
|
||||
|
||||
int number = -1;
|
||||
|
||||
if ( targeted is Mobile )
|
||||
{
|
||||
Mobile targ = (Mobile)targeted;
|
||||
|
||||
if ( targ.Player ) // We can't beg from players
|
||||
{
|
||||
number = 500398; // Perhaps just asking would work better.
|
||||
}
|
||||
else if ( !targ.Body.IsHuman ) // Make sure the NPC is human
|
||||
{
|
||||
number = 500399; // There is little chance of getting money from that!
|
||||
}
|
||||
else if ( !from.InRange( targ, 2 ) )
|
||||
{
|
||||
if ( !targ.Female )
|
||||
number = 500401; // You are too far away to beg from him.
|
||||
else
|
||||
number = 500402; // You are too far away to beg from her.
|
||||
}
|
||||
else if ( from.Mounted ) // If we're on a mount, who would give us money?
|
||||
{
|
||||
number = 500404; // They seem unwilling to give you any money.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Face eachother
|
||||
from.Direction = from.GetDirectionTo( targ );
|
||||
targ.Direction = targ.GetDirectionTo( from );
|
||||
|
||||
from.Animate( 32, 5, 1, true, false, 0 ); // Bow
|
||||
|
||||
new InternalTimer( from, targ ).Start();
|
||||
|
||||
m_SetSkillTime = false;
|
||||
}
|
||||
}
|
||||
else // Not a Mobile
|
||||
{
|
||||
number = 500399; // There is little chance of getting money from that!
|
||||
}
|
||||
|
||||
if ( number != -1 )
|
||||
from.SendLocalizedMessage( number );
|
||||
}
|
||||
|
||||
private class InternalTimer : Timer
|
||||
{
|
||||
private Mobile m_From, m_Target;
|
||||
|
||||
public InternalTimer( Mobile from, Mobile target ) : base( TimeSpan.FromSeconds( 2.0 ) )
|
||||
{
|
||||
m_From = from;
|
||||
m_Target = target;
|
||||
Priority = TimerPriority.TwoFiftyMS;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
Container theirPack = m_Target.Backpack;
|
||||
|
||||
double badKarmaChance = 0.5 - ((double)m_From.Karma / 8570);
|
||||
|
||||
if ( theirPack == null )
|
||||
{
|
||||
m_From.SendLocalizedMessage( 500404 ); // They seem unwilling to give you any money.
|
||||
}
|
||||
else if ( m_From.Karma < 0 && badKarmaChance > Utility.RandomDouble() )
|
||||
{
|
||||
m_Target.PublicOverheadMessage( MessageType.Regular, m_Target.SpeechHue, 500406 ); // Thou dost not look trustworthy... no gold for thee today!
|
||||
}
|
||||
else if ( m_From.CheckTargetSkill( SkillName.Begging, m_Target, 0.0, 100.0 ) )
|
||||
{
|
||||
int toConsume = theirPack.GetAmount( typeof( Gold ) ) / 10;
|
||||
int max = 10 + (m_From.Fame / 2500);
|
||||
|
||||
if ( max > 14 )
|
||||
max = 14;
|
||||
else if ( max < 10 )
|
||||
max = 10;
|
||||
|
||||
if ( toConsume > max )
|
||||
toConsume = max;
|
||||
|
||||
if ( toConsume > 0 )
|
||||
{
|
||||
int consumed = theirPack.ConsumeUpTo( typeof( Gold ), toConsume );
|
||||
|
||||
if ( consumed > 0 )
|
||||
{
|
||||
m_Target.PublicOverheadMessage( MessageType.Regular, m_Target.SpeechHue, 500405 ); // I feel sorry for thee...
|
||||
|
||||
Gold gold = new Gold( consumed );
|
||||
|
||||
m_From.AddToBackpack( gold );
|
||||
m_From.PlaySound( gold.GetDropSound() );
|
||||
|
||||
if ( m_From.Karma > -3000 )
|
||||
{
|
||||
int toLose = m_From.Karma + 3000;
|
||||
|
||||
if ( toLose > 40 )
|
||||
toLose = 40;
|
||||
|
||||
Titles.AwardKarma( m_From, -toLose, true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Target.PublicOverheadMessage( MessageType.Regular, m_Target.SpeechHue, 500407 ); // I have not enough money to give thee any!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Target.PublicOverheadMessage( MessageType.Regular, m_Target.SpeechHue, 500407 ); // I have not enough money to give thee any!
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Target.SendLocalizedMessage( 500404 ); // They seem unwilling to give you any money.
|
||||
}
|
||||
|
||||
m_From.NextSkillTime = DateTime.Now + TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Scripts/Skills/DetectHidden.cs
Normal file
116
Scripts/Skills/DetectHidden.cs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
using System;
|
||||
using Server.Multis;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Regions;
|
||||
using Server.Factions;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class DetectHidden
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.DetectHidden].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile src )
|
||||
{
|
||||
src.SendLocalizedMessage( 500819 );//Where will you search?
|
||||
src.Target = new InternalTarget();
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
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.DetectHidden].Value;
|
||||
int range = (int)(srcSkill / 10.0);
|
||||
|
||||
if ( !src.CheckSkill( SkillName.DetectHidden, 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 ) ) ) )
|
||||
{
|
||||
if ( trg is Mobiles.ShadowKnight && (trg.X != p.X || trg.Y != p.Y) )
|
||||
continue;
|
||||
|
||||
trg.RevealingAction();
|
||||
trg.SendLocalizedMessage( 500814 ); // You have been revealed!
|
||||
foundAnyone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inRange.Free();
|
||||
|
||||
if ( Faction.Find( src ) != null )
|
||||
{
|
||||
IPooledEnumerable itemsInRange = src.Map.GetItemsInRange( p, range );
|
||||
|
||||
foreach ( Item item in itemsInRange )
|
||||
{
|
||||
if ( item is BaseFactionTrap )
|
||||
{
|
||||
BaseFactionTrap trap = (BaseFactionTrap) item;
|
||||
|
||||
if ( src.CheckTargetSkill( SkillName.DetectHidden, trap, 80.0, 100.0 ) )
|
||||
{
|
||||
src.SendLocalizedMessage( 1042712, true, " " + (trap.Faction == null ? "" : trap.Faction.Definition.FriendlyName) ); // You reveal a trap placed by a faction:
|
||||
|
||||
trap.Visible = true;
|
||||
trap.BeginConceal();
|
||||
|
||||
foundAnyone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemsInRange.Free();
|
||||
}
|
||||
}
|
||||
|
||||
if ( !foundAnyone )
|
||||
{
|
||||
src.SendLocalizedMessage( 500817 ); // You can see nothing hidden there.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
239
Scripts/Skills/Discordance.cs
Normal file
239
Scripts/Skills/Discordance.cs
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
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 );
|
||||
}
|
||||
|
||||
private class DiscordanceInfo
|
||||
{
|
||||
public Mobile m_From;
|
||||
public Mobile m_Creature;
|
||||
public DateTime m_EndTime;
|
||||
public Timer m_Timer;
|
||||
public int m_Effect;
|
||||
public ArrayList m_Mods;
|
||||
|
||||
public DiscordanceInfo( Mobile from, Mobile creature, TimeSpan duration, int effect, ArrayList mods )
|
||||
{
|
||||
m_From = from;
|
||||
m_Creature = creature;
|
||||
m_EndTime = DateTime.Now + duration;
|
||||
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 ResistanceMod )
|
||||
m_Creature.AddResistanceMod( (ResistanceMod) mod );
|
||||
else 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 ResistanceMod )
|
||||
m_Creature.RemoveResistanceMod( (ResistanceMod) mod );
|
||||
else 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( object state )
|
||||
{
|
||||
DiscordanceInfo info = (DiscordanceInfo)state;
|
||||
Mobile from = info.m_From;
|
||||
Mobile targ = info.m_Creature;
|
||||
|
||||
if ( DateTime.Now >= info.m_EndTime || targ.Deleted || from.Map != targ.Map || targ.GetDistanceToSqrt( from ) > 16 )
|
||||
{
|
||||
if ( info.m_Timer != null )
|
||||
info.m_Timer.Stop();
|
||||
|
||||
info.Clear();
|
||||
m_Table.Remove( targ );
|
||||
}
|
||||
else
|
||||
{
|
||||
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.Harmful )
|
||||
{
|
||||
m_Instrument = inst;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object target )
|
||||
{
|
||||
from.RevealingAction();
|
||||
|
||||
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 ) )) )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049535 ); // A song of discord would have no effect on that.
|
||||
}
|
||||
else if ( !targ.Player )
|
||||
{
|
||||
TimeSpan len = TimeSpan.FromSeconds( from.Skills[SkillName.Discordance].Value * 2 );
|
||||
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 ) )
|
||||
{
|
||||
if ( !m_Table.Contains( targ ) )
|
||||
{
|
||||
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;
|
||||
|
||||
if ( Core.AOS )
|
||||
{
|
||||
double discord = from.Skills[SkillName.Discordance].Value;
|
||||
|
||||
if ( discord > 100.0 )
|
||||
effect = -20 + (int)((discord - 100.0) / -2.5);
|
||||
else
|
||||
effect = (int)(discord / -5.0);
|
||||
|
||||
if ( Core.SE && BaseInstrument.GetBaseDifficulty( targ ) >= 160.0 )
|
||||
effect /= 2;
|
||||
|
||||
scalar = effect * 0.01;
|
||||
|
||||
mods.Add( new ResistanceMod( ResistanceType.Physical, effect ) );
|
||||
mods.Add( new ResistanceMod( ResistanceType.Fire, effect ) );
|
||||
mods.Add( new ResistanceMod( ResistanceType.Cold, effect ) );
|
||||
mods.Add( new ResistanceMod( ResistanceType.Poison, effect ) );
|
||||
mods.Add( new ResistanceMod( ResistanceType.Energy, effect ) );
|
||||
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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, len, Math.Abs( effect ), mods );
|
||||
info.m_Timer = Timer.DelayCall( TimeSpan.Zero, TimeSpan.FromSeconds( 1.25 ), new TimerStateCallback( ProcessDiscordance ), info );
|
||||
|
||||
m_Table[targ] = info;
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1049537 );// Your target is already in discord.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1049540 );// You fail to disrupt your target
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
m_Instrument.ConsumeUse( from );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Instrument.PlayInstrumentBadly( from );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 1049535 ); // A song of discord would have no effect on that.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Scripts/Skills/EvalInt.cs
Normal file
89
Scripts/Skills/EvalInt.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Targeting;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class EvalInt
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[16].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.Target = new EvalInt.InternalTarget();
|
||||
|
||||
m.SendLocalizedMessage( 500906 ); // What do you wish to evaluate?
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base ( 8, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( from == targeted )
|
||||
{
|
||||
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500910 ); // Hmm, that person looks really silly.
|
||||
}
|
||||
else if ( targeted is TownCrier )
|
||||
{
|
||||
((TownCrier)targeted).PrivateOverheadMessage( MessageType.Regular, 0x3B2, 500907, from.NetState ); // He looks smart enough to remember the news. Ask him about it.
|
||||
}
|
||||
else if ( targeted is BaseVendor && ((BaseVendor)targeted).IsInvulnerable )
|
||||
{
|
||||
((BaseVendor)targeted).PrivateOverheadMessage( MessageType.Regular, 0x3B2, 500909, from.NetState ); // That person could probably calculate the cost of what you buy from them.
|
||||
}
|
||||
else if ( targeted is Mobile )
|
||||
{
|
||||
Mobile targ = (Mobile)targeted;
|
||||
|
||||
int marginOfError = Math.Max( 0, 20 - (int)(from.Skills[SkillName.EvalInt].Value / 5) );
|
||||
|
||||
int intel = targ.Int + Utility.RandomMinMax( -marginOfError, +marginOfError );
|
||||
int mana = ((targ.Mana * 100) / Math.Max( targ.ManaMax, 1 )) + Utility.RandomMinMax( -marginOfError, +marginOfError );
|
||||
|
||||
int intMod = intel / 10;
|
||||
int mnMod = mana / 10;
|
||||
|
||||
if ( intMod > 10 ) intMod = 10;
|
||||
else if ( intMod < 0 ) intMod = 0;
|
||||
|
||||
if ( mnMod > 10 ) mnMod = 10;
|
||||
else if ( mnMod < 0 ) mnMod = 0;
|
||||
|
||||
int body;
|
||||
|
||||
if ( targ.Body.IsHuman )
|
||||
body = targ.Female ? 11 : 0;
|
||||
else
|
||||
body = 22;
|
||||
|
||||
if ( from.CheckTargetSkill( SkillName.EvalInt, targ, 0.0, 120.0 ) )
|
||||
{
|
||||
targ.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1038169 + intMod + body, from.NetState ); // He/She/It looks [slighly less intelligent than a rock.] [Of Average intellect] [etc...]
|
||||
|
||||
if ( from.Skills[SkillName.EvalInt].Base >= 76.0 )
|
||||
targ.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1038202 + mnMod, from.NetState ); // That being is at [10,20,...] percent mental strength.
|
||||
}
|
||||
else
|
||||
{
|
||||
targ.PrivateOverheadMessage( MessageType.Regular, 0x3B2, 1038166 + (body / 11), from.NetState ); // You cannot judge his/her/its mental abilities.
|
||||
}
|
||||
}
|
||||
else if ( targeted is Item )
|
||||
{
|
||||
((Item)targeted).SendLocalizedMessageTo( from, 500908, "" ); // It looks smarter than a rock, but dumber than a piece of wood.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
Scripts/Skills/ForensicEval.cs
Normal file
92
Scripts/Skills/ForensicEval.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class ForensicEvaluation
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Forensics].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.Target = new ForensicTarget();
|
||||
m.RevealingAction();
|
||||
|
||||
m.SendLocalizedMessage( 500906 ); // What would you like to evaluate?
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
public class ForensicTarget : Target
|
||||
{
|
||||
public ForensicTarget() : base( 10, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object target )
|
||||
{
|
||||
if ( target is Mobile )
|
||||
{
|
||||
if ( from.CheckTargetSkill( SkillName.Forensics, target, 40.0, 100.0 ) )
|
||||
{
|
||||
if ( target is PlayerMobile && ((PlayerMobile)target).NpcGuild == NpcGuild.ThievesGuild )
|
||||
from.SendLocalizedMessage( 501004 );//That individual is a thief!
|
||||
else
|
||||
from.SendLocalizedMessage( 501003 );//You notice nothing unusual.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501001 );//You cannot determain anything useful.
|
||||
}
|
||||
}
|
||||
else if ( target is Corpse )
|
||||
{
|
||||
if ( from.CheckTargetSkill( SkillName.Forensics, target, 0.0, 100.0 ) )
|
||||
{
|
||||
Corpse c = (Corpse)target;
|
||||
|
||||
if ( ((Body)c.Amount).IsHuman )
|
||||
c.LabelTo( from, 1042751, ( c.Killer == null ? "no one" : c.Killer.Name ) );//This person was killed by ~1_KILLER_NAME~
|
||||
|
||||
if ( c.Looters.Count > 0 )
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i=0;i<c.Looters.Count;i++)
|
||||
{
|
||||
if ( i>0 )
|
||||
sb.Append( ", " );
|
||||
sb.Append( ((Mobile)c.Looters[i]).Name );
|
||||
}
|
||||
|
||||
c.LabelTo( from, 1042752, sb.ToString() );//This body has been distrubed by ~1_PLAYER_NAMES~
|
||||
}
|
||||
else
|
||||
{
|
||||
c.LabelTo( from, 501002 );//The corpse has not be desecrated.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501001 );//You cannot determain anything useful.
|
||||
}
|
||||
}
|
||||
else if ( target is ILockpickable )
|
||||
{
|
||||
ILockpickable p = (ILockpickable)target;
|
||||
if ( p.Picker != null )
|
||||
from.SendLocalizedMessage( 1042749, p.Picker.Name );//This lock was opened by ~1_PICKER_NAME~
|
||||
else
|
||||
from.SendLocalizedMessage( 501003 );//You notice nothing unusual.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
108
Scripts/Skills/Hiding.cs
Normal file
108
Scripts/Skills/Hiding.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
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[21].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
if ( m.Target != null || 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 ( !Core.AOS )
|
||||
{
|
||||
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.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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Scripts/Skills/Inscribe.cs
Normal file
162
Scripts/Skills/Inscribe.cs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Inscribe
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Inscribe].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
Target target = new InternalTargetSrc();
|
||||
m.Target = target;
|
||||
m.SendLocalizedMessage( 1046295 ); // Target the book you wish to copy.
|
||||
target.BeginTimeout( m, TimeSpan.FromMinutes( 1.0 ) );
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
private static Hashtable m_UseTable = new Hashtable();
|
||||
|
||||
private static void SetUser( BaseBook book, Mobile mob )
|
||||
{
|
||||
m_UseTable[book] = mob;
|
||||
}
|
||||
|
||||
private static void CancelUser( BaseBook book )
|
||||
{
|
||||
m_UseTable.Remove( book );
|
||||
}
|
||||
|
||||
public static Mobile GetUser( BaseBook book )
|
||||
{
|
||||
return (Mobile)m_UseTable[book];
|
||||
}
|
||||
|
||||
public static bool IsEmpty( BaseBook book )
|
||||
{
|
||||
foreach ( BookPageInfo page in book.Pages )
|
||||
{
|
||||
foreach ( string line in page.Lines )
|
||||
{
|
||||
if ( line.Trim() != "" )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Copy( BaseBook bookSrc, BaseBook bookDst )
|
||||
{
|
||||
bookDst.Title = bookSrc.Title;
|
||||
bookDst.Author = bookSrc.Author;
|
||||
|
||||
BookPageInfo[] pagesSrc = bookSrc.Pages;
|
||||
BookPageInfo[] pagesDst = bookDst.Pages;
|
||||
for ( int i = 0; i < pagesSrc.Length && i < pagesDst.Length; i++ )
|
||||
{
|
||||
BookPageInfo pageSrc = pagesSrc[i];
|
||||
BookPageInfo pageDst = pagesDst[i];
|
||||
|
||||
int length = pageSrc.Lines.Length;
|
||||
pageDst.Lines = new string[length];
|
||||
|
||||
for ( int j = 0; j < length; j++ )
|
||||
pageDst.Lines[j] = pageSrc.Lines[j];
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTargetSrc : Target
|
||||
{
|
||||
public InternalTargetSrc() : base ( 3, false, TargetFlags.None )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
BaseBook book = targeted as BaseBook;
|
||||
if ( book == null )
|
||||
from.SendLocalizedMessage( 1046296 ); // That is not a book
|
||||
else if ( Inscribe.IsEmpty( book ) )
|
||||
from.SendLocalizedMessage( 501611 ); // Can't copy an empty book.
|
||||
else if ( Inscribe.GetUser( book ) != null )
|
||||
from.SendLocalizedMessage( 501621 ); // Someone else is inscribing that item.
|
||||
else
|
||||
{
|
||||
Target target = new InternalTargetDst( book );
|
||||
from.Target = target;
|
||||
from.SendLocalizedMessage( 501612 ); // Select a book to copy this to.
|
||||
target.BeginTimeout( from, TimeSpan.FromMinutes( 1.0 ) );
|
||||
Inscribe.SetUser( book, from );
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetCancel( Mobile from, TargetCancelType cancelType )
|
||||
{
|
||||
if ( cancelType == TargetCancelType.Timeout )
|
||||
from.SendLocalizedMessage( 501619 ); // You have waited too long to make your inscribe selection, your inscription attempt has timed out.
|
||||
}
|
||||
}
|
||||
|
||||
private class InternalTargetDst : Target
|
||||
{
|
||||
private BaseBook m_BookSrc;
|
||||
|
||||
public InternalTargetDst( BaseBook bookSrc ) : base ( 3, false, TargetFlags.None )
|
||||
{
|
||||
m_BookSrc = bookSrc;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( m_BookSrc.Deleted )
|
||||
return;
|
||||
|
||||
BaseBook bookDst = targeted as BaseBook;
|
||||
|
||||
if ( bookDst == null )
|
||||
from.SendLocalizedMessage( 1046296 ); // That is not a book
|
||||
else if ( Inscribe.IsEmpty( m_BookSrc ) )
|
||||
from.SendLocalizedMessage( 501611 ); // Can't copy an empty book.
|
||||
else if ( bookDst == m_BookSrc )
|
||||
from.SendLocalizedMessage( 501616 ); // Cannot copy a book onto itself.
|
||||
else if ( !bookDst.Writable )
|
||||
from.SendLocalizedMessage( 501614 ); // Cannot write into that book.
|
||||
else if ( Inscribe.GetUser( bookDst ) != null )
|
||||
from.SendLocalizedMessage( 501621 ); // Someone else is inscribing that item.
|
||||
else
|
||||
{
|
||||
if ( from.CheckTargetSkill( SkillName.Inscribe, bookDst, 0, 50 ) )
|
||||
{
|
||||
Inscribe.Copy( m_BookSrc, bookDst );
|
||||
|
||||
from.SendLocalizedMessage( 501618 ); // You make a copy of the book.
|
||||
from.PlaySound( 0x249 );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 501617 ); // You fail to make a copy of the book.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetCancel( Mobile from, TargetCancelType cancelType )
|
||||
{
|
||||
if ( cancelType == TargetCancelType.Timeout )
|
||||
from.SendLocalizedMessage( 501619 ); // You have waited too long to make your inscribe selection, your inscription attempt has timed out.
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish( Mobile from )
|
||||
{
|
||||
Inscribe.CancelUser( m_BookSrc );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
61
Scripts/Skills/ItemIdentification.cs
Normal file
61
Scripts/Skills/ItemIdentification.cs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Targeting;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.Items
|
||||
{
|
||||
public class ItemIdentification
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.ItemID].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile from )
|
||||
{
|
||||
from.SendLocalizedMessage( 500343 ); // What do you wish to appraise and identify?
|
||||
from.Target = new InternalTarget();
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
[PlayerVendorTarget]
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base ( 8, false, TargetFlags.None )
|
||||
{
|
||||
AllowNonlocal = true;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object o )
|
||||
{
|
||||
if ( o is Item )
|
||||
{
|
||||
if ( from.CheckTargetSkill( SkillName.ItemID, o, 0, 100 ) )
|
||||
{
|
||||
if ( o is BaseWeapon )
|
||||
((BaseWeapon)o).Identified = true;
|
||||
else if ( o is BaseArmor )
|
||||
((BaseArmor)o).Identified = true;
|
||||
|
||||
if ( !Core.AOS )
|
||||
((Item)o).OnSingleClick( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500353 ); // You are not certain...
|
||||
}
|
||||
}
|
||||
else if ( o is Mobile )
|
||||
{
|
||||
((Mobile)o).OnSingleClick( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500353 ); // You are not certain...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
Scripts/Skills/Meditation.cs
Normal file
101
Scripts/Skills/Meditation.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
class Meditation
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[46].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static bool CheckOkayHolding( Item item )
|
||||
{
|
||||
if ( item == null )
|
||||
return true;
|
||||
|
||||
if ( item is Spellbook || item is Runebook )
|
||||
return true;
|
||||
|
||||
if ( Core.AOS && item is BaseWeapon && ((BaseWeapon)item).Attributes.SpellChanneling != 0 )
|
||||
return true;
|
||||
|
||||
if ( Core.AOS && item is BaseArmor && ((BaseArmor)item).Attributes.SpellChanneling != 0 )
|
||||
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 ( !Core.AOS && m.Hits < (m.HitsMax / 10) ) // Less than 10% health
|
||||
{
|
||||
m.SendLocalizedMessage( 501849 ); // The mind is strong but the body is weak.
|
||||
|
||||
return TimeSpan.FromSeconds( 5.0 );
|
||||
}
|
||||
else if ( m.Mana >= m.ManaMax )
|
||||
{
|
||||
m.SendLocalizedMessage( 501846 ); // You are at peace.
|
||||
|
||||
return TimeSpan.FromSeconds( Core.AOS ? 10.0 : 5.0 );
|
||||
}
|
||||
else if ( Core.AOS && Server.Misc.RegenRates.GetArmorOffset( m ) > 0 )
|
||||
{
|
||||
m.SendLocalizedMessage( 500135 ); // Regenative forces cannot penetrate your armor!
|
||||
|
||||
return TimeSpan.FromSeconds( 10.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
Item oneHanded = m.FindItemOnLayer( Layer.OneHanded );
|
||||
Item twoHanded = m.FindItemOnLayer( Layer.TwoHanded );
|
||||
|
||||
if ( Core.AOS )
|
||||
{
|
||||
if ( !CheckOkayHolding( oneHanded ) )
|
||||
m.AddToBackpack( oneHanded );
|
||||
|
||||
if ( !CheckOkayHolding( twoHanded ) )
|
||||
m.AddToBackpack( twoHanded );
|
||||
}
|
||||
else 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;
|
||||
BuffInfo.AddBuff( m, new BuffInfo( BuffIcon.ActiveMeditation, 1075657 ) );
|
||||
|
||||
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 == 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
171
Scripts/Skills/Poisoning.cs
Normal file
171
Scripts/Skills/Poisoning.cs
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
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 || targeted is FukiyaDarts || targeted is Shuriken )
|
||||
{
|
||||
startTimer = true;
|
||||
}
|
||||
else if ( targeted is BaseWeapon )
|
||||
{
|
||||
BaseWeapon weapon = (BaseWeapon)targeted;
|
||||
|
||||
if ( Core.AOS )
|
||||
{
|
||||
startTimer = ( weapon.PrimaryAbility == WeaponAbility.InfectiousStrike || weapon.SecondaryAbility == WeaponAbility.InfectiousStrike );
|
||||
}
|
||||
else 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
|
||||
{
|
||||
if ( Core.AOS )
|
||||
from.SendLocalizedMessage( 1060204 ); // You cannot poison that! You can only poison infectious weapons, food or drink.
|
||||
else
|
||||
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);
|
||||
}
|
||||
else if ( m_Target is FukiyaDarts )
|
||||
{
|
||||
((FukiyaDarts)m_Target).Poison = m_Poison;
|
||||
((FukiyaDarts)m_Target).PoisonCharges = Math.Min( 18 - (m_Poison.Level * 2), ((FukiyaDarts)m_Target).UsesRemaining );
|
||||
}
|
||||
else if ( m_Target is Shuriken )
|
||||
{
|
||||
((Shuriken)m_Target).Poison = m_Poison;
|
||||
((Shuriken)m_Target).PoisonCharges = Math.Min( 18 - (m_Poison.Level * 2), ((Shuriken)m_Target).UsesRemaining );
|
||||
}
|
||||
|
||||
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 if ( creature.IsParagon && BaseInstrument.GetBaseDifficulty( creature ) >= 160.0 )
|
||||
{
|
||||
from.SendLocalizedMessage( 1049446 ); // You have no chance of provoking those creatures.
|
||||
}
|
||||
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 || 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!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
127
Scripts/Skills/RemoveTrap.cs
Normal file
127
Scripts/Skills/RemoveTrap.cs
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Factions;
|
||||
|
||||
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 )
|
||||
{
|
||||
if ( m.Skills[SkillName.Lockpicking].Value < 50 )
|
||||
{
|
||||
m.SendLocalizedMessage( 502366 ); // You do not know enough about locks. Become better at picking locks.
|
||||
}
|
||||
else if ( m.Skills[SkillName.DetectHidden].Value < 50 )
|
||||
{
|
||||
m.SendLocalizedMessage( 502367 ); // You are not perceptive enough. Become better at detect hidden.
|
||||
}
|
||||
else
|
||||
{
|
||||
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 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 BaseFactionTrap )
|
||||
{
|
||||
BaseFactionTrap trap = (BaseFactionTrap) targeted;
|
||||
Faction faction = Faction.Find( from );
|
||||
|
||||
FactionTrapRemovalKit kit = ( from.Backpack == null ? null : from.Backpack.FindItemByType( typeof( FactionTrapRemovalKit ) ) as FactionTrapRemovalKit );
|
||||
|
||||
bool isOwner = ( trap.Placer == from || ( trap.Faction != null && trap.Faction.IsCommander( from ) ) );
|
||||
|
||||
if ( faction == null )
|
||||
{
|
||||
from.SendLocalizedMessage( 1010538 ); // You may not disarm faction traps unless you are in an opposing faction
|
||||
}
|
||||
else if ( faction == trap.Faction && trap.Faction != null && !isOwner )
|
||||
{
|
||||
from.SendLocalizedMessage( 1010537 ); // You may not disarm traps set by your own faction!
|
||||
}
|
||||
else if ( !isOwner && kit == null )
|
||||
{
|
||||
from.SendLocalizedMessage( 1042530 ); // You must have a trap removal kit at the base level of your pack to disarm a faction trap.
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( from.CheckTargetSkill( SkillName.RemoveTrap, trap, 80.0, 100.0 ) && from.CheckTargetSkill( SkillName.Tinkering, trap, 80.0, 100.0 ) )
|
||||
{
|
||||
from.PrivateOverheadMessage( MessageType.Regular, trap.MessageHue, trap.DisarmMessage, from.NetState );
|
||||
|
||||
if ( !isOwner )
|
||||
{
|
||||
int silver = faction.AwardSilver( from, trap.SilverFromDisarm );
|
||||
|
||||
if ( silver > 0 )
|
||||
from.SendLocalizedMessage( 1008113, true, silver.ToString( "N0" ) ); // You have been granted faction silver for removing the enemy trap :
|
||||
}
|
||||
|
||||
trap.Delete();
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 502372 ); // You fail to disarm the trap... but you don't set it off
|
||||
}
|
||||
|
||||
if ( !isOwner && kit != null )
|
||||
kit.ConsumeCharge( from );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 502373 ); // That does'nt appear to be trapped
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
Scripts/Skills/Snooping.cs
Normal file
103
Scripts/Skills/Snooping.cs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Misc;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
using Server.Network;
|
||||
using Server.Regions;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
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; // felucca you can snoop anybody
|
||||
|
||||
GuardedRegion reg = (GuardedRegion) to.Region.GetRegion( typeof( GuardedRegion ) );
|
||||
|
||||
if ( reg == null || reg.IsDisabled() )
|
||||
return true; // not in town? we can snoop any npc
|
||||
|
||||
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.Snooping].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 != from.NetState )
|
||||
ns.Mobile.SendMessage( message );
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
}
|
||||
|
||||
if ( from.AccessLevel == AccessLevel.Player )
|
||||
Titles.AwardKarma( from, -4, true );
|
||||
|
||||
if ( from.AccessLevel > AccessLevel.Player || from.CheckTargetSkill( SkillName.Snooping, cont, 0.0, 100.0 ) )
|
||||
{
|
||||
if ( cont is TrapableContainer && ((TrapableContainer)cont).ExecuteTrap( from ) )
|
||||
return;
|
||||
|
||||
cont.DisplayTo( from );
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500210 ); // You failed to peek into the container.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage( 500446 ); // That is too far away.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
203
Scripts/Skills/SpiritSpeak.cs
Normal file
203
Scripts/Skills/SpiritSpeak.cs
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
using System;
|
||||
using Server;
|
||||
using Server.Items;
|
||||
using Server.Spells;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
class SpiritSpeak
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[32].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
if ( Core.AOS )
|
||||
{
|
||||
Spell spell = new SpiritSpeakSpell( m );
|
||||
|
||||
spell.Cast();
|
||||
|
||||
if ( spell.IsCasting )
|
||||
return TimeSpan.FromSeconds( 5.0 );
|
||||
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
|
||||
m.RevealingAction();
|
||||
|
||||
if ( m.CheckSkill( SkillName.SpiritSpeak, 0, 100 ) )
|
||||
{
|
||||
if ( !m.CanHearGhosts )
|
||||
{
|
||||
Timer t = new SpiritSpeakTimer( m );
|
||||
double secs = m.Skills[SkillName.SpiritSpeak].Base / 50;
|
||||
secs *= 90;
|
||||
if ( secs < 15 )
|
||||
secs = 15;
|
||||
|
||||
t.Delay = TimeSpan.FromSeconds( secs );//15seconds to 3 minutes
|
||||
t.Start();
|
||||
m.CanHearGhosts = true;
|
||||
}
|
||||
|
||||
m.PlaySound( 0x24A );
|
||||
m.SendLocalizedMessage( 502444 );//You contact the neitherworld.
|
||||
}
|
||||
else
|
||||
{
|
||||
m.SendLocalizedMessage( 502443 );//You fail to contact the neitherworld.
|
||||
m.CanHearGhosts = false;
|
||||
}
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
private class SpiritSpeakTimer : Timer
|
||||
{
|
||||
private Mobile m_Owner;
|
||||
public SpiritSpeakTimer( Mobile m ) : base( TimeSpan.FromMinutes( 2.0 ) )
|
||||
{
|
||||
m_Owner = m;
|
||||
Priority = TimerPriority.FiveSeconds;
|
||||
}
|
||||
|
||||
protected override void OnTick()
|
||||
{
|
||||
m_Owner.CanHearGhosts = false;
|
||||
m_Owner.SendLocalizedMessage( 502445 );//You feel your contact with the neitherworld fading.
|
||||
}
|
||||
}
|
||||
|
||||
private class SpiritSpeakSpell : Spell
|
||||
{
|
||||
private static SpellInfo m_Info = new SpellInfo( "Spirit Speak", "", SpellCircle.Second, 269 );
|
||||
|
||||
public override bool BlockedByHorrificBeast{ get{ return false; } }
|
||||
|
||||
public SpiritSpeakSpell( Mobile caster ) : base( caster, null, m_Info )
|
||||
{
|
||||
}
|
||||
|
||||
public override bool ClearHandsOnCast{ get{ return false; } }
|
||||
|
||||
public override TimeSpan GetCastDelay()
|
||||
{
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
public override int GetMana()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override void OnCasterHurt()
|
||||
{
|
||||
if ( IsCasting )
|
||||
Disturb( DisturbType.Hurt, false, true );
|
||||
}
|
||||
|
||||
public override bool ConsumeReagents()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckFizzle()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CheckNextSpellTime{ get{ return false; } }
|
||||
|
||||
public override void OnDisturb( DisturbType type, bool message )
|
||||
{
|
||||
Caster.NextSkillTime = DateTime.Now;
|
||||
|
||||
base.OnDisturb( type, message );
|
||||
}
|
||||
|
||||
public override bool CheckDisturb( DisturbType type, bool checkFirst, bool resistable )
|
||||
{
|
||||
if ( type == DisturbType.EquipRequest || type == DisturbType.UseRequest )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SayMantra()
|
||||
{
|
||||
// Anh Mi Sah Ko
|
||||
Caster.PublicOverheadMessage( MessageType.Regular, 0x3B2, 1062074, "", false );
|
||||
Caster.PlaySound( 0x24A );
|
||||
}
|
||||
|
||||
public override void OnCast()
|
||||
{
|
||||
Corpse toChannel = null;
|
||||
|
||||
foreach ( Item item in Caster.GetItemsInRange( 3 ) )
|
||||
{
|
||||
if ( item is Corpse && !((Corpse)item).Channeled )
|
||||
{
|
||||
toChannel = (Corpse)item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int max, min, mana, number;
|
||||
|
||||
if ( toChannel != null )
|
||||
{
|
||||
min = 1 + (int)(Caster.Skills[SkillName.SpiritSpeak].Value * 0.25);
|
||||
max = min + 4;
|
||||
mana = 0;
|
||||
number = 1061287; // You channel energy from a nearby corpse to heal your wounds.
|
||||
}
|
||||
else
|
||||
{
|
||||
min = 1 + (int)(Caster.Skills[SkillName.SpiritSpeak].Value * 0.25);
|
||||
max = min + 4;
|
||||
mana = 10;
|
||||
number = 1061286; // You channel your own spiritual energy to heal your wounds.
|
||||
}
|
||||
|
||||
if ( Caster.Mana < mana )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 1061285 ); // You lack the mana required to use this skill.
|
||||
}
|
||||
else
|
||||
{
|
||||
Caster.CheckSkill( SkillName.SpiritSpeak, 0.0, 120.0 );
|
||||
|
||||
if ( Utility.RandomDouble() > (Caster.Skills[SkillName.SpiritSpeak].Value / 100.0) )
|
||||
{
|
||||
Caster.SendLocalizedMessage( 502443 ); // You fail your attempt at contacting the netherworld.
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( toChannel != null )
|
||||
{
|
||||
toChannel.Channeled = true;
|
||||
toChannel.Hue = 0x835;
|
||||
}
|
||||
|
||||
Caster.Mana -= mana;
|
||||
Caster.SendLocalizedMessage( number );
|
||||
|
||||
if ( min > max )
|
||||
min = max;
|
||||
|
||||
Caster.Hits += Utility.RandomMinMax( min, max );
|
||||
|
||||
Caster.FixedParticles( 0x375A, 1, 15, 9501, 2100, 4, EffectLayer.Waist );
|
||||
}
|
||||
}
|
||||
|
||||
FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
478
Scripts/Skills/Stealing.cs
Normal file
478
Scripts/Skills/Stealing.cs
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Mobiles;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Factions;
|
||||
using Server.Spells.Seventh;
|
||||
using Server.Spells.Fifth;
|
||||
using Server.Spells.Necromancy;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Stealing
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[33].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static readonly bool ClassicMode = false;
|
||||
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;
|
||||
|
||||
StealableArtifactsSpawner.StealableInstance si = null;
|
||||
if ( toSteal.Parent == null || !toSteal.Movable )
|
||||
si = StealableArtifactsSpawner.GetStealableInstance( toSteal );
|
||||
|
||||
if ( !IsEmptyHanded( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005584 ); // Both hands must be free to steal.
|
||||
}
|
||||
else if ( root is Mobile && ((Mobile)root).Player && IsInnocentTo( m_Thief, (Mobile)root ) && !IsInGuild( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005596 ); // You must be in the thieves guild to steal from other players.
|
||||
}
|
||||
else if ( SuspendOnMurder && root is Mobile && ((Mobile)root).Player && IsInGuild( m_Thief ) && m_Thief.Kills > 0 )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502706 ); // You are currently suspended from the thieves guild.
|
||||
}
|
||||
else if ( root is BaseVendor && ((BaseVendor)root).IsInvulnerable )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005598 ); // You can't steal from shopkeepers.
|
||||
}
|
||||
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.
|
||||
}
|
||||
#region Sigils
|
||||
else if ( toSteal is Sigil )
|
||||
{
|
||||
PlayerState pl = PlayerState.Find( m_Thief );
|
||||
Faction faction = ( pl == null ? null : pl.Faction );
|
||||
|
||||
Sigil sig = (Sigil) toSteal;
|
||||
|
||||
if ( !m_Thief.InRange( toSteal.GetWorldLocation(), 1 ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502703 ); // You must be standing next to an item to steal it.
|
||||
}
|
||||
else if ( root != null ) // not on the ground
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
else if ( faction != null )
|
||||
{
|
||||
if ( !m_Thief.CanBeginAction( typeof( IncognitoSpell ) ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1010581 ); // You cannot steal the sigil when you are incognito
|
||||
}
|
||||
else if ( DisguiseGump.IsDisguised( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1010583 ); // You cannot steal the sigil while disguised
|
||||
}
|
||||
else if ( !m_Thief.CanBeginAction( typeof( PolymorphSpell ) ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1010582 ); // You cannot steal the sigil while polymorphed
|
||||
}
|
||||
else if ( TransformationSpell.UnderTransformation( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1061622 ); // You cannot steal the sigil while in that form.
|
||||
}
|
||||
else if ( Spells.Ninjitsu.AnimalForm.UnderTransformation( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1063222 ); // You cannot steal the sigil while mimicking an animal.
|
||||
}
|
||||
else if ( pl.IsLeaving )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005589 ); // You are currently quitting a faction and cannot steal the town sigil
|
||||
}
|
||||
else if ( sig.IsBeingCorrupted && sig.LastMonolith.Faction == faction )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005590 ); // You cannot steal your own sigil
|
||||
}
|
||||
else if ( sig.IsPurifying )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005592 ); // You cannot steal this sigil until it has been purified
|
||||
}
|
||||
else if ( m_Thief.CheckTargetSkill( SkillName.Stealing, toSteal, 80.0, 80.0 ) )
|
||||
{
|
||||
if ( Sigil.ExistsOn( m_Thief ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1010258 ); // The sigil has gone back to its home location because you already have a sigil.
|
||||
}
|
||||
else if ( m_Thief.Backpack == null || !m_Thief.Backpack.CheckHold( m_Thief, sig, false, true ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1010259 ); // The sigil has gone home because your backpack is full
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sig.IsBeingCorrupted )
|
||||
sig.GraceStart = DateTime.Now; // begin grace period
|
||||
|
||||
m_Thief.SendLocalizedMessage( 1010586 ); // YOU STOLE THE SIGIL!!! (woah, calm down now)
|
||||
|
||||
if ( sig.LastMonolith != null )
|
||||
sig.LastMonolith.Sigil = null;
|
||||
|
||||
sig.LastStolen = DateTime.Now;
|
||||
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005594 ); // You do not have enough skill to steal the sigil
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1005588 ); // You must join a faction to do that
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
else if ( si == null && ( toSteal.Parent == null || !toSteal.Movable ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
else if ( toSteal.LootType == LootType.Newbied || toSteal.CheckBlessed( root ) )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 502710 ); // You can't steal that!
|
||||
}
|
||||
else if ( Core.AOS && si == null && toSteal is Container )
|
||||
{
|
||||
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 ( si != null && m_Thief.Skills[SkillName.Stealing].Value < 100.0 )
|
||||
{
|
||||
m_Thief.SendLocalizedMessage( 1060025, "", 0x66D ); // You're not skilled enough to attempt the theft of this item.
|
||||
}
|
||||
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.
|
||||
|
||||
if ( si != null )
|
||||
{
|
||||
toSteal.Movable = true;
|
||||
si.Item = null;
|
||||
}
|
||||
}
|
||||
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 != m_Thief.NetState )
|
||||
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 ( 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
91
Scripts/Skills/Stealth.cs
Normal file
91
Scripts/Skills/Stealth.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class Stealth
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.Stealth].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static int[,] ArmorTable{ get { return m_ArmorTable; } }
|
||||
private static int[,] m_ArmorTable = new int[,]
|
||||
{
|
||||
// Gorget Gloves Helmet Arms Legs Chest Shield
|
||||
/* Cloth */ { 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* Leather */ { 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* Studded */ { 2, 2, 0, 4, 6, 10, 0 },
|
||||
/* Bone */ { 0, 5, 10, 10, 15, 25, 0 },
|
||||
/* Spined */ { 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* Horned */ { 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* Barbed */ { 0, 0, 0, 0, 0, 0, 0 },
|
||||
/* Ring */ { 0, 5, 0, 10, 15, 25, 0 },
|
||||
/* Chain */ { 0, 0, 10, 0, 15, 25, 0 },
|
||||
/* Plate */ { 5, 5, 10, 10, 15, 25, 0 },
|
||||
/* Dragon */ { 0, 5, 10, 10, 15, 25, 0 }
|
||||
};
|
||||
|
||||
public static int GetArmorRating( Mobile m )
|
||||
{
|
||||
if( !Core.AOS )
|
||||
return (int)m.ArmorRating;
|
||||
|
||||
int ar = 0;
|
||||
|
||||
for( int i = 0; i < m.Items.Count; i++ )
|
||||
{
|
||||
BaseArmor armor = m.Items[i] as BaseArmor;
|
||||
|
||||
if( armor != null && armor.ArmorAttributes.MageArmor == 0 )
|
||||
ar += m_ArmorTable[(int)armor.MaterialType, (int)armor.BodyPosition];
|
||||
}
|
||||
|
||||
return ar;
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
if ( !m.Hidden )
|
||||
{
|
||||
m.SendLocalizedMessage( 502725 ); // You must hide first
|
||||
}
|
||||
else if ( m.Skills[SkillName.Hiding].Base < ((Core.SE) ? 50.0 : 80.0) )
|
||||
{
|
||||
m.SendLocalizedMessage( 502726 ); // You are not hidden well enough. Become better at hiding.
|
||||
m.RevealingAction();
|
||||
}
|
||||
else
|
||||
{
|
||||
int armorRating = GetArmorRating( m );
|
||||
|
||||
if ( armorRating >= (Core.AOS ? 42 : 26) ) //I have a hunch '42' was chosen cause someone's a fan of DNA
|
||||
{
|
||||
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), (Core.AOS ? 60.0 : 80.0) + (armorRating * 2) ) )
|
||||
{
|
||||
int steps = (int)(m.Skills[SkillName.Stealth].Value / (Core.AOS ? 5.0 : 10.0));
|
||||
|
||||
if ( steps < 1 )
|
||||
steps = 1;
|
||||
|
||||
m.AllowedStealthSteps = steps;
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
95
Scripts/Skills/TasteID.cs
Normal file
95
Scripts/Skills/TasteID.cs
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using Server.Targeting;
|
||||
using Server.Items;
|
||||
using Server.Network;
|
||||
using Server.Mobiles;
|
||||
|
||||
namespace Server.SkillHandlers
|
||||
{
|
||||
public class TasteID
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
SkillInfo.Table[(int)SkillName.TasteID].Callback = new SkillUseCallback( OnUse );
|
||||
}
|
||||
|
||||
public static TimeSpan OnUse( Mobile m )
|
||||
{
|
||||
m.Target = new InternalTarget();
|
||||
|
||||
m.SendLocalizedMessage( 502807 ); // What would you like to taste?
|
||||
|
||||
return TimeSpan.FromSeconds( 1.0 );
|
||||
}
|
||||
|
||||
[PlayerVendorTarget]
|
||||
private class InternalTarget : Target
|
||||
{
|
||||
public InternalTarget() : base ( 2, false, TargetFlags.None )
|
||||
{
|
||||
AllowNonlocal = true;
|
||||
}
|
||||
|
||||
protected override void OnTarget( Mobile from, object targeted )
|
||||
{
|
||||
if ( targeted is Mobile )
|
||||
{
|
||||
from.SendLocalizedMessage( 502816 ); // You feel that such an action would be inappropriate.
|
||||
}
|
||||
else if ( targeted is Food )
|
||||
{
|
||||
Food food = (Food) targeted;
|
||||
|
||||
if ( from.CheckTargetSkill( SkillName.TasteID, food, 0, 100 ) )
|
||||
{
|
||||
if ( food.Poison != null )
|
||||
{
|
||||
food.SendLocalizedMessageTo( from, 1038284 ); // It appears to have poison smeared on it.
|
||||
}
|
||||
else
|
||||
{
|
||||
// No poison on the food
|
||||
food.SendLocalizedMessageTo( from, 1010600 ); // You detect nothing unusual about this substance.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skill check failed
|
||||
food.SendLocalizedMessageTo( from, 502823 ); // You cannot discern anything about this substance.
|
||||
}
|
||||
}
|
||||
else if ( targeted is BasePotion )
|
||||
{
|
||||
BasePotion potion = (BasePotion) targeted;
|
||||
|
||||
potion.SendLocalizedMessageTo( from, 502813 ); // You already know what kind of potion that is.
|
||||
potion.SendLocalizedMessageTo( from, potion.LabelNumber );
|
||||
}
|
||||
else if ( targeted is PotionKeg )
|
||||
{
|
||||
PotionKeg keg = (PotionKeg) targeted;
|
||||
|
||||
if ( keg.Held <= 0 )
|
||||
{
|
||||
keg.SendLocalizedMessageTo( from, 502228 ); // There is nothing in the keg to taste!
|
||||
}
|
||||
else
|
||||
{
|
||||
keg.SendLocalizedMessageTo( from, 502229 ); // You are already familiar with this keg's contents.
|
||||
keg.SendLocalizedMessageTo( from, keg.LabelNumber );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The target is not food or potion or potion keg.
|
||||
from.SendLocalizedMessage( 502820 ); // That's not something you can taste.
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnTargetOutOfRange( Mobile from, object targeted )
|
||||
{
|
||||
from.SendLocalizedMessage( 502815 ); // You are too far away to taste that.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
397
Scripts/Skills/Tracking.cs
Normal file
397
Scripts/Skills/Tracking.cs
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using Server;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Server.Spells.Necromancy;
|
||||
|
||||
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 Hashtable m_Table = new Hashtable();
|
||||
|
||||
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 )
|
||||
{
|
||||
// Note: This is not reset as of publish 35.
|
||||
|
||||
TrackingInfo info = m_Table[tracker] as TrackingInfo;
|
||||
|
||||
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;
|
||||
|
||||
return Math.Sqrt( (xDelta * xDelta) + (yDelta * yDelta) );
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
private Mobile m_From;
|
||||
|
||||
public InternalSorter( Mobile from )
|
||||
{
|
||||
m_From = from;
|
||||
}
|
||||
|
||||
public int Compare( object x, object y )
|
||||
{
|
||||
if ( x == null && y == null )
|
||||
return 0;
|
||||
else if ( x == null )
|
||||
return -1;
|
||||
else if ( y == null )
|
||||
return 1;
|
||||
|
||||
Mobile a = x as Mobile;
|
||||
Mobile b = y as Mobile;
|
||||
|
||||
if ( a == null || b == null )
|
||||
throw new ArgumentException();
|
||||
|
||||
return m_From.GetDistanceToSqrt( a ).CompareTo( m_From.GetDistanceToSqrt( b ) );
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ArrayList list = new ArrayList();
|
||||
|
||||
foreach ( Mobile m in from.GetMobilesInRange( range ) )
|
||||
{
|
||||
// Ghosts can no longer be tracked
|
||||
if ( m != from && (!Core.AOS || m.Alive) && (!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 )
|
||||
{
|
||||
if ( !Core.AOS || !m.Player )
|
||||
return true;
|
||||
|
||||
int tracking = from.Skills[SkillName.Tracking].Fixed;
|
||||
int detectHidden = from.Skills[SkillName.DetectHidden].Fixed;
|
||||
|
||||
int hiding = m.Skills[SkillName.Hiding].Fixed;
|
||||
int stealth = m.Skills[SkillName.Stealth].Fixed;
|
||||
int divisor = hiding + stealth;
|
||||
|
||||
// Necromancy forms affect tracking difficulty
|
||||
if ( TransformationSpell.UnderTransformation( m, typeof( HorrificBeastSpell ) ) )
|
||||
divisor -= 200;
|
||||
else if ( TransformationSpell.UnderTransformation( m, typeof( VampiricEmbraceSpell ) ) && divisor < 500 )
|
||||
divisor = 500;
|
||||
else if ( TransformationSpell.UnderTransformation( m, typeof( WraithFormSpell ) ) && divisor <= 2000 )
|
||||
divisor += 200;
|
||||
|
||||
int chance;
|
||||
if ( divisor > 0 )
|
||||
{
|
||||
if ( Core.SE )
|
||||
chance = 50 * (tracking * 2 + detectHidden) / divisor;
|
||||
else
|
||||
chance = 50 * (tracking + detectHidden + 10 * Utility.RandomMinMax( 1, 20 )) / divisor;
|
||||
}
|
||||
else
|
||||
chance = 100;
|
||||
|
||||
return chance > Utility.Random( 100 );
|
||||
}
|
||||
|
||||
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 ArrayList m_List;
|
||||
|
||||
private TrackWhoGump( Mobile from, ArrayList 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 = (Mobile)list[i];
|
||||
|
||||
AddItem( 20 + ((i % 4) * 100), 20 + ((i / 4) * 155), ShrinkTable.Lookup( m ) );
|
||||
AddButton( 20 + ((i % 4) * 100), 130 + ((i / 4) * 155), 4005, 4007, i + 1, GumpButtonType.Reply, 0 );
|
||||
|
||||
if ( m.Name != null )
|
||||
AddHtml( 20 + ((i % 4) * 100), 90 + ((i / 4) * 155), 90, 40, m.Name, false, false );
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnResponse( NetState state, RelayInfo info )
|
||||
{
|
||||
int index = info.ButtonID - 1;
|
||||
|
||||
if ( index >= 0 && index < m_List.Count && index < 12 )
|
||||
{
|
||||
Mobile m = (Mobile)m_List[index];
|
||||
|
||||
m_From.QuestArrow = new TrackArrow( m_From, m, m_Range * 2 );
|
||||
|
||||
if ( Core.SE )
|
||||
Tracking.AddInfo( m_From, m );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TrackArrow : QuestArrow
|
||||
{
|
||||
private Mobile m_From;
|
||||
private Timer m_Timer;
|
||||
|
||||
public TrackArrow( Mobile from, Mobile target, int range ) : base( from )
|
||||
{
|
||||
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_From.Send( new CancelArrow() );
|
||||
m_From.SendLocalizedMessage( 503177 ); // You have lost your quarry.
|
||||
|
||||
Tracking.ClearTrackingInfo( m_From );
|
||||
|
||||
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( m_LastX, m_LastY );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue