/// <summary> /// Gets mobile name from name property. /// </summary> /// <param name="nameProperty">Name property.</param> /// <returns>Mobile name.</returns> public static string GetMobileName(QueryPropertiesProperty nameProperty) { // Get item cliloc int cliloc = 0; string name = null; if (UltimaItemGenerator.IsStackable(nameProperty.Cliloc)) { // Get name from stackable cliloc UltimaClilocArgumentParser nameArguments = new UltimaClilocArgumentParser(nameProperty.Arguments); int nameCliloc = nameArguments.GetCliloc(0); if (nameCliloc > 0) { cliloc = nameCliloc; } else { name = nameArguments[0]; } } else { // Get name from name cliloc if (nameProperty.Cliloc == 1050045) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser(nameProperty.Arguments); if (arguments.Length > 2) { name = arguments[1]; } } else { cliloc = nameProperty.Cliloc; } } UltimaStringCollection clilocs = Globals.Instance.Clilocs; if (name == null) { if (clilocs != null) { name = clilocs.GetString(cliloc); } if (String.IsNullOrEmpty(name)) { name = cliloc.ToString(); } } return(name); }
private int _MaxPropertyValue; // Max global property value #endregion #region Methods /// <summary> /// Constructs a new instance of UltimaLootAnalyzer. /// </summary> /// <param name="names">List of the mobile names to analyze.</param> public UltimaLootAnalyzer(ObservableCollection <UltimaPacket> packets, List <string> names) { _Names = names; _CorpseCount = 0; _HueCounter = new UltimaEnumPropertyCounter(); _GoldCounter = new UltimaSimpleCounter(); _InstrumentCounters = new List <UltimaSimpleCounter>(); _EquipmentCounters = new List <UltimaSimpleCounter>(); UltimaItemDefinitions itemDefinitions = Globals.Instance.ItemDefinitions; if (itemDefinitions == null) { throw new Exception("Item definitions not initialized"); } UltimaItemProperties propertyDefinitions = Globals.Instance.ItemProperties; if (propertyDefinitions == null) { throw new Exception("Item property definitions not initialized"); } // Initialize group UltimaItemDefinitionGroup goldGroup = null; UltimaItemDefinitionGroup instrumentsGroup = null; _Groups = new Dictionary <UltimaItemDefinitionGroup, UltimaSimpleCounter>(); _DefaultGroup = new UltimaDefaultLootGroup(); _PropertiesPerItem = new List <UltimaSimpleCounter>(); _Properties = new Dictionary <int, UltimaPropertyCounter>(); foreach (UltimaItemDefinitionGroup group in itemDefinitions.Groups) { if (group.Analyze) { _Groups.Add(group, new UltimaSimpleCounter()); } if (String.Equals(group.Name, "Gold", StringComparison.InvariantCultureIgnoreCase)) { goldGroup = group; } else if (String.Equals(group.Name, "Instruments", StringComparison.InvariantCultureIgnoreCase)) { instrumentsGroup = group; } } // Analyze packets Dictionary <uint, MobileIncommingPacket> mobiles = new Dictionary <uint, MobileIncommingPacket>(); Dictionary <uint, uint> mobilesToCorpses = new Dictionary <uint, uint>(); Dictionary <uint, ContainerContentPacket> corpsesToContainers = new Dictionary <uint, ContainerContentPacket>(); Dictionary <uint, QueryPropertiesResponsePacket> itemsToProperties = new Dictionary <uint, QueryPropertiesResponsePacket>(); foreach (UltimaPacket packet in packets) { if (packet is MobileIncommingPacket) { MobileIncommingPacket mobile = (MobileIncommingPacket)packet; if (!mobiles.ContainsKey(mobile.Serial)) { mobiles.Add(mobile.Serial, mobile); } } else if (packet is DeathAnimationPacket) { DeathAnimationPacket deathAnimation = (DeathAnimationPacket)packet; if (!mobilesToCorpses.ContainsKey(deathAnimation.Serial)) { mobilesToCorpses.Add(deathAnimation.Serial, deathAnimation.Corpse); } } else if (packet is ContainerContentPacket) { ContainerContentPacket containerContent = (ContainerContentPacket)packet; if (!corpsesToContainers.ContainsKey(containerContent.Serial)) { corpsesToContainers.Add(containerContent.Serial, containerContent); } } else if (packet is QueryPropertiesResponsePacket) { QueryPropertiesResponsePacket properties = (QueryPropertiesResponsePacket)packet; if (!itemsToProperties.ContainsKey(properties.Serial)) { itemsToProperties.Add(properties.Serial, properties); } } } Dictionary <ContainerContentPacket, List <ItemStatistics> > validCorpses = new Dictionary <ContainerContentPacket, List <ItemStatistics> >(); _MinPropertyCount = int.MaxValue; _MaxPropertyCount = int.MinValue; _MinPropertyValue = int.MaxValue; _MaxPropertyValue = int.MinValue; foreach (KeyValuePair <uint, uint> kvp in mobilesToCorpses) { MobileIncommingPacket mobile = null; ContainerContentPacket corpseContainer = null; ContainerContentPacket container = null; QueryPropertiesResponsePacket mobileProperties = null; if (!mobiles.TryGetValue(kvp.Key, out mobile)) { continue; } if (!itemsToProperties.TryGetValue(kvp.Key, out mobileProperties) || mobileProperties.Properties.Count == 0) { continue; } if (!corpsesToContainers.TryGetValue(kvp.Value, out corpseContainer)) { continue; } if (corpseContainer.Items.Count > 0) { ContainerItem corpse = corpseContainer.Items[0]; if (!corpsesToContainers.TryGetValue(corpse.Serial, out container)) { continue; } } else { continue; } string mobileName = GetMobileName(mobileProperties.Properties[0]); if (names.Contains(mobileName)) { // Analyze corpse StartAnalyzingCorpse(); List <ItemStatistics> validItems = new List <ItemStatistics>(); int equipmentCount = 0; int instrumentCount = 0; bool foundGold = false; _HueCounter.Gotcha(mobile.Hue); _CorpseCount += 1; Trace.WriteLine(""); Trace.WriteLine("Found corpse with " + container.Items.Count); foreach (ContainerItem item in container.Items) { QueryPropertiesResponsePacket properties = null; UltimaItemDefinition itemDefinition = null; UltimaArmorDefinition armorDefinition = null; bool analyzed = false; if (itemDefinitions.Items.ContainsKey(item.ItemID)) { itemDefinition = itemDefinitions.Items[item.ItemID]; armorDefinition = itemDefinition as UltimaArmorDefinition; } if (itemsToProperties.ContainsKey(item.Serial)) { properties = itemsToProperties[item.Serial]; } string name = GetItemName(properties.Properties[0]); // EA always generates gold last if (!foundGold) { if (itemDefinition != null) { UltimaItemDefinitionGroup group = itemDefinition.Parent; while (group.Parent != null) { group = group.Parent; } if (properties != null) { QueryPropertiesProperty nameProperty = properties.Properties[0]; // Treat stackable items as special if (!UltimaItemGenerator.IsStackable(nameProperty.Cliloc) && !UltimaItemGenerator.IsString(nameProperty.Cliloc) && !UltimaItemGenerator.IsSpecial(item.ItemID, nameProperty.Cliloc)) { if (_Groups.ContainsKey(group)) { _Groups[group].Gotcha(); analyzed = true; int propertiesPerItem = 0; int minPropertyValue = int.MaxValue; int maxPropertyValue = int.MinValue; bool isValidMinMax = false; bool hasSpecialDamage = false; foreach (QueryPropertiesProperty property in properties.Properties) { string propertyName = Globals.Instance.Clilocs.GetString(property.Cliloc); if (UltimaItemGenerator.IsDamage(property.Cliloc)) { if (property.Cliloc != 1060403) { if (!hasSpecialDamage) { propertiesPerItem += 1; } hasSpecialDamage = true; } } else if (propertyDefinitions.Properties.ContainsKey(property.Cliloc)) { UltimaItemProperty propertyDefinition = propertyDefinitions.Properties[property.Cliloc]; if (propertyDefinition.IsRunic) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser(property.Arguments); bool ignore = false; if (arguments.Length > 0) { int integer = 0; if (arguments.TryGetInteger(0, out integer)) { if (armorDefinition != null) { ignore = CheckIgnoreProperty(armorDefinition, propertyDefinition, ref integer); } if (!ignore) { GetPropertyCounter(property.Cliloc, 1).Gotcha(integer); if (propertyDefinition.Max > propertyDefinition.Min) { int percentage = (integer - propertyDefinition.Min) * 100 / (propertyDefinition.Max - propertyDefinition.Min); if (percentage > maxPropertyValue) { maxPropertyValue = percentage; } if (percentage > _MaxPropertyValue) { _MaxPropertyValue = percentage; } if (percentage < minPropertyValue) { minPropertyValue = percentage; } if (percentage < _MinPropertyValue) { _MinPropertyValue = percentage; } isValidMinMax = true; } } } else { GetPropertyCounter(property.Cliloc, 2).Gotcha(arguments[0]); } } else { GetPropertyCounter(property.Cliloc).Gotcha(null); } if (!ignore) { propertiesPerItem++; } } } } // Count number of properties UltimaSimpleCounter counter = null; while (propertiesPerItem >= _PropertiesPerItem.Count) { _PropertiesPerItem.Add(counter = new UltimaSimpleCounter()); } counter = _PropertiesPerItem[propertiesPerItem]; counter.StartAnalyzing(); counter.Gotcha(); counter.EndAnalyzing(); if (propertiesPerItem < _MinPropertyCount) { _MinPropertyCount = propertiesPerItem; } if (propertiesPerItem > _MaxPropertyCount) { _MaxPropertyCount = propertiesPerItem; } equipmentCount += 1; if (isValidMinMax) { validItems.Add(new ItemStatistics(item, propertiesPerItem, minPropertyValue, maxPropertyValue)); } else { validItems.Add(new ItemStatistics(item, propertiesPerItem)); } } } } } else { Trace.WriteLine("Cannot find item definition for:" + String.Format("0x{0:X}", item.ItemID) + "," + name); } // Check if special item if (itemDefinition != null && !analyzed) { UltimaItemDefinitionGroup group = itemDefinition.Parent; if (group == goldGroup) { _GoldCounter.Gotcha(item.Amount); analyzed = true; foundGold = true; } else if (group == instrumentsGroup) { analyzed = true; } } } if (!analyzed) { _DefaultGroup.AnalyzeItem(item.Serial, item.ItemID, item.Hue, item.Amount, properties); } } Trace.WriteLine(equipmentCount); // Count equipment UltimaSimpleCounter equipmentCounter = null; while (equipmentCount >= _EquipmentCounters.Count) { _EquipmentCounters.Add(equipmentCounter = new UltimaSimpleCounter()); } equipmentCounter = _EquipmentCounters[equipmentCount]; equipmentCounter.StartAnalyzing(); equipmentCounter.Gotcha(); equipmentCounter.EndAnalyzing(); // Count instruments UltimaSimpleCounter instrumentCounter = null; while (instrumentCount >= _InstrumentCounters.Count) { _InstrumentCounters.Add(instrumentCounter = new UltimaSimpleCounter()); } instrumentCounter = _InstrumentCounters[instrumentCount]; instrumentCounter.StartAnalyzing(); instrumentCounter.Gotcha(); instrumentCounter.EndAnalyzing(); if (validItems.Count > 0) { validCorpses.Add(container, validItems); } // Count corpses EndAnalyzingCorpse(); } } // Analyze items with max properties to determine property probabilities _MinPropertyCounts = new List <int>(); _MaxPropertyCounts = new List <int>(); _MinPropertyValues = new List <int>(); _MaxPropertyValues = new List <int>(); _ValidCorpseCount = 0; foreach (KeyValuePair <ContainerContentPacket, List <ItemStatistics> > kvp in validCorpses) { // Only ones with max items are valid if (kvp.Value.Count == _EquipmentCounters.Count - 1) { bool isValidMinMax = true; foreach (ItemStatistics item in kvp.Value) { if (!item.IsValidMinMax) { isValidMinMax = false; break; } } kvp.Value.Sort(SortByCount); if (_MinPropertyCounts.Count == 0) { foreach (ItemStatistics item in kvp.Value) { _MinPropertyCounts.Add(item.PropertyCount); } } else { for (int i = 0; i < kvp.Value.Count; i++) { int count = kvp.Value[i].PropertyCount; if (count < _MinPropertyCounts[i]) { _MinPropertyCounts[i] = count; } } } if (_MaxPropertyCounts.Count == 0) { foreach (ItemStatistics item in kvp.Value) { _MaxPropertyCounts.Add(item.PropertyCount); } } else { for (int i = 0; i < kvp.Value.Count; i++) { int count = kvp.Value[i].PropertyCount; if (count > _MaxPropertyCounts[i]) { _MaxPropertyCounts[i] = count; } } } if (isValidMinMax) { kvp.Value.Sort(SortByMin); if (_MinPropertyValues.Count == 0) { foreach (ItemStatistics item in kvp.Value) { _MinPropertyValues.Add(item.MinPropertyValue); } } else { for (int i = 0; i < kvp.Value.Count; i++) { int min = kvp.Value[i].MinPropertyValue; if (min < _MinPropertyValues[i]) { _MinPropertyValues[i] = min; } } } kvp.Value.Sort(SortByMax); if (_MaxPropertyValues.Count == 0) { foreach (ItemStatistics item in kvp.Value) { _MaxPropertyValues.Add(item.MaxPropertyValue); } } else { for (int i = 0; i < kvp.Value.Count; i++) { int max = kvp.Value[i].MaxPropertyValue; if (max > _MaxPropertyValues[i]) { _MaxPropertyValues[i] = max; } } } } _ValidCorpseCount += 1; } } }
/// <summary> /// Gets mobile name from name property. /// </summary> /// <param name="nameProperty">Name property.</param> /// <returns>Mobile name.</returns> public static string GetMobileName( QueryPropertiesProperty nameProperty ) { // Get item cliloc int cliloc = 0; string name = null; if ( UltimaItemGenerator.IsStackable( nameProperty.Cliloc ) ) { // Get name from stackable cliloc UltimaClilocArgumentParser nameArguments = new UltimaClilocArgumentParser( nameProperty.Arguments ); int nameCliloc = nameArguments.GetCliloc( 0 ); if ( nameCliloc > 0 ) cliloc = nameCliloc; else name = nameArguments[ 0 ]; } else { // Get name from name cliloc if ( nameProperty.Cliloc == 1050045 ) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser( nameProperty.Arguments ); if ( arguments.Length > 2 ) name = arguments[ 1 ]; } else cliloc = nameProperty.Cliloc; } UltimaStringCollection clilocs = Globals.Instance.Clilocs; if ( name == null ) { if ( clilocs != null ) name = clilocs.GetString( cliloc ); if ( String.IsNullOrEmpty( name ) ) name = cliloc.ToString(); } return name; }
private int _ValidCorpseCount; // Number of corpses with max equipment count #endregion Fields #region Constructors /// <summary> /// Constructs a new instance of UltimaLootAnalyzer. /// </summary> /// <param name="names">List of the mobile names to analyze.</param> public UltimaLootAnalyzer( ObservableCollection<UltimaPacket> packets, List<string> names ) { _Names = names; _CorpseCount = 0; _HueCounter = new UltimaEnumPropertyCounter(); _GoldCounter = new UltimaSimpleCounter(); _InstrumentCounters = new List<UltimaSimpleCounter>(); _EquipmentCounters = new List<UltimaSimpleCounter>(); UltimaItemDefinitions itemDefinitions = Globals.Instance.ItemDefinitions; if ( itemDefinitions == null ) throw new Exception( "Item definitions not initialized" ); UltimaItemProperties propertyDefinitions = Globals.Instance.ItemProperties; if ( propertyDefinitions == null ) throw new Exception( "Item property definitions not initialized" ); // Initialize group UltimaItemDefinitionGroup goldGroup = null; UltimaItemDefinitionGroup instrumentsGroup = null; _Groups = new Dictionary<UltimaItemDefinitionGroup, UltimaSimpleCounter>(); _DefaultGroup = new UltimaDefaultLootGroup(); _PropertiesPerItem = new List<UltimaSimpleCounter>(); _Properties = new Dictionary<int, UltimaPropertyCounter>(); foreach ( UltimaItemDefinitionGroup group in itemDefinitions.Groups ) { if ( group.Analyze ) _Groups.Add( group, new UltimaSimpleCounter() ); if ( String.Equals( group.Name, "Gold", StringComparison.InvariantCultureIgnoreCase ) ) goldGroup = group; else if ( String.Equals( group.Name, "Instruments", StringComparison.InvariantCultureIgnoreCase ) ) instrumentsGroup = group; } // Analyze packets Dictionary<uint, MobileIncommingPacket> mobiles = new Dictionary<uint, MobileIncommingPacket>(); Dictionary<uint, uint> mobilesToCorpses = new Dictionary<uint, uint>(); Dictionary<uint, ContainerContentPacket> corpsesToContainers = new Dictionary<uint, ContainerContentPacket>(); Dictionary<uint, QueryPropertiesResponsePacket> itemsToProperties = new Dictionary<uint, QueryPropertiesResponsePacket>(); foreach ( UltimaPacket packet in packets ) { if ( packet is MobileIncommingPacket ) { MobileIncommingPacket mobile = (MobileIncommingPacket) packet; if ( !mobiles.ContainsKey( mobile.Serial ) ) mobiles.Add( mobile.Serial, mobile ); } else if ( packet is DeathAnimationPacket ) { DeathAnimationPacket deathAnimation = (DeathAnimationPacket) packet; if ( !mobilesToCorpses.ContainsKey( deathAnimation.Serial ) ) mobilesToCorpses.Add( deathAnimation.Serial, deathAnimation.Corpse ); } else if ( packet is ContainerContentPacket ) { ContainerContentPacket containerContent = (ContainerContentPacket) packet; if ( !corpsesToContainers.ContainsKey( containerContent.Serial ) ) corpsesToContainers.Add( containerContent.Serial, containerContent ); } else if ( packet is QueryPropertiesResponsePacket ) { QueryPropertiesResponsePacket properties = (QueryPropertiesResponsePacket) packet; if ( !itemsToProperties.ContainsKey( properties.Serial ) ) itemsToProperties.Add( properties.Serial, properties ); } } Dictionary<ContainerContentPacket, List<ItemStatistics>> validCorpses = new Dictionary<ContainerContentPacket, List<ItemStatistics>>(); _MinPropertyCount = int.MaxValue; _MaxPropertyCount = int.MinValue; _MinPropertyValue = int.MaxValue; _MaxPropertyValue = int.MinValue; foreach ( KeyValuePair<uint, uint> kvp in mobilesToCorpses ) { MobileIncommingPacket mobile = null; ContainerContentPacket corpseContainer = null; ContainerContentPacket container = null; QueryPropertiesResponsePacket mobileProperties = null; if ( !mobiles.TryGetValue( kvp.Key, out mobile ) ) continue; if ( !itemsToProperties.TryGetValue( kvp.Key, out mobileProperties ) || mobileProperties.Properties.Count == 0 ) continue; if ( !corpsesToContainers.TryGetValue( kvp.Value, out corpseContainer ) ) continue; if ( corpseContainer.Items.Count > 0 ) { ContainerItem corpse = corpseContainer.Items[ 0 ]; if ( !corpsesToContainers.TryGetValue( corpse.Serial, out container ) ) continue; } else continue; string mobileName = GetMobileName( mobileProperties.Properties[ 0 ] ); if ( names.Contains( mobileName ) ) { // Analyze corpse StartAnalyzingCorpse(); List<ItemStatistics> validItems = new List<ItemStatistics>(); int equipmentCount = 0; int instrumentCount = 0; bool foundGold = false; _HueCounter.Gotcha( mobile.Hue ); _CorpseCount += 1; Trace.WriteLine( "" ); Trace.WriteLine( "Found corpse with " + container.Items.Count ); foreach ( ContainerItem item in container.Items ) { QueryPropertiesResponsePacket properties = null; UltimaItemDefinition itemDefinition = null; UltimaArmorDefinition armorDefinition = null; bool analyzed = false; if ( itemDefinitions.Items.ContainsKey( item.ItemID ) ) { itemDefinition = itemDefinitions.Items[ item.ItemID ]; armorDefinition = itemDefinition as UltimaArmorDefinition; } if ( itemsToProperties.ContainsKey( item.Serial ) ) properties = itemsToProperties[ item.Serial ]; string name = GetItemName( properties.Properties[ 0 ] ); // EA always generates gold last if ( !foundGold ) { if ( itemDefinition != null ) { UltimaItemDefinitionGroup group = itemDefinition.Parent; while ( group.Parent != null ) group = group.Parent; if ( properties != null ) { QueryPropertiesProperty nameProperty = properties.Properties[ 0 ]; // Treat stackable items as special if ( !UltimaItemGenerator.IsStackable( nameProperty.Cliloc ) && !UltimaItemGenerator.IsString( nameProperty.Cliloc ) && !UltimaItemGenerator.IsSpecial( item.ItemID, nameProperty.Cliloc ) ) { if ( _Groups.ContainsKey( group ) ) { _Groups[ group ].Gotcha(); analyzed = true; int propertiesPerItem = 0; int minPropertyValue = int.MaxValue; int maxPropertyValue = int.MinValue; bool isValidMinMax = false; bool hasSpecialDamage = false; foreach ( QueryPropertiesProperty property in properties.Properties ) { string propertyName = Globals.Instance.Clilocs.GetString( property.Cliloc ); if ( UltimaItemGenerator.IsDamage( property.Cliloc ) ) { if ( property.Cliloc != 1060403 ) { if ( !hasSpecialDamage ) propertiesPerItem += 1; hasSpecialDamage = true; } } else if ( propertyDefinitions.Properties.ContainsKey( property.Cliloc ) ) { UltimaItemProperty propertyDefinition = propertyDefinitions.Properties[ property.Cliloc ]; if ( propertyDefinition.IsRunic ) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser( property.Arguments ); bool ignore = false; if ( arguments.Length > 0 ) { int integer = 0; if ( arguments.TryGetInteger( 0, out integer ) ) { if ( armorDefinition != null ) ignore = CheckIgnoreProperty( armorDefinition, propertyDefinition, ref integer ); if ( !ignore ) { GetPropertyCounter( property.Cliloc, 1 ).Gotcha( integer ); if ( propertyDefinition.Max > propertyDefinition.Min ) { int percentage = ( integer - propertyDefinition.Min ) * 100 / ( propertyDefinition.Max - propertyDefinition.Min ); if ( percentage > maxPropertyValue ) maxPropertyValue = percentage; if ( percentage > _MaxPropertyValue ) _MaxPropertyValue = percentage; if ( percentage < minPropertyValue ) minPropertyValue = percentage; if ( percentage < _MinPropertyValue ) _MinPropertyValue = percentage; isValidMinMax = true; } } } else GetPropertyCounter( property.Cliloc, 2 ).Gotcha( arguments[ 0 ] ); } else GetPropertyCounter( property.Cliloc ).Gotcha( null ); if ( !ignore ) propertiesPerItem++; } } } // Count number of properties UltimaSimpleCounter counter = null; while ( propertiesPerItem >= _PropertiesPerItem.Count ) _PropertiesPerItem.Add( counter = new UltimaSimpleCounter() ); counter = _PropertiesPerItem[ propertiesPerItem ]; counter.StartAnalyzing(); counter.Gotcha(); counter.EndAnalyzing(); if ( propertiesPerItem < _MinPropertyCount ) _MinPropertyCount = propertiesPerItem; if ( propertiesPerItem > _MaxPropertyCount ) _MaxPropertyCount = propertiesPerItem; equipmentCount += 1; if ( isValidMinMax ) validItems.Add( new ItemStatistics( item, propertiesPerItem, minPropertyValue, maxPropertyValue ) ); else validItems.Add( new ItemStatistics( item, propertiesPerItem ) ); } } } } else Trace.WriteLine( "Cannot find item definition for:" + String.Format( "0x{0:X}", item.ItemID ) + "," + name ); // Check if special item if ( itemDefinition != null && !analyzed ) { UltimaItemDefinitionGroup group = itemDefinition.Parent; if ( group == goldGroup ) { _GoldCounter.Gotcha( item.Amount ); analyzed = true; foundGold = true; } else if ( group == instrumentsGroup ) { analyzed = true; } } } if ( !analyzed ) _DefaultGroup.AnalyzeItem( item.Serial, item.ItemID, item.Hue, item.Amount, properties ); } Trace.WriteLine( equipmentCount ); // Count equipment UltimaSimpleCounter equipmentCounter = null; while ( equipmentCount >= _EquipmentCounters.Count ) _EquipmentCounters.Add( equipmentCounter = new UltimaSimpleCounter() ); equipmentCounter = _EquipmentCounters[ equipmentCount ]; equipmentCounter.StartAnalyzing(); equipmentCounter.Gotcha(); equipmentCounter.EndAnalyzing(); // Count instruments UltimaSimpleCounter instrumentCounter = null; while ( instrumentCount >= _InstrumentCounters.Count ) _InstrumentCounters.Add( instrumentCounter = new UltimaSimpleCounter() ); instrumentCounter = _InstrumentCounters[ instrumentCount ]; instrumentCounter.StartAnalyzing(); instrumentCounter.Gotcha(); instrumentCounter.EndAnalyzing(); if ( validItems.Count > 0 ) validCorpses.Add( container, validItems ); // Count corpses EndAnalyzingCorpse(); } } // Analyze items with max properties to determine property probabilities _MinPropertyCounts = new List<int>(); _MaxPropertyCounts = new List<int>(); _MinPropertyValues = new List<int>(); _MaxPropertyValues = new List<int>(); _ValidCorpseCount = 0; foreach ( KeyValuePair<ContainerContentPacket, List<ItemStatistics>> kvp in validCorpses ) { // Only ones with max items are valid if ( kvp.Value.Count == _EquipmentCounters.Count - 1 ) { bool isValidMinMax = true; foreach ( ItemStatistics item in kvp.Value ) { if ( !item.IsValidMinMax ) { isValidMinMax = false; break; } } kvp.Value.Sort( SortByCount ); if ( _MinPropertyCounts.Count == 0 ) { foreach ( ItemStatistics item in kvp.Value ) _MinPropertyCounts.Add( item.PropertyCount ); } else { for ( int i = 0; i < kvp.Value.Count; i++ ) { int count = kvp.Value[ i ].PropertyCount; if ( count < _MinPropertyCounts[ i ] ) _MinPropertyCounts[ i ] = count; } } if ( _MaxPropertyCounts.Count == 0 ) { foreach ( ItemStatistics item in kvp.Value ) _MaxPropertyCounts.Add( item.PropertyCount ); } else { for ( int i = 0; i < kvp.Value.Count; i++ ) { int count = kvp.Value[ i ].PropertyCount; if ( count > _MaxPropertyCounts[ i ] ) _MaxPropertyCounts[ i ] = count; } } if ( isValidMinMax ) { kvp.Value.Sort( SortByMin ); if ( _MinPropertyValues.Count == 0 ) { foreach ( ItemStatistics item in kvp.Value ) _MinPropertyValues.Add( item.MinPropertyValue ); } else { for ( int i = 0; i < kvp.Value.Count; i++ ) { int min = kvp.Value[ i ].MinPropertyValue; if ( min < _MinPropertyValues[ i ] ) _MinPropertyValues[ i ] = min; } } kvp.Value.Sort( SortByMax ); if ( _MaxPropertyValues.Count == 0 ) { foreach ( ItemStatistics item in kvp.Value ) _MaxPropertyValues.Add( item.MaxPropertyValue ); } else { for ( int i = 0; i < kvp.Value.Count; i++ ) { int max = kvp.Value[ i ].MaxPropertyValue; if ( max > _MaxPropertyValues[ i ] ) _MaxPropertyValues[ i ] = max; } } } _ValidCorpseCount += 1; } } }
/// <summary> /// Analyzes item. /// </summary> /// <param name="serial">Item serial.</param> /// <param name="itemID">Item ID.</param> /// <param name="hue">Item hue.</param> /// <param name="amount">Item amount.</param> /// <param name="properties">Item properties.</param> public void AnalyzeItem(uint serial, int itemID, int hue, int amount, QueryPropertiesResponsePacket properties) { // Get item cliloc int cliloc = 0; string name = null; if (properties != null && properties.Properties.Count > 0) { // Get name from name property QueryPropertiesProperty nameProperty = properties.Properties[0]; if (UltimaItemGenerator.IsStackable(nameProperty.Cliloc)) { // Get name from stackable cliloc UltimaClilocArgumentParser nameArguments = new UltimaClilocArgumentParser(nameProperty.Arguments); int nameCliloc = nameArguments.GetCliloc(1); if (nameCliloc > 0) { cliloc = nameCliloc; } else { name = nameArguments[1]; } } else { // Get name from name cliloc if (!UltimaItemGenerator.IsString(nameProperty.Cliloc)) { cliloc = nameProperty.Cliloc; } else { name = nameProperty.Arguments; } } } else { // Get name from item ID cliloc = UltimaItemGenerator.GetClilocFromItemID(itemID); } // Count UltimaItemCounter counter = null; UltimaStringCollection clilocs = Globals.Instance.Clilocs; if (name == null) { if (clilocs != null) { name = clilocs.GetString(cliloc); } if (String.IsNullOrEmpty(name)) { name = cliloc.ToString(); } } if (!_Items.TryGetValue(name, out counter)) { counter = new UltimaItemCounter(serial, name); _Items.Add(name, counter); } if (UltimaItemGenerator.IsStackable(cliloc)) { amount = Math.Max(amount, 1); } else { amount = 1; } counter.Gotcha(hue, amount); _Counter.Gotcha(1); }
/// <summary> /// Generates class and saves it to stream. /// </summary> /// <param name="stream">Stream to write to.</param> /// <param name="item">ItemID of item to generate.</param> /// <param name="hue">Hue of item to generate.</param> /// <param name="amount">Stackable amount of item to generate.</param> /// <param name="properties">Item properties packet.</param> public static void Generate(Stream stream, int itemID, int hue = 0, int amount = 0, QueryPropertiesResponsePacket properties = null) { UltimaItemDefinitions itemDefinitions = Globals.Instance.ItemDefinitions; if (itemDefinitions == null) { App.Window.ShowNotification(NotificationType.Error, "Item definitions not initialized"); return; } UltimaItemProperties itemProperties = Globals.Instance.ItemProperties; if (itemProperties == null) { App.Window.ShowNotification(NotificationType.Error, "Item properties not initialized"); return; } UltimaStringCollection clilocs = Globals.Instance.Clilocs; using (UltimaClassWriter writer = new UltimaClassWriter(stream)) { writer.WriteUsing("System"); writer.WriteUsing("Server"); writer.WriteUsing("Server.Items"); writer.WriteLine(); writer.BeginNamespace("Server.Items"); // Get item definition UltimaItemDefinition itemDefinition = null; if (itemDefinitions.Items.ContainsKey(itemID)) { itemDefinition = itemDefinitions.Items[itemID]; } string className = "GenericClass"; string baseClass = null; int nameCliloc = 0; string nameClilocText = null; string nameText = null; bool stackable = false; if (itemDefinition != null) { baseClass = itemDefinition.Class; } // Get class name if (properties != null && properties.Properties.Count > 0) { // Get name from name property QueryPropertiesProperty nameProperty = properties.Properties[0]; if (nameProperty.Cliloc == StackableCliloc) { // Get name from stackable cliloc UltimaClilocArgumentParser nameArguments = new UltimaClilocArgumentParser(nameProperty.Arguments); nameCliloc = nameArguments.GetCliloc(0); if (nameCliloc > 0) { if (clilocs != null) { nameClilocText = clilocs.GetString(nameCliloc); if (!String.IsNullOrEmpty(nameClilocText)) { className = UltimaClassWriter.BuildClassName(nameClilocText); } } } else { nameText = nameArguments[0]; if (!String.IsNullOrEmpty(nameText)) { className = UltimaClassWriter.BuildClassName(nameText); } } stackable = true; } else { // Get name from name cliloc nameCliloc = nameProperty.Cliloc; if (!IsString(nameCliloc)) { if (clilocs != null) { nameClilocText = clilocs.GetString(nameCliloc); if (!String.IsNullOrEmpty(nameClilocText)) { className = UltimaClassWriter.BuildClassName(nameClilocText); } } } else { nameText = nameProperty.Arguments; if (!String.IsNullOrEmpty(nameText)) { className = UltimaClassWriter.BuildClassName(nameText); } } } } else if (clilocs != null) { // Get name from itemID cliloc int itemIDCliloc = 0; if (itemID < 0x4000) { itemIDCliloc = OldItemCliloc + itemID; } else { itemIDCliloc = NewItemCliloc + itemID; } string clilocText = clilocs.GetString(itemIDCliloc); if (!String.IsNullOrEmpty(clilocText)) { className = UltimaClassWriter.BuildClassName(clilocText); } } // Check if container bool isContainer = false; if (baseClass == null && properties != null && properties.Properties.Count > 0) { for (int i = 1; i < properties.Properties.Count; i++) { QueryPropertiesProperty property = properties.Properties[i]; if (IsContainer(property.Cliloc)) { baseClass = "BaseContainer"; isContainer = true; break; } } } if (baseClass == null) { baseClass = "Item"; } writer.BeginClass(className, baseClass); // Name cliloc bool anyOverrides = false; if (nameCliloc > 0 && IsSpecial(itemID, nameCliloc)) { if (!String.IsNullOrEmpty(nameClilocText)) { writer.OverrideProperty("public", "int", "LabelNumber", nameCliloc.ToString(), nameClilocText); } else { writer.OverrideProperty("public", "int", "LabelNumber", nameCliloc.ToString()); } anyOverrides = true; } // Properties if (properties != null && properties.Properties.Count > 0) { Dictionary <int, UltimaItemProperty> constructorPropertyDefinitions = new Dictionary <int, UltimaItemProperty>(); List <QueryPropertiesProperty> constructorProperties = new List <QueryPropertiesProperty>(); List <QueryPropertiesProperty> unknownProperties = new List <QueryPropertiesProperty>(); List <QueryPropertiesProperty> damageProperties = new List <QueryPropertiesProperty>(); for (int i = 1; i < properties.Properties.Count; i++) { QueryPropertiesProperty property = properties.Properties[i]; if (IsDamage(property.Cliloc)) { damageProperties.Add(property); continue; } UltimaItemProperty propertyDefinition = null; if (itemDefinition != null) { Dictionary <int, UltimaItemProperty> groupProperties = null; UltimaItemDefinitionGroup group = itemDefinition.Parent; while (group.Parent != null) { group = group.Parent; } if (itemProperties.GroupProperties.TryGetValue(group.Name, out groupProperties)) { if (!groupProperties.TryGetValue(property.Cliloc, out propertyDefinition)) { itemProperties.Properties.TryGetValue(property.Cliloc, out propertyDefinition); } } else { itemProperties.Properties.TryGetValue(property.Cliloc, out propertyDefinition); } } else { itemProperties.Properties.TryGetValue(property.Cliloc, out propertyDefinition); } if (propertyDefinition != null) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser(property.Arguments); bool isConstructor = false; string propertyValue = null; if (propertyDefinition.Switch != null) { propertyDefinition.Switch.TryGetValue(property.Cliloc, out propertyValue); } foreach (UltimaItemPropertySetter setter in propertyDefinition.Setters) { if (!isConstructor && !setter.Overrides) { constructorProperties.Add(property); constructorPropertyDefinitions.Add(property.Cliloc, propertyDefinition); isConstructor = true; } if (setter.Overrides) { string argument = arguments[setter.Index]; string value = propertyValue; if (propertyValue == null) { value = GetPropertyValue(property.Cliloc, argument, setter); } writer.OverrideProperty("public", setter.ReturnType, setter.Name, value); anyOverrides = true; } } } else { unknownProperties.Add(property); } } if (anyOverrides) { writer.WriteLine(); } writer.WriteLineWithIndent("[Constructable]"); if (isContainer) { writer.BeginConstructor("public", className, null, String.Format("0x{0:X}", itemID)); } else { writer.BeginConstructor("public", className, null, ""); } // Name if (nameText != null) { writer.WriteLineWithIndent("Name = \"{0}\";", nameText); } // ItemID if (!isContainer && itemDefinition == null) { writer.WriteLineWithIndent("ItemID = 0x{0:X};", itemID); } // Hue if (hue > 0) { writer.WriteLineWithIndent("Hue = 0x{0:X};", hue); } // Stackable if (stackable) { writer.WriteLineWithIndent("Stackable = true;"); } if (amount > 1) { writer.WriteLineWithIndent("Amount = {0};", amount); } // Constructor variables foreach (QueryPropertiesProperty property in constructorProperties) { UltimaItemProperty propertyDefinition = constructorPropertyDefinitions[property.Cliloc]; UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser(property.Arguments); bool isSlayerSet = false; string propertyValue = null; if (propertyDefinition.Switch != null) { propertyDefinition.Switch.TryGetValue(property.Cliloc, out propertyValue); } foreach (UltimaItemPropertySetter setter in propertyDefinition.Setters) { if (!setter.Overrides) { string argument = arguments[setter.Index]; string value = propertyValue; if (value == null) { value = GetPropertyValue(property.Cliloc, argument, setter); } // Check if slayer 2 string setterName = setter.Name; if (isSlayerSet) { setterName += "2"; } if (setter.IsSlayer) { isSlayerSet = true; } // Write writer.WriteLineWithIndent(String.Format("{0} = {1};", setterName, value)); } } } // Write unknowns if (unknownProperties.Count > 0) { writer.WriteLine(); writer.WriteLineWithIndent("// Unknown properties"); foreach (QueryPropertiesProperty property in unknownProperties) { string clilocText = null; string format = "Found unknown property '{0}' with parameters '{1}'"; string notification = null; if (clilocs != null) { clilocText = GetPropertyDescription(property.Cliloc); } if (clilocText != null) { writer.WriteLineWithIndent(String.Format("//{0} = {1}; // Cliloc: {2}", property.Cliloc, property.Arguments, clilocText)); notification = String.Format(format, clilocText, property.Arguments); } else { writer.WriteLineWithIndent(String.Format("//{0} = {1};", property.Cliloc, property.Arguments)); notification = String.Format(format, property.Cliloc, property.Arguments); } App.Window.ShowNotification(NotificationType.Warning, notification); } } writer.EndConstructor(); // Write damage overwrite if (damageProperties.Count > 0) { int physicalDamage = 0; int fireDamage = 0; int coldDamage = 0; int poisonDamage = 0; int energyDamage = 0; int chaosDamage = 0; int directDamage = 0; foreach (QueryPropertiesProperty property in damageProperties) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser(property.Arguments); if (arguments.Length > 0) { int integer = 0; if (Int32.TryParse(arguments[0], out integer)) { if (property.Cliloc == 1060403) { physicalDamage = integer; } else if (property.Cliloc == 1060405) { fireDamage = integer; } else if (property.Cliloc == 1060404) { coldDamage = integer; } else if (property.Cliloc == 1060406) { poisonDamage = integer; } else if (property.Cliloc == 1060407) { energyDamage = integer; } else if (property.Cliloc == 1072846) { chaosDamage = integer; } else if (property.Cliloc == 1079978) { directDamage = integer; } } } } if (physicalDamage != 100) { writer.WriteLine(); writer.BeginOverrideMethod("public", "void", "GetDamageTypes", "Mobile wielder, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, out int direct"); writer.WriteLineWithIndent("phys = {0};", physicalDamage); writer.WriteLineWithIndent("fire = {0};", fireDamage); writer.WriteLineWithIndent("cold = {0};", coldDamage); writer.WriteLineWithIndent("pois = {0};", poisonDamage); writer.WriteLineWithIndent("nrgy = {0};", energyDamage); writer.WriteLineWithIndent("chaos = {0};", chaosDamage); writer.WriteLineWithIndent("direct = {0};", directDamage); writer.EndMethod(); } } } else { writer.BeginConstructor("public", className); // Name if (nameText != null) { writer.WriteLineWithIndent("Name = \"{0}\";", nameText); } // ItemID writer.WriteLineWithIndent("ItemID = 0x{0:X};", itemID); // Hue if (hue > 0) { writer.WriteLineWithIndent("Hue = 0x{0:X};", hue); } // Stackable if (stackable) { writer.WriteLineWithIndent("Stackable = true;"); } if (amount > 1) { writer.WriteLineWithIndent("Amount = {0};", amount); } writer.EndConstructor(); } writer.WriteLine(); writer.WriteSerialConstructor(className); writer.WriteLine(); writer.WriteSerialize(); writer.WriteLine(); writer.WriteDeserialize(); writer.EndClass(); writer.EndNamespace(); App.Window.ShowNotification(NotificationType.Info, "Item generation complete"); } }
/// <summary> /// Analyzes item. /// </summary> /// <param name="serial">Item serial.</param> /// <param name="itemID">Item ID.</param> /// <param name="hue">Item hue.</param> /// <param name="amount">Item amount.</param> /// <param name="properties">Item properties.</param> public void AnalyzeItem( uint serial, int itemID, int hue, int amount, QueryPropertiesResponsePacket properties ) { // Get item cliloc int cliloc = 0; string name = null; if ( properties != null && properties.Properties.Count > 0 ) { // Get name from name property QueryPropertiesProperty nameProperty = properties.Properties[ 0 ]; if ( UltimaItemGenerator.IsStackable( nameProperty.Cliloc ) ) { // Get name from stackable cliloc UltimaClilocArgumentParser nameArguments = new UltimaClilocArgumentParser( nameProperty.Arguments ); int nameCliloc = nameArguments.GetCliloc( 1 ); if ( nameCliloc > 0 ) cliloc = nameCliloc; else name = nameArguments[1 ]; } else { // Get name from name cliloc if ( !UltimaItemGenerator.IsString( nameProperty.Cliloc ) ) cliloc = nameProperty.Cliloc; else name = nameProperty.Arguments; } } else { // Get name from item ID cliloc = UltimaItemGenerator.GetClilocFromItemID( itemID ); } // Count UltimaItemCounter counter = null; UltimaStringCollection clilocs = Globals.Instance.Clilocs; if ( name == null ) { if ( clilocs != null ) name = clilocs.GetString( cliloc ); if ( String.IsNullOrEmpty( name ) ) name = cliloc.ToString(); } if ( !_Items.TryGetValue( name, out counter ) ) { counter = new UltimaItemCounter( serial, name ); _Items.Add( name, counter ); } if ( UltimaItemGenerator.IsStackable( cliloc ) ) amount = Math.Max( amount, 1 ); else amount = 1; counter.Gotcha( hue, amount ); _Counter.Gotcha( 1 ); }
/// <summary> /// Generates class and saves it to stream. /// </summary> /// <param name="stream">Stream to write to.</param> /// <param name="item">ItemID of item to generate.</param> /// <param name="hue">Hue of item to generate.</param> /// <param name="amount">Stackable amount of item to generate.</param> /// <param name="properties">Item properties packet.</param> public static void Generate( Stream stream, int itemID, int hue = 0, int amount = 0, QueryPropertiesResponsePacket properties = null ) { UltimaItemDefinitions itemDefinitions = Globals.Instance.ItemDefinitions; if ( itemDefinitions == null ) { App.Window.ShowNotification( NotificationType.Error, "Item definitions not initialized" ); return; } UltimaItemProperties itemProperties = Globals.Instance.ItemProperties; if ( itemProperties == null ) { App.Window.ShowNotification( NotificationType.Error, "Item properties not initialized" ); return; } UltimaStringCollection clilocs = Globals.Instance.Clilocs; using ( UltimaClassWriter writer = new UltimaClassWriter( stream ) ) { writer.WriteUsing( "System" ); writer.WriteUsing( "Server" ); writer.WriteUsing( "Server.Items" ); writer.WriteLine(); writer.BeginNamespace( "Server.Items" ); // Get item definition UltimaItemDefinition itemDefinition = null; if ( itemDefinitions.Items.ContainsKey( itemID ) ) itemDefinition = itemDefinitions.Items[ itemID ]; string className = "GenericClass"; string baseClass = null; int nameCliloc = 0; string nameClilocText = null; string nameText = null; bool stackable = false; if ( itemDefinition != null ) baseClass = itemDefinition.Class; // Get class name if ( properties != null && properties.Properties.Count > 0 ) { // Get name from name property QueryPropertiesProperty nameProperty = properties.Properties[ 0 ]; if ( nameProperty.Cliloc == StackableCliloc ) { // Get name from stackable cliloc UltimaClilocArgumentParser nameArguments = new UltimaClilocArgumentParser( nameProperty.Arguments ); nameCliloc = nameArguments.GetCliloc( 0 ); if ( nameCliloc > 0 ) { if ( clilocs != null ) { nameClilocText = clilocs.GetString( nameCliloc ); if ( !String.IsNullOrEmpty( nameClilocText ) ) className = UltimaClassWriter.BuildClassName( nameClilocText ); } } else { nameText = nameArguments[ 0 ]; if ( !String.IsNullOrEmpty( nameText ) ) className = UltimaClassWriter.BuildClassName( nameText ); } stackable = true; } else { // Get name from name cliloc nameCliloc = nameProperty.Cliloc; if ( !IsString( nameCliloc ) ) { if ( clilocs != null ) { nameClilocText = clilocs.GetString( nameCliloc ); if ( !String.IsNullOrEmpty( nameClilocText ) ) className = UltimaClassWriter.BuildClassName( nameClilocText ); } } else { nameText = nameProperty.Arguments; if ( !String.IsNullOrEmpty( nameText ) ) className = UltimaClassWriter.BuildClassName( nameText ); } } } else if ( clilocs != null ) { // Get name from itemID cliloc int itemIDCliloc = 0; if ( itemID < 0x4000 ) itemIDCliloc = OldItemCliloc + itemID; else itemIDCliloc = NewItemCliloc + itemID; string clilocText = clilocs.GetString( itemIDCliloc ); if ( !String.IsNullOrEmpty( clilocText ) ) className = UltimaClassWriter.BuildClassName( clilocText ); } // Check if container bool isContainer = false; if ( baseClass == null && properties != null && properties.Properties.Count > 0 ) { for ( int i = 1; i < properties.Properties.Count; i++ ) { QueryPropertiesProperty property = properties.Properties[ i ]; if ( IsContainer( property.Cliloc ) ) { baseClass = "BaseContainer"; isContainer = true; break; } } } if ( baseClass == null ) baseClass = "Item"; writer.BeginClass( className, baseClass ); // Name cliloc bool anyOverrides = false; if ( nameCliloc > 0 && IsSpecial( itemID, nameCliloc ) ) { if ( !String.IsNullOrEmpty( nameClilocText ) ) writer.OverrideProperty( "public", "int", "LabelNumber", nameCliloc.ToString(), nameClilocText ); else writer.OverrideProperty( "public", "int", "LabelNumber", nameCliloc.ToString() ); anyOverrides = true; } // Properties if ( properties != null && properties.Properties.Count > 0 ) { Dictionary<int, UltimaItemProperty> constructorPropertyDefinitions = new Dictionary<int, UltimaItemProperty>(); List<QueryPropertiesProperty> constructorProperties = new List<QueryPropertiesProperty>(); List<QueryPropertiesProperty> unknownProperties = new List<QueryPropertiesProperty>(); List<QueryPropertiesProperty> damageProperties = new List<QueryPropertiesProperty>(); for ( int i = 1; i < properties.Properties.Count; i++ ) { QueryPropertiesProperty property = properties.Properties[ i ]; if ( IsDamage( property.Cliloc ) ) { damageProperties.Add( property ); continue; } UltimaItemProperty propertyDefinition = null; if ( itemDefinition != null ) { Dictionary<int, UltimaItemProperty> groupProperties = null; UltimaItemDefinitionGroup group = itemDefinition.Parent; while ( group.Parent != null ) group = group.Parent; if ( itemProperties.GroupProperties.TryGetValue( group.Name, out groupProperties ) ) { if ( !groupProperties.TryGetValue( property.Cliloc, out propertyDefinition ) ) itemProperties.Properties.TryGetValue( property.Cliloc, out propertyDefinition ); } else itemProperties.Properties.TryGetValue( property.Cliloc, out propertyDefinition ); } else itemProperties.Properties.TryGetValue( property.Cliloc, out propertyDefinition ); if ( propertyDefinition != null ) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser( property.Arguments ); bool isConstructor = false; string propertyValue = null; if ( propertyDefinition.Switch != null ) propertyDefinition.Switch.TryGetValue( property.Cliloc, out propertyValue ); foreach ( UltimaItemPropertySetter setter in propertyDefinition.Setters ) { if ( !isConstructor && !setter.Overrides ) { constructorProperties.Add( property ); constructorPropertyDefinitions.Add( property.Cliloc, propertyDefinition ); isConstructor = true; } if ( setter.Overrides ) { string argument = arguments[ setter.Index ]; string value = propertyValue; if ( propertyValue == null ) value = GetPropertyValue( property.Cliloc, argument, setter ); writer.OverrideProperty( "public", setter.ReturnType, setter.Name, value ); anyOverrides = true; } } } else unknownProperties.Add( property ); } if ( anyOverrides ) writer.WriteLine(); writer.WriteLineWithIndent( "[Constructable]" ); if ( isContainer ) writer.BeginConstructor( "public", className, null, String.Format( "0x{0:X}", itemID ) ); else writer.BeginConstructor( "public", className, null, "" ); // Name if ( nameText != null ) writer.WriteLineWithIndent( "Name = \"{0}\";", nameText ); // ItemID if ( !isContainer && itemDefinition == null ) writer.WriteLineWithIndent( "ItemID = 0x{0:X};", itemID ); // Hue if ( hue > 0 ) writer.WriteLineWithIndent( "Hue = 0x{0:X};", hue ); // Stackable if ( stackable ) writer.WriteLineWithIndent( "Stackable = true;" ); if ( amount > 1 ) writer.WriteLineWithIndent( "Amount = {0};", amount ); // Constructor variables foreach ( QueryPropertiesProperty property in constructorProperties ) { UltimaItemProperty propertyDefinition = constructorPropertyDefinitions[ property.Cliloc ]; UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser( property.Arguments ); bool isSlayerSet = false; string propertyValue = null; if ( propertyDefinition.Switch != null ) propertyDefinition.Switch.TryGetValue( property.Cliloc, out propertyValue ); foreach ( UltimaItemPropertySetter setter in propertyDefinition.Setters ) { if ( !setter.Overrides ) { string argument = arguments[ setter.Index ]; string value = propertyValue; if ( value == null ) value = GetPropertyValue( property.Cliloc, argument, setter ); // Check if slayer 2 string setterName = setter.Name; if ( isSlayerSet ) setterName += "2"; if ( setter.IsSlayer ) isSlayerSet = true; // Write writer.WriteLineWithIndent( String.Format( "{0} = {1};", setterName, value ) ); } } } // Write unknowns if ( unknownProperties.Count > 0 ) { writer.WriteLine(); writer.WriteLineWithIndent( "// Unknown properties" ); foreach ( QueryPropertiesProperty property in unknownProperties ) { string clilocText = null; string format = "Found unknown property '{0}' with parameters '{1}'"; string notification = null; if ( clilocs != null ) clilocText = GetPropertyDescription( property.Cliloc ); if ( clilocText != null ) { writer.WriteLineWithIndent( String.Format( "//{0} = {1}; // Cliloc: {2}", property.Cliloc, property.Arguments, clilocText ) ); notification = String.Format( format, clilocText, property.Arguments ); } else { writer.WriteLineWithIndent( String.Format( "//{0} = {1};", property.Cliloc, property.Arguments ) ); notification = String.Format( format, property.Cliloc, property.Arguments ); } App.Window.ShowNotification( NotificationType.Warning, notification ); } } writer.EndConstructor(); // Write damage overwrite if ( damageProperties.Count > 0 ) { int physicalDamage = 0; int fireDamage = 0; int coldDamage = 0; int poisonDamage = 0; int energyDamage = 0; int chaosDamage = 0; int directDamage = 0; foreach ( QueryPropertiesProperty property in damageProperties ) { UltimaClilocArgumentParser arguments = new UltimaClilocArgumentParser( property.Arguments ); if ( arguments.Length > 0 ) { int integer = 0; if ( Int32.TryParse( arguments[ 0 ], out integer ) ) { if ( property.Cliloc == 1060403 ) physicalDamage = integer; else if ( property.Cliloc == 1060405 ) fireDamage = integer; else if ( property.Cliloc == 1060404 ) coldDamage = integer; else if ( property.Cliloc == 1060406 ) poisonDamage = integer; else if ( property.Cliloc == 1060407 ) energyDamage = integer; else if ( property.Cliloc == 1072846 ) chaosDamage = integer; else if ( property.Cliloc == 1079978 ) directDamage = integer; } } } if ( physicalDamage != 100 ) { writer.WriteLine(); writer.BeginOverrideMethod( "public", "void", "GetDamageTypes", "Mobile wielder, out int phys, out int fire, out int cold, out int pois, out int nrgy, out int chaos, out int direct" ); writer.WriteLineWithIndent( "phys = {0};", physicalDamage ); writer.WriteLineWithIndent( "fire = {0};", fireDamage ); writer.WriteLineWithIndent( "cold = {0};", coldDamage ); writer.WriteLineWithIndent( "pois = {0};", poisonDamage ); writer.WriteLineWithIndent( "nrgy = {0};", energyDamage ); writer.WriteLineWithIndent( "chaos = {0};", chaosDamage ); writer.WriteLineWithIndent( "direct = {0};", directDamage ); writer.EndMethod(); } } } else { writer.BeginConstructor( "public", className ); // Name if ( nameText != null ) writer.WriteLineWithIndent( "Name = \"{0}\";", nameText ); // ItemID writer.WriteLineWithIndent( "ItemID = 0x{0:X};", itemID ); // Hue if ( hue > 0 ) writer.WriteLineWithIndent( "Hue = 0x{0:X};", hue ); // Stackable if ( stackable ) writer.WriteLineWithIndent( "Stackable = true;" ); if ( amount > 1 ) writer.WriteLineWithIndent( "Amount = {0};", amount ); writer.EndConstructor(); } writer.WriteLine(); writer.WriteSerialConstructor( className ); writer.WriteLine(); writer.WriteSerialize(); writer.WriteLine(); writer.WriteDeserialize(); writer.EndClass(); writer.EndNamespace(); App.Window.ShowNotification( NotificationType.Info, "Item generation complete" ); } }