#W# Source and Scripts added. Added Scripts/Settings.cs to expose some basic tweak able settings.

This commit is contained in:
WarrentyExpired 2026-08-06 11:06:05 -04:00
parent b51c58f514
commit 3045c83799
3512 changed files with 627673 additions and 0 deletions

View file

@ -0,0 +1,556 @@
using System;
using System.Collections.Generic;
using Server;
using Server.Gumps;
using Server.Items;
using Server.Mobiles;
using Server.Network;
using Server.Targeting;
namespace Server.Items
{
public class Bandage : Item, IDyable
{
public static int Range = ( Core.AOS ? 2 : 1 );
public override double DefaultWeight
{
get { return 0.1; }
}
public static void Initialize()
{
EventSink.BandageTargetRequest += new BandageTargetRequestEventHandler(EventSink_BandageTargetRequest);
}
[Constructable]
public Bandage() : this( 1 )
{
}
[Constructable]
public Bandage( int amount ) : base( 0xE21 )
{
Stackable = true;
Amount = amount;
}
public Bandage( Serial serial ) : base( serial )
{
}
public virtual bool Dye( Mobile from, DyeTub sender )
{
if ( Deleted )
return false;
Hue = sender.DyedHue;
return true;
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int) 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
}
public override void OnDoubleClick( Mobile from )
{
if ( from.InRange( GetWorldLocation(), Range ) )
{
from.RevealingAction();
from.SendLocalizedMessage( 500948 ); // Who will you use the bandages on?
from.Target = new InternalTarget( this );
}
else
{
from.SendLocalizedMessage( 500295 ); // You are too far away to do that.
}
}
private static void EventSink_BandageTargetRequest(BandageTargetRequestEventArgs e)
{
Bandage b = e.Bandage as Bandage;
if (b == null || b.Deleted)
return;
Mobile from = e.Mobile;
if (from.InRange(b.GetWorldLocation(), Range))
{
Target t = from.Target;
if (t != null)
{
Target.Cancel(from);
from.Target = null;
}
from.RevealingAction();
from.SendLocalizedMessage(500948); // Who will you use the bandages on?
new InternalTarget(b).Invoke(from, e.Target);
}
else
{
from.SendLocalizedMessage(500295); // You are too far away to do that.
}
}
private class InternalTarget : Target
{
private Bandage m_Bandage;
public InternalTarget( Bandage bandage ) : base( Bandage.Range, false, TargetFlags.Beneficial )
{
m_Bandage = bandage;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( m_Bandage.Deleted )
return;
if ( targeted is Mobile )
{
if ( from.InRange( m_Bandage.GetWorldLocation(), Bandage.Range ) )
{
if ( BandageContext.BeginHeal( from, (Mobile)targeted ) != null )
{
if ( !Engines.ConPVP.DuelContext.IsFreeConsume( from ) )
m_Bandage.Consume();
}
}
else
{
from.SendLocalizedMessage( 500295 ); // You are too far away to do that.
}
}
else if ( targeted is PlagueBeastInnard )
{
if ( ((PlagueBeastInnard) targeted).OnBandage( from ) )
m_Bandage.Consume();
}
else
{
from.SendLocalizedMessage( 500970 ); // Bandages can not be used on that.
}
}
protected override void OnNonlocalTarget( Mobile from, object targeted )
{
if ( targeted is PlagueBeastInnard )
{
if ( ((PlagueBeastInnard) targeted).OnBandage( from ) )
m_Bandage.Consume();
}
else
base.OnNonlocalTarget( from, targeted );
}
}
}
public class BandageContext
{
private Mobile m_Healer;
private Mobile m_Patient;
private int m_Slips;
private Timer m_Timer;
public Mobile Healer{ get{ return m_Healer; } }
public Mobile Patient{ get{ return m_Patient; } }
public int Slips{ get{ return m_Slips; } set{ m_Slips = value; } }
public Timer Timer{ get{ return m_Timer; } }
public void Slip()
{
m_Healer.SendLocalizedMessage( 500961 ); // Your fingers slip!
++m_Slips;
}
public BandageContext( Mobile healer, Mobile patient, TimeSpan delay )
{
m_Healer = healer;
m_Patient = patient;
m_Timer = new InternalTimer( this, delay );
m_Timer.Start();
}
public void StopHeal()
{
m_Table.Remove( m_Healer );
if ( m_Timer != null )
m_Timer.Stop();
m_Timer = null;
}
private static Dictionary<Mobile, BandageContext> m_Table = new Dictionary<Mobile, BandageContext>();
public static BandageContext GetContext( Mobile healer )
{
BandageContext bc = null;
m_Table.TryGetValue( healer, out bc );
return bc;
}
public static SkillName GetPrimarySkill( Mobile m )
{
if ( !m.Player && (m.Body.IsMonster || m.Body.IsAnimal) )
return SkillName.Veterinary;
else
return SkillName.Healing;
}
public static SkillName GetSecondarySkill( Mobile m )
{
if ( !m.Player && (m.Body.IsMonster || m.Body.IsAnimal) )
return SkillName.AnimalLore;
else
return SkillName.Anatomy;
}
public void EndHeal()
{
StopHeal();
int healerNumber = -1, patientNumber = -1;
bool playSound = true;
bool checkSkills = false;
SkillName primarySkill = GetPrimarySkill( m_Patient );
SkillName secondarySkill = GetSecondarySkill( m_Patient );
BaseCreature petPatient = m_Patient as BaseCreature;
if ( !m_Healer.Alive )
{
healerNumber = 500962; // You were unable to finish your work before you died.
patientNumber = -1;
playSound = false;
}
else if ( !m_Healer.InRange( m_Patient, Bandage.Range ) )
{
healerNumber = 500963; // You did not stay close enough to heal your target.
patientNumber = -1;
playSound = false;
}
else if ( !m_Patient.Alive || (petPatient != null && petPatient.IsDeadPet) )
{
double healing = m_Healer.Skills[primarySkill].Value;
double anatomy = m_Healer.Skills[secondarySkill].Value;
double chance = ((healing - 68.0) / 50.0) - (m_Slips * 0.02);
if (( (checkSkills = (healing >= 80.0 && anatomy >= 80.0)) && chance > Utility.RandomDouble() )
|| ( Core.SE && petPatient is Factions.FactionWarHorse && petPatient.ControlMaster == m_Healer) ) //TODO: Dbl check doesn't check for faction of the horse here?
{
if ( m_Patient.Map == null || !m_Patient.Map.CanFit( m_Patient.Location, 16, false, false ) )
{
healerNumber = 501042; // Target can not be resurrected at that location.
patientNumber = 502391; // Thou can not be resurrected there!
}
else if ( m_Patient.Region != null && m_Patient.Region.IsPartOf( "Khaldun" ) )
{
healerNumber = 1010395; // The veil of death in this area is too strong and resists thy efforts to restore life.
patientNumber = -1;
}
else
{
healerNumber = 500965; // You are able to resurrect your patient.
patientNumber = -1;
m_Patient.PlaySound( 0x214 );
m_Patient.FixedEffect( 0x376A, 10, 16 );
if ( petPatient != null && petPatient.IsDeadPet )
{
Mobile master = petPatient.ControlMaster;
if( master != null && m_Healer == master )
{
petPatient.ResurrectPet();
for ( int i = 0; i < petPatient.Skills.Length; ++i )
{
petPatient.Skills[i].Base -= 0.1;
}
}
else if ( master != null && master.InRange( petPatient, 3 ) )
{
healerNumber = 503255; // You are able to resurrect the creature.
master.CloseGump( typeof( PetResurrectGump ) );
master.SendGump( new PetResurrectGump( m_Healer, petPatient ) );
}
else
{
bool found = false;
List<Mobile> friends = petPatient.Friends;
for ( int i = 0; friends != null && i < friends.Count; ++i )
{
Mobile friend = friends[i];
if ( friend.InRange( petPatient, 3 ) )
{
healerNumber = 503255; // You are able to resurrect the creature.
friend.CloseGump( typeof( PetResurrectGump ) );
friend.SendGump( new PetResurrectGump( m_Healer, petPatient ) );
found = true;
break;
}
}
if ( !found )
healerNumber = 1049670; // The pet's owner must be nearby to attempt resurrection.
}
}
else
{
m_Patient.CloseGump( typeof( ResurrectGump ) );
m_Patient.SendGump( new ResurrectGump( m_Patient, m_Healer ) );
}
}
}
else
{
if ( petPatient != null && petPatient.IsDeadPet )
healerNumber = 503256; // You fail to resurrect the creature.
else
healerNumber = 500966; // You are unable to resurrect your patient.
patientNumber = -1;
}
}
else if ( m_Patient.Poisoned )
{
m_Healer.SendLocalizedMessage( 500969 ); // You finish applying the bandages.
double healing = m_Healer.Skills[primarySkill].Value;
double anatomy = m_Healer.Skills[secondarySkill].Value;
double chance = ((healing - 30.0) / 50.0) - (m_Patient.Poison.Level * 0.1) - (m_Slips * 0.02);
if ( (checkSkills = (healing >= 60.0 && anatomy >= 60.0)) && chance > Utility.RandomDouble() )
{
if ( m_Patient.CurePoison( m_Healer ) )
{
healerNumber = (m_Healer == m_Patient) ? -1 : 1010058; // You have cured the target of all poisons.
patientNumber = 1010059; // You have been cured of all poisons.
}
else
{
healerNumber = -1;
patientNumber = -1;
}
}
else
{
healerNumber = 1010060; // You have failed to cure your target!
patientNumber = -1;
}
}
else if ( BleedAttack.IsBleeding( m_Patient ) )
{
healerNumber = 1060088; // You bind the wound and stop the bleeding
patientNumber = 1060167; // The bleeding wounds have healed, you are no longer bleeding!
BleedAttack.EndBleed( m_Patient, false );
}
else if ( MortalStrike.IsWounded( m_Patient ) )
{
healerNumber = ( m_Healer == m_Patient ? 1005000 : 1010398 );
patientNumber = -1;
playSound = false;
}
else if ( m_Patient.Hits == m_Patient.HitsMax )
{
healerNumber = 500967; // You heal what little damage your patient had.
patientNumber = -1;
}
else
{
checkSkills = true;
patientNumber = -1;
double healing = m_Healer.Skills[primarySkill].Value;
double anatomy = m_Healer.Skills[secondarySkill].Value;
double chance = ((healing + 10.0) / 100.0) - (m_Slips * 0.02);
if ( chance > Utility.RandomDouble() )
{
healerNumber = 500969; // You finish applying the bandages.
double min, max;
if ( Core.AOS )
{
min = (anatomy / 8.0) + (healing / 5.0) + 4.0;
max = (anatomy / 6.0) + (healing / 2.5) + 4.0;
}
else
{
min = (anatomy / 5.0) + (healing / 5.0) + 3.0;
max = (anatomy / 5.0) + (healing / 2.0) + 10.0;
}
double toHeal = min + (Utility.RandomDouble() * (max - min));
if ( m_Patient.Body.IsMonster || m_Patient.Body.IsAnimal )
toHeal += m_Patient.HitsMax / 100;
if ( Core.AOS )
toHeal -= toHeal * m_Slips * 0.35; // TODO: Verify algorithm
else
toHeal -= m_Slips * 4;
if ( toHeal < 1 )
{
toHeal = 1;
healerNumber = 500968; // You apply the bandages, but they barely help.
}
m_Patient.Heal( (int) toHeal, m_Healer, false );
}
else
{
healerNumber = 500968; // You apply the bandages, but they barely help.
playSound = false;
}
}
if ( healerNumber != -1 )
m_Healer.SendLocalizedMessage( healerNumber );
if ( patientNumber != -1 )
m_Patient.SendLocalizedMessage( patientNumber );
if ( playSound )
m_Patient.PlaySound( 0x57 );
if ( checkSkills )
{
m_Healer.CheckSkill( secondarySkill, 0.0, 120.0 );
m_Healer.CheckSkill( primarySkill, 0.0, 120.0 );
}
}
private class InternalTimer : Timer
{
private BandageContext m_Context;
public InternalTimer( BandageContext context, TimeSpan delay ) : base( delay )
{
m_Context = context;
Priority = TimerPriority.FiftyMS;
}
protected override void OnTick()
{
m_Context.EndHeal();
}
}
public static BandageContext BeginHeal( Mobile healer, Mobile patient )
{
bool isDeadPet = ( patient is BaseCreature && ((BaseCreature)patient).IsDeadPet );
if ( patient is Golem )
{
healer.SendLocalizedMessage( 500970 ); // Bandages cannot be used on that.
}
else if ( patient is BaseCreature && ((BaseCreature)patient).IsAnimatedDead )
{
healer.SendLocalizedMessage( 500951 ); // You cannot heal that.
}
else if ( !patient.Poisoned && patient.Hits == patient.HitsMax && !BleedAttack.IsBleeding( patient ) && !isDeadPet )
{
healer.SendLocalizedMessage( 500955 ); // That being is not damaged!
}
else if ( !patient.Alive && (patient.Map == null || !patient.Map.CanFit( patient.Location, 16, false, false )) )
{
healer.SendLocalizedMessage( 501042 ); // Target cannot be resurrected at that location.
}
else if ( healer.CanBeBeneficial( patient, true, true ) )
{
healer.DoBeneficial( patient );
bool onSelf = ( healer == patient );
int dex = healer.Dex;
double seconds;
double resDelay = ( patient.Alive ? 0.0 : 5.0 );
if ( onSelf )
{
if ( Core.AOS )
seconds = 5.0 + (0.5 * ((double)(120 - dex) / 10)); // TODO: Verify algorithm
else
seconds = 9.4 + (0.6 * ((double)(120 - dex) / 10));
}
else
{
if ( Core.AOS && GetPrimarySkill( patient ) == SkillName.Veterinary )
{
seconds = 2.0;
}
else if ( Core.AOS )
{
if (dex < 204)
{
seconds = 3.2-(Math.Sin((double)dex/130)*2.5) + resDelay;
}
else
{
seconds = 0.7 + resDelay;
}
}
else
{
if ( dex >= 100 )
seconds = 3.0 + resDelay;
else if ( dex >= 40 )
seconds = 4.0 + resDelay;
else
seconds = 5.0 + resDelay;
}
}
BandageContext context = GetContext( healer );
if ( context != null )
context.StopHeal();
seconds *= 1000;
context = new BandageContext( healer, patient, TimeSpan.FromMilliseconds( seconds ) );
m_Table[healer] = context;
if ( !onSelf )
patient.SendLocalizedMessage( 1008078, false, healer.Name ); // : Attempting to heal you.
healer.SendLocalizedMessage( 500956 ); // You begin applying the bandages.
return context;
}
return null;
}
}
}

View file

@ -0,0 +1,225 @@
using System;
using System.Collections;
using Server;
using Server.Network;
using Server.Targeting;
using Server.Spells;
namespace Server.Items
{
public class FireHorn : Item
{
public override int LabelNumber{ get{ return 1060456; } } // fire horn
[Constructable]
public FireHorn() : base( 0xFC7 )
{
Hue = 0x466;
Weight = 1.0;
}
public FireHorn( Serial serial ) : base( serial )
{
}
private bool CheckUse( Mobile from )
{
if ( !this.IsAccessibleTo( from ) )
return false;
if ( from.Map != this.Map || !from.InRange( GetWorldLocation(), 2 ) )
{
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
return false;
}
if ( !from.CanBeginAction( typeof( FireHorn ) ) )
{
from.SendLocalizedMessage( 1049615 ); // You must take a moment to catch your breath.
return false;
}
int sulfAsh = Core.AOS ? 4 : 15;
if ( from.Backpack == null || from.Backpack.GetAmount( typeof( SulfurousAsh ) ) < sulfAsh )
{
from.SendLocalizedMessage( 1049617 ); // You do not have enough sulfurous ash.
return false;
}
return true;
}
public override void OnDoubleClick( Mobile from )
{
if ( CheckUse( from ) )
{
from.SendLocalizedMessage( 1049620 ); // Select an area to incinerate.
from.Target = new InternalTarget( this );
}
}
public void Use( Mobile from, IPoint3D loc )
{
if ( !CheckUse( from ) )
return;
from.BeginAction( typeof( FireHorn ) );
Timer.DelayCall( Core.AOS ? TimeSpan.FromSeconds( 6.0 ) : TimeSpan.FromSeconds( 12.0 ), new TimerStateCallback( EndAction ), from );
int music = from.Skills[SkillName.Musicianship].Fixed;
int sucChance = 500 + ( music - 775 ) * 2;
double dSucChance = ((double)sucChance) / 1000.0;
if ( !from.CheckSkill( SkillName.Musicianship, dSucChance ) )
{
from.SendLocalizedMessage( 1049618 ); // The horn emits a pathetic squeak.
from.PlaySound( 0x18A );
return;
}
int sulfAsh = Core.AOS ? 4 : 15;
from.Backpack.ConsumeUpTo( typeof( SulfurousAsh ), sulfAsh );
from.PlaySound( 0x15F );
Effects.SendPacket( from, from.Map, new HuedEffect( EffectType.Moving, from.Serial, Serial.Zero, 0x36D4, from.Location, loc, 5, 0, false, true, 0, 0 ) );
ArrayList targets = new ArrayList();
bool playerVsPlayer = false;
IPooledEnumerable eable = from.Map.GetMobilesInRange( new Point3D( loc ), 2 );
foreach ( Mobile m in eable )
{
if ( from != m && SpellHelper.ValidIndirectTarget( from, m ) && from.CanBeHarmful( m, false ) )
{
if ( Core.AOS && !from.InLOS( m ) )
continue;
targets.Add( m );
if ( m.Player )
playerVsPlayer = true;
}
}
eable.Free();
if ( targets.Count > 0 )
{
int prov = from.Skills[SkillName.Provocation].Fixed;
int disc = from.Skills[SkillName.Discordance].Fixed;
int peace = from.Skills[SkillName.Peacemaking].Fixed;
int minDamage, maxDamage;
if ( Core.AOS )
{
int musicScaled = music + Math.Max( 0, music - 900 ) * 2;
int provScaled = prov + Math.Max( 0, prov - 900 ) * 2;
int discScaled = disc + Math.Max( 0, disc - 900 ) * 2;
int peaceScaled = peace + Math.Max( 0, peace - 900 ) * 2;
int weightAvg = ( musicScaled + provScaled * 3 + discScaled * 3 + peaceScaled ) / 80;
int avgDamage;
if ( playerVsPlayer )
avgDamage = weightAvg / 3;
else
avgDamage = weightAvg / 2;
minDamage = ( avgDamage * 9 ) / 10;
maxDamage = ( avgDamage * 10 ) / 9;
}
else
{
int total = prov + disc / 5 + peace / 5;
if ( playerVsPlayer )
total /= 3;
maxDamage = ( total * 2 ) / 30;
minDamage = ( maxDamage * 7 ) / 10;
}
double damage = Utility.RandomMinMax( minDamage, maxDamage );
if ( Core.AOS && targets.Count > 1 )
damage = (damage * 2) / targets.Count;
else if ( !Core.AOS )
damage /= targets.Count;
for ( int i = 0; i < targets.Count; ++i )
{
Mobile m = (Mobile)targets[i];
double toDeal = damage;
if ( !Core.AOS && m.CheckSkill( SkillName.MagicResist, 0.0, 120.0 ) )
{
toDeal *= 0.5;
m.SendLocalizedMessage( 501783 ); // You feel yourself resisting magical energy.
}
from.DoHarmful( m );
SpellHelper.Damage( TimeSpan.Zero, m, from, toDeal, 0, 100, 0, 0, 0 );
Effects.SendTargetEffect( m, 0x3709, 10, 30 );
}
}
double breakChance = Core.AOS ? 0.01 : 0.16;
if ( Utility.RandomDouble() < breakChance )
{
from.SendLocalizedMessage( 1049619 ); // The fire horn crumbles in your hands.
this.Delete();
}
}
private static void EndAction( object state )
{
Mobile m = (Mobile) state;
m.EndAction( typeof( FireHorn ) );
m.SendLocalizedMessage( 1049621 ); // You catch your breath.
}
private class InternalTarget : Target
{
private FireHorn m_Horn;
public InternalTarget( FireHorn horn ) : base( Core.AOS ? 3 : 2, true, TargetFlags.Harmful )
{
m_Horn = horn;
}
protected override void OnTarget( Mobile from, object targeted )
{
if ( m_Horn.Deleted )
return;
IPoint3D loc;
if ( targeted is Item )
loc = ((Item)targeted).GetWorldLocation();
else
loc = targeted as IPoint3D;
m_Horn.Use( from, loc );
}
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.WriteEncodedInt( 0 ); // version
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadEncodedInt();
}
}
}

View file

@ -0,0 +1,124 @@
using System;
using Server;
using Server.Engines.Craft;
using Server.Mobiles;
using Server.Network;
namespace Server.Items
{
public class RecipeScroll : Item
{
public override int LabelNumber { get { return 1074560; } } // recipe scroll
private int m_RecipeID;
[CommandProperty( AccessLevel.GameMaster )]
public int RecipeID
{
get { return m_RecipeID; }
set { m_RecipeID = value; InvalidateProperties(); }
}
public Recipe Recipe
{
get
{
if ( Recipe.Recipes.ContainsKey( m_RecipeID ) )
return Recipe.Recipes[m_RecipeID];
return null;
}
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
Recipe r = this.Recipe;
if( r != null )
list.Add( 1049644, r.TextDefinition.ToString() ); // [~1_stuff~]
}
public RecipeScroll( Recipe r )
: this( r.ID )
{
}
[Constructable]
public RecipeScroll( int recipeID )
: base( 0x2831 )
{
m_RecipeID = recipeID;
}
public RecipeScroll( Serial serial )
: base( serial )
{
}
public override void OnDoubleClick( Mobile from )
{
if( !from.InRange( this.GetWorldLocation(), 2 ) )
{
from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that.
return;
}
Recipe r = this.Recipe;
if( r != null && from is PlayerMobile )
{
PlayerMobile pm = from as PlayerMobile;
if( !pm.HasRecipe( r ) )
{
bool allRequiredSkills = true;
double chance = r.CraftItem.GetSuccessChance( from, null, r.CraftSystem, false, ref allRequiredSkills );
if ( allRequiredSkills && chance >= 0.0 )
{
pm.SendLocalizedMessage( 1073451, r.TextDefinition.ToString() ); // You have learned a new recipe: ~1_RECIPE~
pm.AcquireRecipe( r );
this.Delete();
}
else
{
pm.SendLocalizedMessage( 1044153 ); // You don't have the required skills to attempt this item.
}
}
else
{
pm.SendLocalizedMessage( 1073427 ); // You already know this recipe.
}
}
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
writer.Write( (int)m_RecipeID );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch( version )
{
case 0:
{
m_RecipeID = reader.ReadInt();
break;
}
}
}
}
}

View file

@ -0,0 +1,246 @@
using System;
using Server;
using Server.Targeting;
using Server.Engines.Craft;
using Server.Mobiles;
using Server.Regions;
namespace Server.Items
{
public class RepairDeed : Item
{
private class RepairSkillInfo
{
private CraftSystem m_System;
private Type[] m_NearbyTypes;
private TextDefinition m_NotNearbyMessage, m_Name;
public TextDefinition NotNearbyMessage{ get { return m_NotNearbyMessage; } }
public TextDefinition Name { get { return m_Name; } }
public CraftSystem System { get { return m_System; } }
public Type[] NearbyTypes { get { return m_NearbyTypes; } }
public RepairSkillInfo( CraftSystem system, Type[] nearbyTypes, TextDefinition notNearbyMessage, TextDefinition name )
{
m_System = system;
m_NearbyTypes = nearbyTypes;
m_NotNearbyMessage = notNearbyMessage;
m_Name = name;
}
public RepairSkillInfo( CraftSystem system, Type nearbyType, TextDefinition notNearbyMessage, TextDefinition name )
: this( system, new Type[] { nearbyType }, notNearbyMessage, name )
{
}
public static RepairSkillInfo[] Table { get { return m_Table; } }
private static RepairSkillInfo[] m_Table = new RepairSkillInfo[]
{
new RepairSkillInfo( DefBlacksmithy.CraftSystem, typeof( Blacksmith ), 1047013, 1023015 ),
new RepairSkillInfo( DefTailoring.CraftSystem, typeof( Tailor ), 1061132, 1022981 ),
new RepairSkillInfo( DefTinkering.CraftSystem, typeof( Tinker ), 1061166, 1022983 ),
new RepairSkillInfo( DefCarpentry.CraftSystem, typeof( Carpenter ), 1061135, 1060774 ),
new RepairSkillInfo( DefBowFletching.CraftSystem, typeof( Bowyer ), 1061134, 1023005 )
};
public static RepairSkillInfo GetInfo( RepairSkillType type )
{
int v = (int)type;
if( v < 0 || v >= m_Table.Length )
v = 0;
return m_Table[v];
}
}
public enum RepairSkillType
{
Smithing,
Tailoring,
Tinkering,
Carpentry,
Fletching
}
public override bool DisplayLootType { get { return false; } }
private RepairSkillType m_Skill;
private double m_SkillLevel;
private Mobile m_Crafter;
[CommandProperty( AccessLevel.GameMaster )]
public RepairSkillType RepairSkill
{
get { return m_Skill; }
set { m_Skill = value; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public double SkillLevel
{
get { return m_SkillLevel; }
set { m_SkillLevel = Math.Max( Math.Min( value, 120.0 ), 0 ) ; InvalidateProperties(); }
}
[CommandProperty( AccessLevel.GameMaster )]
public Mobile Crafter
{
get { return m_Crafter; }
set { m_Crafter = value; InvalidateProperties(); }
}
public override void AddNameProperty( ObjectPropertyList list )
{
list.Add( 1061133, String.Format( "{0}\t{1}", GetSkillTitle( m_SkillLevel ).ToString(), RepairSkillInfo.GetInfo( m_Skill ).Name ) ); // A repair service contract from ~1_SKILL_TITLE~ ~2_SKILL_NAME~.
}
public override void GetProperties( ObjectPropertyList list )
{
base.GetProperties( list );
if( m_Crafter != null )
list.Add( 1050043, m_Crafter.Name ); // crafted by ~1_NAME~
//On OSI it says it's exceptional. Intentional difference.
}
public override void OnSingleClick( Mobile from )
{
if ( Deleted || !from.CanSee( this ) )
return;
this.LabelTo( from, 1061133, String.Format( "{0}\t{1}", GetSkillTitle( m_SkillLevel ).ToString(), RepairSkillInfo.GetInfo( m_Skill ).Name ) ); // A repair service contract from ~1_SKILL_TITLE~ ~2_SKILL_NAME~.
if( m_Crafter != null )
this.LabelTo( from, 1050043, m_Crafter.Name ); // crafted by ~1_NAME~
}
[Constructable]
public RepairDeed() : this( RepairSkillType.Smithing, 100.0, null, true )
{
}
[Constructable]
public RepairDeed( RepairSkillType skill, double level ) : this( skill, level, null, true )
{
}
[Constructable]
public RepairDeed( RepairSkillType skill, double level, bool normalizeLevel ) : this( skill, level, null, normalizeLevel )
{
}
public RepairDeed( RepairSkillType skill, double level, Mobile crafter ) : this( skill, level, crafter, true )
{
}
public RepairDeed( RepairSkillType skill, double level, Mobile crafter, bool normalizeLevel ) : base( 0x14F0 )
{
if( normalizeLevel )
SkillLevel = (int)(level/10)*10;
else
SkillLevel = level;
m_Skill = skill;
m_Crafter = crafter;
Hue = 0x1BC;
LootType = LootType.Blessed;
}
public RepairDeed( Serial serial ) : base( serial )
{
}
private static TextDefinition GetSkillTitle( double skillLevel )
{
int skill = (int)(skillLevel/10);
if( skill >= 11 )
return (1062008 + skill-11);
else if( skill >=5 )
return (1061123 + skill-5);
switch( skill )
{
case 4:
return "a Novice";
case 3:
return "a Neophyte";
default:
return "a Newbie"; //On OSI, it shouldn't go below 50, but, this is for 'custom' support.
}
}
public static RepairSkillType GetTypeFor( CraftSystem s )
{
for( int i = 0; i < RepairSkillInfo.Table.Length; i++ )
{
if( RepairSkillInfo.Table[i].System == s )
return (RepairSkillType)i;
}
return RepairSkillType.Smithing;
}
public override void OnDoubleClick( Mobile from )
{
if( Check( from ) )
Repair.Do( from, RepairSkillInfo.GetInfo( m_Skill ).System, this );
}
public bool Check( Mobile from )
{
if( !IsChildOf( from.Backpack ) )
from.SendLocalizedMessage( 1047012 ); // The contract must be in your backpack to use it.
else if( !VerifyRegion( from ) )
TextDefinition.SendMessageTo( from, RepairSkillInfo.GetInfo( m_Skill ).NotNearbyMessage );
else
return true;
return false;
}
public bool VerifyRegion( Mobile m )
{
//TODO: When the entire region system data is in, convert to that instead of a proximity thing.
if( !m.Region.IsPartOf( typeof( TownRegion ) ) )
return false;
return Server.Factions.Faction.IsNearType( m, RepairSkillInfo.GetInfo( m_Skill ).NearbyTypes, 6 );
}
public override void Serialize( GenericWriter writer )
{
base.Serialize( writer );
writer.Write( (int)0 ); // version
writer.Write( (int)m_Skill );
writer.Write( m_SkillLevel );
writer.Write( m_Crafter );
}
public override void Deserialize( GenericReader reader )
{
base.Deserialize( reader );
int version = reader.ReadInt();
switch( version )
{
case 0:
{
m_Skill = (RepairSkillType)reader.ReadInt();
m_SkillLevel = reader.ReadDouble();
m_Crafter = reader.ReadMobile();
break;
}
}
}
}
}