946 lines
No EOL
20 KiB
C#
946 lines
No EOL
20 KiB
C#
/***************************************************************************
|
|
* Skills.cs
|
|
* -------------------
|
|
* begin : May 1, 2002
|
|
* copyright : (C) The RunUO Software Team
|
|
* email : info@runuo.com
|
|
*
|
|
* $Id$
|
|
*
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
***************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using Server.Network;
|
|
|
|
namespace Server
|
|
{
|
|
public delegate TimeSpan SkillUseCallback( Mobile user );
|
|
|
|
public enum SkillLock : byte
|
|
{
|
|
Up = 0,
|
|
Down = 1,
|
|
Locked = 2
|
|
}
|
|
|
|
public enum SkillName
|
|
{
|
|
Archery = 0,
|
|
Bludgeoning = 1,
|
|
Fencing = 2,
|
|
Swords = 3,
|
|
Tactics = 4,
|
|
Parry = 5,
|
|
Concentration = 6,
|
|
Discordance = 7,
|
|
Dodging = 8,
|
|
HandToHand = 9,
|
|
Healing = 10,
|
|
Hiding = 11,
|
|
Lockpicking = 12,
|
|
Magery = 13,
|
|
MagicResist = 14,
|
|
Meditation = 15,
|
|
Musicianship = 16,
|
|
Peacemaking = 17,
|
|
Poisoning = 18,
|
|
Provocation = 19,
|
|
RemoveTrap = 20,
|
|
Searching = 21,
|
|
Stealing = 22,
|
|
Stealth = 23,
|
|
Tracking = 24
|
|
}
|
|
|
|
[PropertyObject]
|
|
public class Skill
|
|
{
|
|
private Skills m_Owner;
|
|
private SkillInfo m_Info;
|
|
private ushort m_Base;
|
|
private ushort m_Cap;
|
|
private SkillLock m_Lock;
|
|
|
|
public override string ToString()
|
|
{
|
|
return String.Format( "[{0}: {1}]", Name, Base );
|
|
}
|
|
|
|
public Skill( Skills owner, SkillInfo info, GenericReader reader )
|
|
{
|
|
m_Owner = owner;
|
|
m_Info = info;
|
|
|
|
int version = reader.ReadByte();
|
|
|
|
switch ( version )
|
|
{
|
|
case 0:
|
|
{
|
|
m_Base = reader.ReadUShort();
|
|
m_Cap = reader.ReadUShort();
|
|
m_Lock = (SkillLock)reader.ReadByte();
|
|
|
|
break;
|
|
}
|
|
case 0xFF:
|
|
{
|
|
m_Base = 0;
|
|
m_Cap = 1000;
|
|
m_Lock = SkillLock.Up;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
if ( (version & 0xC0) == 0x00 )
|
|
{
|
|
if ( (version & 0x1) != 0 )
|
|
m_Base = reader.ReadUShort();
|
|
|
|
if ( (version & 0x2) != 0 )
|
|
m_Cap = reader.ReadUShort();
|
|
else
|
|
m_Cap = 1000;
|
|
|
|
if ( (version & 0x4) != 0 )
|
|
m_Lock = (SkillLock)reader.ReadByte();
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( m_Lock < SkillLock.Up || m_Lock > SkillLock.Locked )
|
|
{
|
|
Console.WriteLine( "Bad skill lock -> {0}.{1}", owner.Owner, m_Lock );
|
|
m_Lock = SkillLock.Up;
|
|
}
|
|
}
|
|
|
|
public Skill( Skills owner, SkillInfo info, int baseValue, int cap, SkillLock skillLock )
|
|
{
|
|
m_Owner = owner;
|
|
m_Info = info;
|
|
m_Base = (ushort)baseValue;
|
|
m_Cap = (ushort)cap;
|
|
m_Lock = skillLock;
|
|
}
|
|
|
|
public void SetLockNoRelay( SkillLock skillLock )
|
|
{
|
|
if ( skillLock < SkillLock.Up || skillLock > SkillLock.Locked )
|
|
return;
|
|
|
|
m_Lock = skillLock;
|
|
}
|
|
|
|
public void Serialize( GenericWriter writer )
|
|
{
|
|
if ( m_Base == 0 && m_Cap == 1000 && m_Lock == SkillLock.Up )
|
|
{
|
|
writer.Write( (byte) 0xFF ); // default
|
|
}
|
|
else
|
|
{
|
|
int flags = 0x0;
|
|
|
|
if ( m_Base != 0 )
|
|
flags |= 0x1;
|
|
|
|
if ( m_Cap != 1000 )
|
|
flags |= 0x2;
|
|
|
|
if ( m_Lock != SkillLock.Up )
|
|
flags |= 0x4;
|
|
|
|
writer.Write( (byte) flags ); // version
|
|
|
|
if ( m_Base != 0 )
|
|
writer.Write( (short) m_Base );
|
|
|
|
if ( m_Cap != 1000 )
|
|
writer.Write( (short) m_Cap );
|
|
|
|
if ( m_Lock != SkillLock.Up )
|
|
writer.Write( (byte) m_Lock );
|
|
}
|
|
}
|
|
|
|
public Skills Owner
|
|
{
|
|
get
|
|
{
|
|
return m_Owner;
|
|
}
|
|
}
|
|
|
|
public SkillName SkillName
|
|
{
|
|
get
|
|
{
|
|
return (SkillName)m_Info.SkillID;
|
|
}
|
|
}
|
|
|
|
public int SkillID
|
|
{
|
|
get
|
|
{
|
|
return m_Info.SkillID;
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
return m_Info.Name;
|
|
}
|
|
}
|
|
|
|
public SkillInfo Info
|
|
{
|
|
get
|
|
{
|
|
return m_Info;
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public SkillLock Lock
|
|
{
|
|
get
|
|
{
|
|
return m_Lock;
|
|
}
|
|
}
|
|
|
|
public int BaseFixedPoint
|
|
{
|
|
get
|
|
{
|
|
return m_Base;
|
|
}
|
|
set
|
|
{
|
|
if ( value < 0 )
|
|
value = 0;
|
|
else if ( value >= 0x10000 )
|
|
value = 0xFFFF;
|
|
|
|
ushort sv = (ushort)value;
|
|
|
|
int oldBase = m_Base;
|
|
|
|
if ( m_Base != sv )
|
|
{
|
|
m_Owner.Total = (m_Owner.Total - m_Base) + sv;
|
|
|
|
m_Base = sv;
|
|
|
|
m_Owner.OnSkillChange( this );
|
|
|
|
Mobile m = m_Owner.Owner;
|
|
|
|
if ( m != null )
|
|
m.OnSkillChange( SkillName, (double)oldBase / 10 );
|
|
}
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
|
|
public double Base
|
|
{
|
|
get
|
|
{
|
|
return ((double)m_Base / 10.0);
|
|
}
|
|
set
|
|
{
|
|
BaseFixedPoint = (int)(value * 10.0);
|
|
}
|
|
}
|
|
|
|
public int CapFixedPoint
|
|
{
|
|
get
|
|
{
|
|
return m_Cap;
|
|
}
|
|
set
|
|
{
|
|
if ( value < 0 )
|
|
value = 0;
|
|
else if ( value >= 0x10000 )
|
|
value = 0xFFFF;
|
|
|
|
ushort sv = (ushort)value;
|
|
|
|
if ( m_Cap != sv )
|
|
{
|
|
m_Cap = sv;
|
|
|
|
m_Owner.OnSkillChange( this );
|
|
}
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
|
|
public double Cap
|
|
{
|
|
get
|
|
{
|
|
return ((double)m_Cap / 10.0);
|
|
}
|
|
set
|
|
{
|
|
CapFixedPoint = (int)(value * 10.0);
|
|
}
|
|
}
|
|
|
|
private static bool m_UseStatMods;
|
|
|
|
public static bool UseStatMods{ get{ return m_UseStatMods; } set{ m_UseStatMods = value; } }
|
|
|
|
public int Fixed
|
|
{
|
|
get{ return (int)(Value * 10); }
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public double Value
|
|
{
|
|
get
|
|
{
|
|
//There has to be this distinction between the racial values and not to account for gaining skills and these skills aren't displayed nor Totaled up.
|
|
double value = this.NonRacialValue;
|
|
|
|
double raceBonus = m_Owner.Owner.RacialSkillBonus;
|
|
|
|
if( raceBonus > value )
|
|
value = raceBonus;
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public double NonRacialValue
|
|
{
|
|
get
|
|
{
|
|
double baseValue = Base;
|
|
double inv = 100.0 - baseValue;
|
|
|
|
if( inv < 0.0 ) inv = 0.0;
|
|
|
|
inv /= 100.0;
|
|
|
|
double statsOffset = ((m_UseStatMods ? m_Owner.Owner.Str : m_Owner.Owner.RawStr) * m_Info.StrScale) + ((m_UseStatMods ? m_Owner.Owner.Dex : m_Owner.Owner.RawDex) * m_Info.DexScale) + ((m_UseStatMods ? m_Owner.Owner.Int : m_Owner.Owner.RawInt) * m_Info.IntScale);
|
|
double statTotal = m_Info.StatTotal * inv;
|
|
|
|
statsOffset *= inv;
|
|
|
|
if( statsOffset > statTotal )
|
|
statsOffset = statTotal;
|
|
|
|
double value = baseValue + statsOffset;
|
|
|
|
m_Owner.Owner.ValidateSkillMods();
|
|
|
|
List<SkillMod> mods = m_Owner.Owner.SkillMods;
|
|
|
|
double bonusObey = 0.0, bonusNotObey = 0.0;
|
|
|
|
for( int i = 0; i < mods.Count; ++i )
|
|
{
|
|
SkillMod mod = mods[i];
|
|
|
|
if( mod.Skill == (SkillName)m_Info.SkillID )
|
|
{
|
|
if( mod.Relative )
|
|
{
|
|
if( mod.ObeyCap )
|
|
bonusObey += mod.Value;
|
|
else
|
|
bonusNotObey += mod.Value;
|
|
}
|
|
else
|
|
{
|
|
bonusObey = 0.0;
|
|
bonusNotObey = 0.0;
|
|
value = mod.Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
value += bonusNotObey;
|
|
|
|
if( value < Cap )
|
|
{
|
|
value += bonusObey;
|
|
|
|
if( value > Cap )
|
|
value = Cap;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
m_Owner.OnSkillChange( this );
|
|
}
|
|
}
|
|
|
|
public class SkillInfo
|
|
{
|
|
private int m_SkillID;
|
|
private string m_Name;
|
|
private string m_Title;
|
|
private double m_StrScale;
|
|
private double m_DexScale;
|
|
private double m_IntScale;
|
|
private double m_StatTotal;
|
|
private SkillUseCallback m_Callback;
|
|
private double m_StrGain;
|
|
private double m_DexGain;
|
|
private double m_IntGain;
|
|
private double m_GainFactor;
|
|
|
|
public SkillInfo( int skillID, string name, double strScale, double dexScale, double intScale, string title, SkillUseCallback callback, double strGain, double dexGain, double intGain, double gainFactor )
|
|
{
|
|
m_Name = name;
|
|
m_Title = title;
|
|
m_SkillID = skillID;
|
|
m_StrScale = strScale / 100.0;
|
|
m_DexScale = dexScale / 100.0;
|
|
m_IntScale = intScale / 100.0;
|
|
m_Callback = callback;
|
|
m_StrGain = strGain;
|
|
m_DexGain = dexGain;
|
|
m_IntGain = intGain;
|
|
m_GainFactor = gainFactor;
|
|
|
|
m_StatTotal = strScale + dexScale + intScale;
|
|
}
|
|
|
|
public SkillUseCallback Callback
|
|
{
|
|
get
|
|
{
|
|
return m_Callback;
|
|
}
|
|
set
|
|
{
|
|
m_Callback = value;
|
|
}
|
|
}
|
|
|
|
public int SkillID
|
|
{
|
|
get
|
|
{
|
|
return m_SkillID;
|
|
}
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
return m_Name;
|
|
}
|
|
set
|
|
{
|
|
m_Name = value;
|
|
}
|
|
}
|
|
|
|
public string Title
|
|
{
|
|
get
|
|
{
|
|
return m_Title;
|
|
}
|
|
set
|
|
{
|
|
m_Title = value;
|
|
}
|
|
}
|
|
|
|
public double StrScale
|
|
{
|
|
get
|
|
{
|
|
return m_StrScale;
|
|
}
|
|
set
|
|
{
|
|
m_StrScale = value;
|
|
}
|
|
}
|
|
|
|
public double DexScale
|
|
{
|
|
get
|
|
{
|
|
return m_DexScale;
|
|
}
|
|
set
|
|
{
|
|
m_DexScale = value;
|
|
}
|
|
}
|
|
|
|
public double IntScale
|
|
{
|
|
get
|
|
{
|
|
return m_IntScale;
|
|
}
|
|
set
|
|
{
|
|
m_IntScale = value;
|
|
}
|
|
}
|
|
|
|
public double StatTotal
|
|
{
|
|
get
|
|
{
|
|
return m_StatTotal;
|
|
}
|
|
set
|
|
{
|
|
m_StatTotal = value;
|
|
}
|
|
}
|
|
|
|
public double StrGain
|
|
{
|
|
get
|
|
{
|
|
return m_StrGain;
|
|
}
|
|
set
|
|
{
|
|
m_StrGain = value;
|
|
}
|
|
}
|
|
|
|
public double DexGain
|
|
{
|
|
get
|
|
{
|
|
return m_DexGain;
|
|
}
|
|
set
|
|
{
|
|
m_DexGain = value;
|
|
}
|
|
}
|
|
|
|
public double IntGain
|
|
{
|
|
get
|
|
{
|
|
return m_IntGain;
|
|
}
|
|
set
|
|
{
|
|
m_IntGain = value;
|
|
}
|
|
}
|
|
|
|
public double GainFactor
|
|
{
|
|
get
|
|
{
|
|
return m_GainFactor;
|
|
}
|
|
set
|
|
{
|
|
m_GainFactor = value;
|
|
}
|
|
}
|
|
|
|
private static SkillInfo[] m_Table = new SkillInfo[25]
|
|
{
|
|
new SkillInfo( 0, "Archery", 2.5, 7.5, 0.0, "Archer", null, 0.25, 0.75, 0.0, 1.0 ),
|
|
new SkillInfo( 1, "Bludgeoning", 9.0, 1.0, 0.0, "Bludgeoner", null, 0.9, 0.1, 0.0, 1.0 ),
|
|
new SkillInfo( 2, "Fencing", 4.5, 5.5, 0.0, "Fencer", null, 0.45, 0.55, 0.0, 1.0 ),
|
|
new SkillInfo( 3, "Swordsmanship", 7.5, 2.5, 0.0, "Swordsman", null, 0.75, 0.25, 0.0, 1.0 ),
|
|
new SkillInfo( 4, "Tactics", 2.0, 2.0, 2.0, "Tactician", null, 0.0, 0.0, 0.0, 1.0 ),
|
|
new SkillInfo( 5, "Parrying", 7.5, 2.5, 0.0, "Duelist", null, 0.75, 0.25, 0.0, 1.0 ),
|
|
new SkillInfo( 6, "Concentration", 0.0, 0.0, 10.0, "Concentrator", null, 0.0, 0.0, 1.0, 1.0 ),
|
|
new SkillInfo( 7, "Discordance", 0.0, 2.5, 2.5, "Demoralizer", null, 0.0, 0.25, 0.25, 1.0 ),
|
|
new SkillInfo( 8, "Dodging", 2.5, 7.5, 0.0, "Lightfoot", null, 0.0, 0.0, 0.0, 1.0 ),
|
|
new SkillInfo( 9, "Hand-to-Hand", 9.0, 1.0, 0.0, "Pugilist", null, 0.9, 0.1, 0.0, 1.0 ),
|
|
new SkillInfo( 10, "Healing", 6.0, 6.0, 8.0, "Healer", null, 0.6, 0.6, 0.8, 1.0 ),
|
|
new SkillInfo( 11, "Hiding", 0.0, 10.0, 0.0, "Sneak", null, 0.0, 0.8, 0.2, 1.0 ),
|
|
new SkillInfo( 12, "Lockpicking", 0.0, 25.0, 0.0, "Lockpicker", null, 0.0, 2.0, 0.0, 1.0 ),
|
|
new SkillInfo( 13, "Magery", 0.0, 0.0, 15.0, "Mage", null, 0.0, 0.0, 1.5, 1.0 ),
|
|
new SkillInfo( 14, "Resisting Spells", 0.0, 0.0, 10.0, "Warder", null, 0.25, 0.25, 0.5, 1.0 ),
|
|
new SkillInfo( 15, "Meditation", 0.0, 0.0, 10.0, "Meditator", null, 0.0, 0.0, 0.0, 1.0 ),
|
|
new SkillInfo( 16, "Musicianship", 0.0, 4.5, 0.5, "Bard", null, 0.0, 0.8, 0.2, 1.0 ),
|
|
new SkillInfo( 17, "Peacemaking", 0.0, 4.5, 0.5, "Pacifier", null, 0.0, 0.0, 0.0, 1.0 ),
|
|
new SkillInfo( 18, "Poisoning", 0.0, 4.0, 16.0, "Assassin", null, 0.0, 0.4, 1.6, 1.0 ),
|
|
new SkillInfo( 19, "Provocation", 0.0, 4.5, 0.5, "Rouser", null, 0.0, 0.45, 0.05, 1.0 ),
|
|
new SkillInfo( 20, "Remove Trap", 0.0, 5.0, 0.0, "Trespasser", null, 0.0, 0.0, 0.0, 1.0 ),
|
|
new SkillInfo( 21, "Searching", 0.0, 0.0, 5.0, "Scout", null, 0.0, 0.4, 0.6, 1.0 ),
|
|
new SkillInfo( 22, "Stealing", 0.0, 10.0, 0.0, "Thief", null, 0.0, 1.0, 0.0, 1.0 ),
|
|
new SkillInfo( 23, "Stealth", 0.0, 5.0, 0.0, "Rogue", null, 0.0, 0.0, 0.0, 1.0 ),
|
|
new SkillInfo( 24, "Tracking", 0.0, 12.5, 12.5, "Ranger", null, 0.0, 1.25, 1.25, 1.0 )
|
|
};
|
|
|
|
public static SkillInfo[] Table
|
|
{
|
|
get
|
|
{
|
|
return m_Table;
|
|
}
|
|
set
|
|
{
|
|
m_Table = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
[PropertyObject]
|
|
public class Skills
|
|
{
|
|
private Mobile m_Owner;
|
|
private Skill[] m_Skills;
|
|
private int m_Total, m_Cap;
|
|
private Skill m_Highest;
|
|
|
|
#region Skill Getters & Setters
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Archery{ get{ return this[SkillName.Archery]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Bludgeoning{ get{ return this[SkillName.Bludgeoning]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Fencing{ get{ return this[SkillName.Fencing]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Swords{ get{ return this[SkillName.Swords]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Tactics{ get{ return this[SkillName.Tactics]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Parry{ get{ return this[SkillName.Parry]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Concentration{ get{ return this[SkillName.Concentration]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Discordance{ get{ return this[SkillName.Discordance]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Dodging{ get{ return this[SkillName.Dodging]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill HandToHand{ get{ return this[SkillName.HandToHand]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Healing{ get{ return this[SkillName.Healing]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Hiding{ get{ return this[SkillName.Hiding]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Lockpicking{ get{ return this[SkillName.Lockpicking]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Magery{ get{ return this[SkillName.Magery]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill MagicResist{ get{ return this[SkillName.MagicResist]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Meditation{ get{ return this[SkillName.Meditation]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Musicianship{ get{ return this[SkillName.Musicianship]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Peacemaking{ get{ return this[SkillName.Peacemaking]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Poisoning{ get{ return this[SkillName.Poisoning]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Provocation{ get{ return this[SkillName.Provocation]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill RemoveTrap{ get{ return this[SkillName.RemoveTrap]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Searching{ get{ return this[SkillName.Searching]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Stealing{ get{ return this[SkillName.Stealing]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Stealth{ get{ return this[SkillName.Stealth]; } set{} }
|
|
|
|
[CommandProperty( AccessLevel.Counselor )]
|
|
public Skill Tracking{ get{ return this[SkillName.Tracking]; } set{} }
|
|
|
|
#endregion
|
|
|
|
[CommandProperty( AccessLevel.Counselor, AccessLevel.GameMaster )]
|
|
public int Cap
|
|
{
|
|
get{ return m_Cap; }
|
|
set{ m_Cap = value; }
|
|
}
|
|
|
|
public int Total
|
|
{
|
|
get{ return m_Total; }
|
|
set{ m_Total = value; }
|
|
}
|
|
|
|
public Mobile Owner
|
|
{
|
|
get{ return m_Owner; }
|
|
}
|
|
|
|
public int Length
|
|
{
|
|
get{ return m_Skills.Length; }
|
|
}
|
|
|
|
public Skill this[SkillName name]
|
|
{
|
|
get{ return this[(int)name]; }
|
|
}
|
|
|
|
public Skill this[int skillID]
|
|
{
|
|
get
|
|
{
|
|
if ( skillID < 0 || skillID >= m_Skills.Length )
|
|
return null;
|
|
|
|
Skill sk = m_Skills[skillID];
|
|
|
|
if ( sk == null )
|
|
m_Skills[skillID] = sk = new Skill( this, SkillInfo.Table[skillID], 0, 1000, SkillLock.Up );
|
|
|
|
return sk;
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return "...";
|
|
}
|
|
|
|
public static bool UseSkill( Mobile from, SkillName name )
|
|
{
|
|
return UseSkill( from, (int)name );
|
|
}
|
|
|
|
public static bool UseSkill( Mobile from, int skillID )
|
|
{
|
|
if ( !from.CheckAlive() )
|
|
return false;
|
|
else if ( !from.Region.OnSkillUse( from, skillID ) )
|
|
return false;
|
|
else if ( !from.AllowSkillUse( (SkillName)skillID ) )
|
|
return false;
|
|
|
|
if ( skillID >= 0 && skillID < SkillInfo.Table.Length )
|
|
{
|
|
SkillInfo info = SkillInfo.Table[skillID];
|
|
|
|
if ( info.Callback != null )
|
|
{
|
|
if ( from.NextSkillTime <= DateTime.Now && from.Spell == null )
|
|
{
|
|
from.DisruptiveAction();
|
|
|
|
from.NextSkillTime = DateTime.Now + info.Callback( from );
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
from.SendSkillMessage();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
from.SendLocalizedMessage( 500014 ); // That skill cannot be used directly.
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public Skill Highest
|
|
{
|
|
get
|
|
{
|
|
if ( m_Highest == null )
|
|
{
|
|
Skill highest = null;
|
|
int value = int.MinValue;
|
|
|
|
for ( int i = 0; i < m_Skills.Length; ++i )
|
|
{
|
|
Skill sk = m_Skills[i];
|
|
|
|
if ( sk != null && sk.BaseFixedPoint > value )
|
|
{
|
|
value = sk.BaseFixedPoint;
|
|
highest = sk;
|
|
}
|
|
}
|
|
|
|
if ( highest == null && m_Skills.Length > 0 )
|
|
highest = this[0];
|
|
|
|
m_Highest = highest;
|
|
}
|
|
|
|
return m_Highest;
|
|
}
|
|
}
|
|
|
|
public void Serialize( GenericWriter writer )
|
|
{
|
|
m_Total = 0;
|
|
|
|
writer.Write( (int) 3 ); // version
|
|
|
|
writer.Write( (int) m_Cap );
|
|
writer.Write( (int) m_Skills.Length );
|
|
|
|
for ( int i = 0; i < m_Skills.Length; ++i )
|
|
{
|
|
Skill sk = m_Skills[i];
|
|
|
|
if ( sk == null )
|
|
{
|
|
writer.Write( (byte) 0xFF );
|
|
}
|
|
else
|
|
{
|
|
sk.Serialize( writer );
|
|
m_Total += sk.BaseFixedPoint;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Skills( Mobile owner )
|
|
{
|
|
m_Owner = owner;
|
|
m_Cap = 7000;
|
|
|
|
SkillInfo[] info = SkillInfo.Table;
|
|
|
|
m_Skills = new Skill[info.Length];
|
|
|
|
//for ( int i = 0; i < info.Length; ++i )
|
|
// m_Skills[i] = new Skill( this, info[i], 0, 1000, SkillLock.Up );
|
|
}
|
|
|
|
public Skills( Mobile owner, GenericReader reader )
|
|
{
|
|
m_Owner = owner;
|
|
|
|
int version = reader.ReadInt();
|
|
|
|
switch ( version )
|
|
{
|
|
case 3:
|
|
case 2:
|
|
{
|
|
m_Cap = reader.ReadInt();
|
|
|
|
goto case 1;
|
|
}
|
|
case 1:
|
|
{
|
|
if ( version < 2 )
|
|
m_Cap = 7000;
|
|
|
|
if ( version < 3 )
|
|
/*m_Total =*/ reader.ReadInt();
|
|
|
|
SkillInfo[] info = SkillInfo.Table;
|
|
|
|
m_Skills = new Skill[info.Length];
|
|
|
|
int count = reader.ReadInt();
|
|
|
|
for ( int i = 0; i < count; ++i )
|
|
{
|
|
if ( i < info.Length )
|
|
{
|
|
Skill sk = new Skill( this, info[i], reader );
|
|
|
|
if ( sk.BaseFixedPoint != 0 || sk.CapFixedPoint != 1000 || sk.Lock != SkillLock.Up )
|
|
{
|
|
m_Skills[i] = sk;
|
|
m_Total += sk.BaseFixedPoint;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
new Skill( this, null, reader );
|
|
}
|
|
}
|
|
|
|
//for ( int i = count; i < info.Length; ++i )
|
|
// m_Skills[i] = new Skill( this, info[i], 0, 1000, SkillLock.Up );
|
|
|
|
break;
|
|
}
|
|
case 0:
|
|
{
|
|
reader.ReadInt();
|
|
|
|
goto case 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnSkillChange( Skill skill )
|
|
{
|
|
if ( skill == m_Highest ) // could be downgrading the skill, force a recalc
|
|
m_Highest = null;
|
|
else if ( m_Highest != null && skill.BaseFixedPoint > m_Highest.BaseFixedPoint )
|
|
m_Highest = skill;
|
|
|
|
m_Owner.OnSkillInvalidated( skill );
|
|
|
|
NetState ns = m_Owner.NetState;
|
|
|
|
if ( ns != null )
|
|
ns.Send( new SkillChange( skill ) );
|
|
}
|
|
}
|
|
} |