Files
Beyhan Oğur d5f52cc3d3 first commit
2026-09-03 04:45:36 +03:00

438 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Windows.Input;
using ClassicAssist.Misc;
using ClassicAssist.Shared;
using ClassicAssist.Shared.Resources;
using ClassicAssist.UI.Models;
using ClassicAssist.UO;
using ClassicAssist.UO.Data;
using ClassicAssist.UO.Objects;
using Microsoft.Scripting.Utils;
namespace ClassicAssist.UI.ViewModels
{
public class ObjectInspectorViewModel : BaseViewModel
{
private ICommand _copyToClipboardCommand;
private ObservableCollection<ObjectInspectorData> _items = new ObservableCollection<ObjectInspectorData>();
private ObjectInspectorData _selectedItem;
public ObjectInspectorViewModel()
{
Items.AddRange( new List<ObjectInspectorData>
{
new ObjectInspectorData { Name = "Name", Value = "Value", Category = "Category" }
} );
}
public ObjectInspectorViewModel( Entity entity )
{
AddEntityProperties( entity );
if ( entity is Mobile mobile )
{
AddMobileProperties( mobile );
}
//AddPublicProperties( entity );
}
public ObjectInspectorViewModel( StaticTile staticTile )
{
AddStaticProperties( staticTile );
}
public ObjectInspectorViewModel( LandTile landTile )
{
AddLandProperties( landTile );
}
public ICommand CopyToClipboardCommand
{
get
{
return _copyToClipboardCommand ?? ( _copyToClipboardCommand =
new RelayCommand( o => CopyToClipboard(), o => _selectedItem != null ) );
}
}
public ObservableCollection<ObjectInspectorData> Items
{
get => _items;
set => SetProperty( ref _items, value );
}
public ObjectInspectorData SelectedItem
{
get => _selectedItem;
set => SetProperty( ref _selectedItem, value );
}
private void AddLandProperties( LandTile landTile )
{
AddData( typeof( Entity ), nameof( Entity.Name ), landTile.Name, Strings.Entity );
AddData( "Flags", landTile.Flags.ToString(), Strings.Entity );
AddData( typeof( Entity ), nameof( Entity.ID ), landTile.ID, Strings.Entity, Strings.Graphic );
AddData( "Position", $"{landTile.X}, {landTile.Y}, {landTile.Z}", Strings.Entity );
}
private void AddStaticProperties( StaticTile staticTile )
{
AddData( typeof( Entity ), nameof( Entity.Name ), staticTile.Name, Strings.Entity );
AddData( "Flags", staticTile.Flags.ToString(), Strings.Entity );
AddData( typeof( Entity ), nameof( Entity.ID ), staticTile.ID, Strings.Entity, Strings.Graphic );
AddData( typeof( Entity ), nameof( Entity.Hue ), staticTile.Hue, Strings.Entity, Strings.Color );
AddData( "Position", $"{staticTile.X}, {staticTile.Y}, {staticTile.Z}", Strings.Entity );
AddData( "Weight", staticTile.Weight.ToString(), Strings.Entity );
AddData( "Height", staticTile.Height.ToString(), Strings.Entity );
AddData( "Quality", staticTile.Quality.ToString(), Strings.Entity );
AddData( "Quantity", staticTile.Quantity.ToString(), Strings.Entity );
}
private void AddEntityProperties( Entity entity )
{
AddData( typeof( Entity ), nameof( Entity.Name ), entity.Name, Strings.Entity );
AddData( typeof( Entity ), nameof( Entity.Serial ), entity.Serial, Strings.Entity );
AddData( typeof( Entity ), nameof( Entity.ID ), entity.ID, Strings.Entity, Strings.Graphic );
AddData( typeof( Entity ), nameof( Entity.Hue ), entity.Hue, Strings.Entity, Strings.Color );
AddData( "Position", $"{entity.X}, {entity.Y}, {entity.Z}", Strings.Entity );
}
private void AddMobileProperties( Mobile mobile )
{
AddData( typeof( Mobile ), nameof( Mobile.Name ), mobile.Name, Strings.Mobile );
AddData( "Sex", mobile.Status.HasFlag( MobileStatus.Female ) ? "Female" : "Male", Strings.Mobile );
if ( mobile is PlayerMobile player )
{
AddData( typeof( Mobile ), nameof( Mobile.Hits ), player.Hits, Strings.Mobile );
AddData( typeof( Mobile ), nameof( Mobile.HitsMax ), player.HitsMax, Strings.Mobile, "Max Health" );
}
else
{
float health = mobile.Hits;
float maxHealth = mobile.HitsMax;
float per = health / maxHealth * 100;
AddData( "Hits", ( (uint) per ).ToString() + '%', Strings.Mobile );
}
AddData( typeof( Mobile ), nameof( Mobile.Notoriety ), mobile.Notoriety, Strings.Mobile );
AddData( typeof( Mobile ), nameof( Mobile.Status ), mobile.Status, Strings.Mobile, "Flags" );
#region Equipment Properties
Item[] equipment = GetEquipmentItems( mobile );
if ( equipment == null )
{
return;
}
AddEquipmentProperty( equipment, new[] { 1060448, 1153735 }, new[] { 0, 0 }, "Physical Resist",
Strings.Resistances );
AddEquipmentProperty( equipment, new[] { 1060447, 1153737 }, new[] { 0, 0 }, "Fire Resist",
Strings.Resistances );
AddEquipmentProperty( equipment, new[] { 1060445, 1153739 }, new[] { 0, 0 }, "Cold Resist",
Strings.Resistances );
AddEquipmentProperty( equipment, new[] { 1060449, 1153736 }, new[] { 0, 0 }, "Poison Resist",
Strings.Resistances );
AddEquipmentProperty( equipment, new[] { 1060446, 1153738 }, new[] { 0, 0 }, "Energy Resist",
Strings.Resistances );
AddEquipmentProperty( equipment, 1060413, 0, "Faster Casting", Strings.Magical );
AddEquipmentProperty( equipment, 1060412, 0, "Faster Cast Recovery", Strings.Magical );
AddEquipmentProperty( equipment, 1060434, 0, "Lower Reagent Cost", Strings.Magical );
AddEquipmentProperty( equipment, 1060433, 0, "Lower Mana Cost", Strings.Magical );
AddEquipmentProperty( equipment, 1060483, 0, "Spell Damage Increase", Strings.Magical );
AddEquipmentProperty( equipment, 1060408, 0, "Defense Chance Increase", Strings.Combat );
AddEquipmentProperty( equipment, 1060415, 0, "Hit Chance Increase", Strings.Combat );
AddEquipmentProperty( equipment, 1060401, 0, "Damage Increase", Strings.Combat );
AddEquipmentProperty( equipment, 1060402, 0, "Damage Increase", Strings.Combat );
AddEquipmentProperty( equipment, 1060486, 0, "Swing Speed Increase", Strings.Combat );
AddEquipmentProperty( equipment, 1060485, 0, "Strength Bonus", Strings.Stats );
AddEquipmentProperty( equipment, 1060432, 0, "Intelligence Bonus", Strings.Stats );
AddEquipmentProperty( equipment, 1060409, 0, "Dexterity Bonus", Strings.Stats );
AddEquipmentProperty( equipment, 1060431, 0, "Hit Point Increase", Strings.Stats );
AddEquipmentProperty( equipment, 1060439, 0, "Mana Increase", Strings.Stats );
AddEquipmentProperty( equipment, 1060484, 0, "Stamina Increase", Strings.Stats );
AddEquipmentProperty( equipment, 1060444, 0, "Hit Point Regeneration", Strings.Regeneration );
AddEquipmentProperty( equipment, 1060440, 0, "Mana Regeneration", Strings.Regeneration );
AddEquipmentProperty( equipment, 1060443, 0, "Stamina Regeneration", Strings.Regeneration );
AddEquipmentProperty( equipment, 1060436, 0, "Luck", "Misc" );
AddEquipmentPropertyWithSymbol( equipment, 1153733, 0, 1, "Max Defense Chance Increase",
Strings.Buffs___Penalties );
AddEquipmentPropertyWithSymbol( equipment, 1153735, 1, 2, "Physical Resist", Strings.Buffs___Penalties );
AddEquipmentPropertyWithSymbol( equipment, 1153737, 1, 2, "Fire Resist", Strings.Buffs___Penalties );
AddEquipmentPropertyWithSymbol( equipment, 1153739, 1, 2, "Cold Resist", Strings.Buffs___Penalties );
AddEquipmentPropertyWithSymbol( equipment, 1153736, 1, 2, "Poison Resist", Strings.Buffs___Penalties );
AddEquipmentPropertyWithSymbol( equipment, 1153738, 1, 2, "Energy Resist", Strings.Buffs___Penalties );
#endregion
}
private static Item[] GetEquipmentItems( Mobile mobile )
{
List<Item> items = new List<Item>();
foreach ( Item item in mobile.GetEquippedItems() )
{
items.Add( item );
}
return items.ToArray();
}
private void AddEquipmentProperty( Item[] items, int cliloc, int argumentIndex, string name, string category )
{
AddEquipmentProperty( items, new[] { cliloc }, new[] { argumentIndex }, name, category );
}
private void AddEquipmentProperty( Item[] items, IReadOnlyList<int> clilocs, IReadOnlyList<int> argumentIndexs,
string name, string category )
{
int amount = clilocs.Select( ( t, i ) => CountPropertyList( items.ToArray(), t, argumentIndexs[i] ) ).Sum();
if ( amount > 0 )
{
AddData( new ObjectInspectorData
{
Name = name, Value = amount.ToString(), Category = category, IsExpanded = false
} );
}
}
private void AddEquipmentPropertyWithSymbol( Item[] items, int cliloc, int symbolIndex, int argumentIndex,
string name, string category )
{
int amount = CountPropertyListWithSymbol( items.ToArray(), cliloc, symbolIndex, argumentIndex );
if ( amount != 0 )
{
AddData( new ObjectInspectorData
{
Name = name, Value = amount.ToString(), Category = category, IsExpanded = false
} );
}
}
private static int CountProperty( int serial, int cliloc, int argumentIndex )
{
Item item = Engine.Items.GetItem( serial );
Property[] properties = item?.Properties;
if ( properties == null )
{
return 0;
}
return properties.Where( p => p.Cliloc == cliloc ).Select( p => int.Parse( p.Arguments[argumentIndex] ) )
.FirstOrDefault();
}
private static int CountPropertyList( IEnumerable<Item> items, int cliloc, int argumentIndex )
{
return items.Sum( t => CountProperty( t.Serial, cliloc, argumentIndex ) );
}
private static int CountPropertyListWithSymbol( IReadOnlyList<Item> items, int cliloc, int symbolIndex,
int argumentIndex )
{
int total = 0;
foreach ( Item t in items )
{
int count = CountProperty( t.Serial, cliloc, argumentIndex );
Property[] properties = t.Properties;
if ( properties == null )
{
continue;
}
foreach ( Property p in properties )
{
if ( p.Cliloc != cliloc )
{
continue;
}
string symbol = p.Arguments[symbolIndex];
if ( symbol == "-" )
{
total -= count;
}
else
{
total += count;
}
}
}
return total;
}
private static string GetDisplayFormat( Type type, string propertyName, object value )
{
if ( propertyName == null )
{
return value.ToString();
}
DisplayFormatAttribute attr = type.GetPropertyAttribute<DisplayFormatAttribute>( propertyName );
return attr != null ? attr.ToString( value ) : value?.ToString() ?? string.Empty;
}
private void AddData( Type type, string propertyName, object value, string category, string nameOverride = "",
Action<object> action = null )
{
AddData( new ObjectInspectorData
{
Name = string.IsNullOrEmpty( nameOverride ) ? propertyName : nameOverride,
Value = GetDisplayFormat( type, propertyName, value ),
Category = category,
OnDoubleClick = action
} );
}
private void AddData( string name, string value, string category )
{
AddData( new ObjectInspectorData { Name = name, Value = value, Category = category } );
}
private void AddData( ObjectInspectorData data )
{
_dispatcher.Invoke( () => { Items.Add( data ); } );
}
private void CopyToClipboard()
{
try
{
//TODO
//Clipboard.SetData( DataFormats.Text, _selectedItem.Value );
}
catch ( Exception )
{
// ignored
}
}
private void AddPublicProperties( Entity entity )
{
List<ObjectInspectorData> data = new List<ObjectInspectorData>();
IOrderedEnumerable<PropertyInfo> properties = entity.GetType().GetProperties().OrderBy( p => p.Name );
foreach ( PropertyInfo p in properties )
{
object value = p.GetValue( entity );
string valueString = "null";
if ( value != null )
{
valueString = value.ToString();
}
DisplayFormatAttribute attr = entity.GetType().GetPropertyAttribute<DisplayFormatAttribute>( p.Name );
if ( attr != null )
{
valueString = attr.ToString( value );
}
data.Add( new ObjectInspectorData
{
Name = p.Name,
Value = valueString,
Category = Strings.Public_Properties,
IsExpanded = true,
OnDoubleClick = GetDoubleClickAction( value )
} );
}
Items.AddRange( data );
}
private static Action<object> GetDoubleClickAction( object value )
{
if ( value == null )
{
return null;
}
if ( value is IObjectInspectorDoubleClick )
{
return o => ( (IObjectInspectorDoubleClick) value ).OnDoubleClick( o );
}
if ( value is ItemCollection collection )
{
return o => ShowItemCollection( collection );
}
if ( value is Item item )
{
return o => InspectObject( item.Serial );
}
return null;
}
private static void InspectObject( int serial )
{
Entity entity;
if ( UOMath.IsMobile( serial ) )
{
entity = Engine.Mobiles.GetMobile( serial );
}
else
{
entity = Engine.Items.GetItem( serial );
}
if ( entity == null )
{
return;
}
Engine.UIInvoker.Invoke( "ObjectInspectorWindow", null, typeof( ObjectInspectorViewModel ),
new object[] { entity } );
}
private static void ShowItemCollection( ItemCollection collection )
{
if ( collection == null )
{
}
//TODO
//EntityCollectionViewer window = new EntityCollectionViewer
//{
// DataContext = new EntityCollectionViewerViewModel( collection ),
// Topmost = true
//};
//window.ShowDialog();
}
}
public interface IObjectInspectorDoubleClick
{
void OnDoubleClick( object o );
}
}