Infernal
Member
Hi Guys, I Apologize for my bad english and for my bad Code XD
I'm trying to customize the Tracking skill for an RPG shard.
Compile and i Obtain the info relative to the mobile, however when I put on track on a mobile and I kill it, the client crashes for unknown packet: 0xff...
I think I'm wrong in pointing out the closing of the gump as well as the arrow, but honestly I can not fix
I'm trying to customize the Tracking skill for an RPG shard.
Compile and i Obtain the info relative to the mobile, however when I put on track on a mobile and I kill it, the client crashes for unknown packet: 0xff...
Code:
using System;
using System.Collections;
using Server;
using Server.Gumps;
using Server.Network;
using Server.Spells;
using Server.Spells.Necromancy;
using Server.Mobiles;
using Server.Misc;
using Server.Items;
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 )
{
if (m.Hidden == true && (m is PlayerMobile))
{
PlayerMobile playa = (PlayerMobile)m;
int skillsum = (int)(playa.Skills.Hiding.Value);
skillsum += (int)(playa.Skills.Stealth.Value);
skillsum = (int)(skillsum / 2);
skillsum += (int)(playa.RawDex / 10);
if (playa.ClasseType == ClasseType.Rogue)
skillsum += 64;
if (playa.ClasseType == ClasseType.Ranger)
skillsum += 21;
if (skillsum > Utility.Random (175))
{
m.SendLocalizedMessage( 1011350 ); // What do you wish to track?
m.CloseGump( typeof( TrackWhatGump ) );
m.CloseGump( typeof( TrackWhoGump ) );
m.SendGump( new TrackWhatGump( m ) );
m.SendMessage ("Riesci a non rivelare la tua posizione");
}
else
{
m.RevealingAction ();
m.SendMessage ("Riveli la tua posizione!");
m.Emote ("*Cerca qualcosa*");
m.SendLocalizedMessage( 1011350 ); // What do you wish to track?
m.CloseGump( typeof( TrackWhatGump ) );
m.CloseGump( typeof( TrackWhoGump ) );
m.SendGump( new TrackWhatGump( m ) );
}
}
else
{
m.Emote ("*Cerca qualcosa*");
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;
double bonus = Math.Sqrt((xDelta * xDelta) + (yDelta * yDelta));
m_Table.Remove(tracker); //Reset as of Pub 40, counting it as bug for Core.SE.
if (Core.ML)
return Math.Min(bonus, 10 + tracker.Skills.Tracking.Value / 10);
return bonus;
}
public static void ClearTrackingInfo( Mobile tracker )
{
m_Table.Remove( tracker );
}
}
public class TrackWhatGump : Gump
{
private Mobile m_From;
private bool m_Success;
public TrackWhatGump( Mobile from ) : base( 20, 30 )
{
m_From = from;
m_Success = from.CheckSkill( SkillName.Tracking, 0.0, 21.1 );
AddPage( 0 );
AddBackground( 0, 0, 440, 135, 5054 );
AddBackground( 10, 10, 420, 75, 2620 );
AddBackground( 10, 85, 420, 25, 3000 );
AddItem( 20, 20, 9682 );
AddButton( 20, 110, 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 20, 90, 100, 20, 1018087, false, false ); // Animals
AddItem( 120, 20, 9607 );
AddButton( 120, 110, 4005, 4007, 2, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 120, 90, 100, 20, 1018088, false, false ); // Monsters
AddItem( 220, 20, 8454 );
AddButton( 220, 110, 4005, 4007, 3, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 220, 90, 100, 20, 1018089, false, false ); // Human NPCs
AddItem( 320, 20, 8455 );
AddButton( 320, 110, 4005, 4007, 4, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 320, 90, 100, 20, 1018090, false, false ); // Players
}
public override void OnResponse( NetState state, RelayInfo info )
{
if ( info.ButtonID >= 1 && info.ButtonID <= 4 )
TrackWhoGump.DisplayTo( m_Success, m_From, info.ButtonID - 1 );
}
}
public delegate bool TrackTypeDelegate( Mobile m );
public class TrackWhoGump : Gump
{
private Mobile m_From;
private int m_Range;
private static TrackTypeDelegate[] m_Delegates = new TrackTypeDelegate[]
{
new TrackTypeDelegate( IsAnimal ),
new TrackTypeDelegate( IsMonster ),
new TrackTypeDelegate( IsHumanNPC ),
new TrackTypeDelegate( IsPlayer )
};
private class InternalSorter : IComparer
{
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 / 3);
PlayerMobile pm = (PlayerMobile) from;
if (pm.ClasseType == ClasseType.Ranger && type == 0)
range += (int)(from.Skills[SkillName.AnimalTaming].Value / 5);
if (pm.ClasseType == ClasseType.Rogue)
range += (int)(from.Skills[SkillName.Tracking].Value / 10);
bool canide = false;
ArrayList listino = new ArrayList();
foreach ( Mobile animale in pm.GetMobilesInRange( 4 ) )
{
// Ghosts can no longer be tracked
if ( animale.Alive && animale is BaseCreature )
{
if ( ((BaseCreature)animale).Controlled )
listino.Add(animale);
}
}
for (int i = 0; i < listino.Count; i++)
{
Mobile ora = listino as Mobile;
if ( ((BaseCreature)ora).ControlMaster == pm && ((BaseCreature)ora).TipoPet == PetType.Canide)
{
canide = true;
ora.Emote ("*Fiuta*");
}
}
if (pm.Hidden == true)
{
if (pm.ClasseType == ClasseType.Rogue)
range -= 10;
else if (pm.ClasseType == ClasseType.Ranger)
range -= 20;
else
range -= 30;
}
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, canide ) )
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, bool hasdog )
{
if ( !Core.AOS || !m.Player )
return true;
int tracking = from.Skills[SkillName.Tracking].Fixed;
int detectHidden = from.Skills[SkillName.DetectHidden].Fixed;
if (hasdog)
tracking += 50;
int hiding = m.Skills[SkillName.Hiding].Fixed;
int stealth = m.Skills[SkillName.Stealth].Fixed;
if (m is PlayerMobile)
{
hiding += ( PlayerMobile.BonusHidingRogue( m ));
}
if ( m is BaseCreature )
{
hiding += ( 12 * (3 - (int)((BaseCreature)m).Stazza ) );
}
int divisor = hiding + stealth;
// Necromancy forms affect tracking difficulty
if (TransformationSpellHelper.UnderTransformation(m, typeof(HorrificBeastSpell)))
divisor -= 200;
else if (TransformationSpellHelper.UnderTransformation(m, typeof(VampiricEmbraceSpell)) && divisor < 500)
divisor = 500;
else if (TransformationSpellHelper.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 int ArrowDir( Direction d )
{
switch ( d )
{
case Direction.North: return 0x1195; break;
case Direction.Right: return 0x1196; break;
case Direction.East: return 0x1197; break;
case Direction.Down: return 0x1198; break;
case Direction.South: return 0x1199; break;
case Direction.Left: return 0x119A; break;
case Direction.West: return 0x119B; break;
case Direction.Up: return 0x1194; break;
}
return 0;
}
private string getDistanzaHue( Mobile one, Mobile two, int range )
{
int dis = -1;
if ( !one.InRange(two, range / 2) )
dis = 0; //fuga
else
{
int rBase = range / 2;
int distanza = Math.Max( Math.Abs( one.X - two.X ), Math.Abs( one.Y - two.Y ) );
dis = (int)( 4.0 - ( ( (double)distanza / (double)rBase ) * 3 ) );
}
if ( dis >= 3 )
return "008706";
else
if ( dis == 2 )
return "D27C00";
else
return "BF0000";
}
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;
AddItem( 20 + ((i % 4) * 100), 20 + ((i / 4) * 155), ShrinkTable.Lookup( m ) );
Direction d = from.GetDirectionTo( m );
AddImage( 40 + ((i % 4) * 100), 20 + ((i / 4) * 155), ArrowDir( d ));
AddButton( 20 + ((i % 4) * 100), 130 + ((i / 4) * 155), 4005, 4007, i + 1, GumpButtonType.Reply, 0 );
string name = "*Tracce*";
if ( m.Name != null )
{
if ( NotorietyHandlers.GildaOrParty( m_From, m ) )
name = m.Name;
else
{
if ( IsHumanNPC( m ) || IsPlayer( m ) )
{
if ( BaseArmor.GetMaxArmor( m ) >= ArmorMaterialType.Chainmail )
name = "*Tracce marcate*";
else
name = "*Tracce lievi*";
}
else
{
if ( m is BaseCreature )
{
if ( ((BaseCreature)m).ControlMaster != null && ((BaseCreature)m).ControlMaster == m_From )
name = m.Name;
else
if ( (int)((BaseCreature)m).Stazza > 3 )
{
if ( (int)((BaseCreature)m).Stazza > 5 )
name = "*Tracce ovvie*";
else
name = "*Tracce prominenti*";
}
}
}
}
}
AddHtml( 20 + ((i % 4) * 100), 90 + ((i / 4) * 155), 90, 40, "<BASEFONT COLOR=#" + getDistanzaHue( m, m_From, m_Range ) + ">" + name + "</BASEFONT>", 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, target )
{
m_From = from;
m_Timer = new TrackTimer( from, target, range, this );
m_Timer.Start();
}
public override void OnClick( bool rightClick )
{
if ( rightClick )
{
Tracking.ClearTrackingInfo( m_From );
m_From = null;
Stop();
}
}
public override void OnStop()
{
m_Timer.Stop();
if ( m_From != null )
{
Tracking.ClearTrackingInfo( m_From );
m_From.SendLocalizedMessage( 503177 ); // You have lost your quarry.
}
}
}
public class TrackInfoGump : Gump
{
private string ConvertiArmor( ArmorMaterialType amt )
{
if (amt >= ArmorMaterialType.Plate )
return "Armatura pesante";
else
if (amt >= ArmorMaterialType.Ringmail )
return "Armatura metallica";
else
if (amt >= ArmorMaterialType.Leather )
return "Armatura leggera";
else
return "Senza armatura";
}
private string ConvertiCondizione( int cond )
{
if ( cond == 5 )
return "In salute e vigore";
else
if ( cond == 4 )
return "Lieve affaticamento";
else
if ( cond == 3 )
return "In difficolta`";
else
if ( cond == 2 )
return "In seria difficolta`";
else
if ( cond == 1 )
return "Gravissimi problemi";
else
if ( cond == 0 )
return "Morente";
else
return "Non definibile";
}
private string ConvertiDist( int dist )
{
if ( dist >= 3 )
return "Vicine";
else
if ( dist == 2 )
return "Media freschezza";
else
if ( dist == 1 )
return "Vecchie";
else
if ( dist == 0 )
return "In perdita...";
else
return "non valutabili";
}
private int ConvertiDistHue( int dist )
{
if ( dist >= 3 )
return 66;
else
if ( dist == 2 )
return 43;
else
return 32;
}
public TrackInfoGump( Mobile hunt, Mobile quarry, int displayCond, int dist ) : base ( 450, 50 )
{
Closable=true;
Disposable=true;
Dragable=true;
Resizable=false;
AddPage(0);
AddBackground(0, 0, 250,150, 0x2422);
AddLabel(40, 30, 43, @"Dati sulle tracce");
String data = "";
double punteggio = hunt.Skills.Tracking.Value + ( hunt.Skills.Camping.Value / 2.0 );
if ( quarry is BaseCreature && ((BaseCreature)quarry).Tamable )
punteggio += ( hunt.Skills.AnimalLore. Value / 3.0 );
if ( punteggio >= 130 )
{
if ( quarry is BaseCreature )
{
if ( !quarry.Body.IsHuman )
data = "Tipologia: " + ((BaseCreature)quarry).TrackName;
else
data = "Tipologia: Umanoide - " + ConvertiArmor( BaseArmor.GetMaxArmor( quarry ) );
}
else
if ( quarry.Player )
{
if ( ((PlayerMobile)quarry).ClasseType != ClasseType.Rogue )
data = "Tipologia: Umanoide - " + ConvertiArmor( BaseArmor.GetMaxArmor( quarry ) );
else
{
data = "Tipologia: Umanoide - Armatura leggera";
}
}
AddLabel(40, 50, 50, @data);
}
if ( punteggio >= 150 )
{
data = "Condizioni: " + ConvertiCondizione( displayCond );
AddLabel(40,70, 50, @data);
}
data = "Tracce: " + ConvertiDist( dist );
AddLabel(40, 90, ConvertiDistHue( dist ), @data);
}
}
public class TrackTimer : Timer
{
private Mobile m_From, m_Target;
private int m_Range;
private int m_LastX, m_LastY;
private QuestArrow m_Arrow;
private bool isescaping = false;
private int beforerun;
private PlayerMobile pm;
private int lastKnownCond;
private double condDist;
private int getCondition( Mobile mob )
{
double percent = ( (double)mob.Hits / (double)mob.HitsMax );
percent *= 0.75;
percent += ( ( (double)mob.Stam / (double)mob.StamMax ) / 4.0 );
percent *= 5.0;
return (int)(percent);
}
private int getDistanza( Mobile one, Mobile two, int range )
{
if ( !one.InRange(two, range / 2) )
return 0; //fuga
else
{
int rBase = range / 2;
int distanza = Math.Max( Math.Abs( one.X - two.X ), Math.Abs( one.Y - two.Y ) );
return (int)( 4.0 - ( ( (double)distanza / (double)rBase ) * 3 ) );
}
}
private bool AllowCondizioni( Mobile hunt, Mobile quarry )
{
double punteggio = hunt.Skills.Tracking.Value + ( hunt.Skills.Camping.Value / 2.0 );
if ( quarry is BaseCreature && ((BaseCreature)quarry).Tamable )
punteggio += ( hunt.Skills.AnimalLore. Value / 3.0 );
return ( punteggio >= 150 );
}
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;
pm = (PlayerMobile) m_From;
if ( AllowCondizioni( m_From, target ) )
lastKnownCond = getCondition( target );
else
lastKnownCond = -1;
condDist = Math.Sqrt( (Math.Abs( m_From.X - target.X ))^2 + (Math.Abs( m_From.Y - target.Y ))^2 );
}
protected override void OnTick()
{
if ( !m_Arrow.Running )
{
Stop();
return;
}
else if (this.m_From.NetState == null || this.m_From.Deleted || this.m_Target.Deleted || this.m_From.Map != this.m_Target.Map || !this.m_From.InRange(this.m_Target, this.m_Range) || this.m_Target is Mobile && (((Mobile)this.m_Target).Hidden && ((Mobile)this.m_Target).AccessLevel > this.m_From.AccessLevel) || beforerun > 60)
{
m_From.Send( new CancelArrow() );
m_From.SendLocalizedMessage( 503177 ); // You have lost your quarry.
Tracking.ClearTrackingInfo( m_From );
m_From.CloseGump( typeof( TrackInfoGump ) );
Stop();
return;
}
if (!m_From.InRange(m_Target, m_Range / 2) && !isescaping)
{
isescaping = true;
m_From.SendMessage ("Le tracce si fanno poco visibili, fatichi a seguirle...");
beforerun = 0;
lastKnownCond = -1;
}
if (!m_From.InRange(m_Target, m_Range / 2) && isescaping && beforerun <= 60)
{
if (pm.ClasseType == ClasseType.Rogue)
beforerun +=2;
else
{
beforerun += 3;
}
}
if (m_From.InRange(m_Target, m_Range / 2) && isescaping)
{
isescaping = false;
m_From.SendMessage ("Ritrovi la pista");
beforerun = 0;
}
if ( m_LastX != m_Target.X || m_LastY != m_Target.Y )
{
if ( Math.Sqrt( (Math.Abs( m_From.X - m_Target.X ))^2 + (Math.Abs( m_From.Y - m_Target.Y ))^2 ) < condDist && AllowCondizioni( m_From, m_Target ) )
lastKnownCond = getCondition( m_Target );
m_LastX = m_Target.X;
m_LastY = m_Target.Y;
m_Arrow.Update( m_LastX, m_LastY );
}
m_From.CloseGump( typeof( TrackInfoGump ) );
if ( AllowCondizioni( m_From, m_Target ) )
{
m_From.SendGump( new TrackInfoGump( m_From, m_Target, lastKnownCond, getDistanza( m_From, m_Target, m_Range ) ) );
}
else
m_From.SendGump( new TrackInfoGump( m_From, m_Target, -1, getDistanza( m_From, m_Target, m_Range ) ) );
}
}
}
Last edited by a moderator: