Compare commits
108 Commits
feature-sm
...
0.0.1-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46c877f036 | ||
|
|
2943f7a50b | ||
|
|
bdd026519f | ||
|
|
a11cde4121 | ||
|
|
b3c3a5fa85 | ||
|
|
b97a2ea63c | ||
|
|
75a5b842f7 | ||
|
|
c61019961b | ||
|
|
c3f6d10dc6 | ||
|
|
b7d8dd1db0 | ||
|
|
f761a0577e | ||
|
|
7f81380c89 | ||
|
|
e3e0db29ad | ||
|
|
ee0b8db572 | ||
|
|
e95d748f00 | ||
|
|
38c8a67bfb | ||
|
|
c84a086447 | ||
|
|
e42ff2b5e7 | ||
|
|
129381e13c | ||
|
|
63833745b6 | ||
|
|
385f02a3d8 | ||
|
|
17a4f82f24 | ||
|
|
efffe8a7cb | ||
|
|
604ba8af9b | ||
|
|
ee11faf0ce | ||
|
|
2e025fd0cf | ||
|
|
641e20e82a | ||
|
|
8ea599ccc6 | ||
|
|
24b7055136 | ||
|
|
521af7c00e | ||
|
|
a2428bb0d1 | ||
|
|
ab85800275 | ||
|
|
03e61a9b9a | ||
|
|
9836ef3a17 | ||
|
|
ede55a870e | ||
|
|
b948273172 | ||
|
|
2c475e69f3 | ||
|
|
787f4969ed | ||
|
|
a7a9b626f4 | ||
|
|
3050c58881 | ||
|
|
d47ad68ff0 | ||
|
|
c31bc2597e | ||
|
|
ac7bde68e9 | ||
|
|
f450a7cc0e | ||
|
|
8eea2ded26 | ||
|
|
7276b24249 | ||
|
|
81e26a7e52 | ||
|
|
bb4538794b | ||
|
|
123d039263 | ||
|
|
ad5d7a5159 | ||
|
|
abcf3b20c0 | ||
|
|
eefb5d40ae | ||
|
|
130cdc6bca | ||
|
|
2480563914 | ||
|
|
d03f37fbf7 | ||
|
|
c35f4e317a | ||
|
|
03423d0c41 | ||
|
|
0e6d8dec86 | ||
|
|
6cbf61d67f | ||
|
|
546b371dd6 | ||
|
|
ec54d22c65 | ||
|
|
1bd107ad0a | ||
|
|
9a0204c6ed | ||
|
|
32fdef9b1c | ||
|
|
823241ef32 | ||
|
|
123037cf23 | ||
|
|
4dc08f3139 | ||
|
|
24e6c4a180 | ||
|
|
5388dea95f | ||
|
|
bd50473bfb | ||
|
|
d2b20e0666 | ||
|
|
31febdd341 | ||
|
|
b8b92b7cf8 | ||
|
|
ea6778a3bd | ||
|
|
89cec4f40f | ||
|
|
a8734a4ca0 | ||
|
|
57d6a61791 | ||
|
|
35e3f5e487 | ||
|
|
905b189bf2 | ||
|
|
a8adf23959 | ||
|
|
f8b0b4b894 | ||
|
|
8b27c84a9e | ||
|
|
16630de6a4 | ||
|
|
4778f1c478 | ||
|
|
340e91b325 | ||
|
|
42d594bbbb | ||
|
|
1d77bceeff | ||
|
|
112c20b7d3 | ||
|
|
2a3e39019e | ||
|
|
54a4514a53 | ||
|
|
7ad3ff4081 | ||
|
|
eb7bfc779b | ||
|
|
f7198a13ef | ||
|
|
b3bb4a52f3 | ||
|
|
d7c0375416 | ||
|
|
1d0dbf86c3 | ||
|
|
e0c7445ef7 | ||
|
|
d6c15ee0c2 | ||
|
|
d48e910603 | ||
|
|
a2bcb25f0e | ||
|
|
4cfb986ce0 | ||
|
|
ca0183603f | ||
|
|
2b94f823f2 | ||
|
|
43f38c7a57 | ||
|
|
6ca8752108 | ||
|
|
3755e45ac6 | ||
|
|
e6e20a1e08 | ||
|
|
e127d94902 |
9
Client/App.xaml
Normal file
@@ -0,0 +1,9 @@
|
||||
<Application x:Class="Client.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:Client"
|
||||
ShutdownMode="OnMainWindowClose">
|
||||
<Application.Resources>
|
||||
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
158
Client/App.xaml.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using Client.Domain.Factories;
|
||||
using Client.Infrastructure.Factories;
|
||||
using Client.Domain.Parsers;
|
||||
using Client.Infrastructure.Parsers;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Windows;
|
||||
using Client.Domain.Transports;
|
||||
using Client.Infrastructure.Transports;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using Client.Domain.ValueObjects;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Reflection;
|
||||
using Client.Application.Views;
|
||||
using Client.Application.ViewModels;
|
||||
using Client.Domain.Helpers;
|
||||
using Client.Infrastructure.Helpers;
|
||||
using Client.Domain.Events;
|
||||
using Client.Infrastructure.Events;
|
||||
using System;
|
||||
using Client.Infrastructure.Service;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Client.Domain.AI;
|
||||
using Client.Infrastructure.AI.IO;
|
||||
using Client.Domain.AI.IO;
|
||||
|
||||
namespace Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : System.Windows.Application
|
||||
{
|
||||
public static IHost? AppHost { get; private set; }
|
||||
|
||||
public App()
|
||||
{
|
||||
AppHost = Host.CreateDefaultBuilder()
|
||||
.ConfigureServices(
|
||||
(hostContext, services) => ConfigureServices(services)
|
||||
)
|
||||
.Build();
|
||||
}
|
||||
|
||||
protected override async void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
await AppHost!.StartAsync();
|
||||
|
||||
var startupForm = AppHost.Services.GetRequiredService<MainWindow>();
|
||||
startupForm.Show();
|
||||
|
||||
base.OnStartup(e);
|
||||
|
||||
var application = AppHost.Services.GetRequiredService<Bot>();
|
||||
await application.StartAsync();
|
||||
}
|
||||
|
||||
protected override async void OnExit(ExitEventArgs e)
|
||||
{
|
||||
await AppHost!.StopAsync();
|
||||
|
||||
base.OnExit(e);
|
||||
}
|
||||
|
||||
private void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
IConfiguration config = new ConfigurationBuilder()
|
||||
.AddJsonFile("config.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("Assets/data/experience.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("Assets/data/npcInfo.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("Assets/data/itemInfo.json", optional: false, reloadOnChange: true)
|
||||
.AddJsonFile("Assets/data/skillInfo.json", optional: false, reloadOnChange: true)
|
||||
.Build();
|
||||
|
||||
services
|
||||
.AddSingleton(typeof(IConfiguration), config)
|
||||
.AddSingleton<MainWindow>()
|
||||
.AddSingleton(
|
||||
typeof(Bot),
|
||||
x => new Bot(
|
||||
x.GetRequiredService<IServiceProvider>(),
|
||||
config.GetValue<string>("DLLName") ?? ""
|
||||
)
|
||||
)
|
||||
.AddSingleton(typeof(EntityHandlerFactoryInterface), typeof(EntityHandlerFactory))
|
||||
.AddSingleton(typeof(MessageParserInterface), typeof(JsonMessageParser))
|
||||
.AddSingleton(typeof(OutgoingMessageBuilderInterface), typeof(JsonOutgoingMessageBuilder))
|
||||
.AddSingleton(
|
||||
typeof(TransportInterface),
|
||||
x => new NamedPipeTransport(
|
||||
config.GetValue<string>("ConnectionPipeName") ?? ""
|
||||
)
|
||||
)
|
||||
.AddSingleton(typeof(ExperienceHelperInterface), typeof(ConfigurationExperienceHelper))
|
||||
.AddSingleton(typeof(NpcInfoHelperInterface), typeof(ConfigurationNpcInfoHelper))
|
||||
.AddSingleton(typeof(ItemInfoHelperInterface), typeof(ConfigurationItemInfoHelper))
|
||||
.AddSingleton(typeof(SkillInfoHelperInterface), typeof(ConfigurationSkillInfoHelper))
|
||||
.AddSingleton(typeof(EventBusInterface), typeof(InMemoryEventBus))
|
||||
|
||||
.AddTransient(typeof(EntityFactoryInterface<Entity>), typeof(EntityFactory<Entity>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<Hero>), typeof(EntityFactory<Hero>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<Drop>), typeof(EntityFactory<Drop>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<NPC>), typeof(EntityFactory<NPC>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<Player>), typeof(EntityFactory<Player>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<ChatMessage>), typeof(EntityFactory<ChatMessage>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<Skill>), typeof(EntityFactory<Skill>))
|
||||
.AddTransient(typeof(EntityFactoryInterface<ItemInterface>), typeof(ItemFactory))
|
||||
|
||||
.AddSingleton<HeroHandler>()
|
||||
.AddSingleton<DropHandler>()
|
||||
.AddSingleton<NpcHandler>()
|
||||
.AddSingleton<PlayerHandler>()
|
||||
.AddSingleton<ChatMessageHandler>()
|
||||
.AddSingleton<SkillHandler>()
|
||||
.AddSingleton<ItemHander>()
|
||||
.AddSingleton<WorldHandler>()
|
||||
|
||||
.AddSingleton(
|
||||
typeof(PathfinderInterface),
|
||||
x => new L2jGeoDataPathfinder(
|
||||
config.GetValue<string>("GeoDataDirectory") ?? "",
|
||||
config.GetValue<ushort>("MaxPassableHeight")
|
||||
)
|
||||
)
|
||||
.AddSingleton(
|
||||
typeof(AsyncPathMoverInterface),
|
||||
x => new AsyncPathMover(
|
||||
x.GetRequiredService<WorldHandler>(),
|
||||
x.GetRequiredService<PathfinderInterface>(),
|
||||
config.GetValue<int>("PathNumberOfAttempts"),
|
||||
config.GetValue<double>("NodeWaitingTime"),
|
||||
config.GetValue<int>("NodeDistanceTolerance"),
|
||||
config.GetValue<int>("NextNodeDistanceTolerance")
|
||||
)
|
||||
)
|
||||
|
||||
.AddSingleton<Config>()
|
||||
.AddSingleton<TransitionBuilderLocator>()
|
||||
.AddSingleton(
|
||||
typeof(AIInterface),
|
||||
x => new AI(
|
||||
x.GetRequiredService<WorldHandler>(),
|
||||
x.GetRequiredService<Config>(),
|
||||
x.GetRequiredService<AsyncPathMoverInterface>(),
|
||||
x.GetRequiredService<TransitionBuilderLocator>()
|
||||
)
|
||||
)
|
||||
|
||||
.AddTransient(typeof(ConfigSerializerInterface), typeof(JsonConfigSerializer))
|
||||
.AddTransient(typeof(ConfigDeserializerInterface), typeof(JsonConfigDeserializer))
|
||||
|
||||
.AddSingleton<MainViewModel>()
|
||||
.AddSingleton<AIConfigViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Client/Application/Commands/RelayCommand.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.Commands
|
||||
{
|
||||
public class RelayCommand : ICommand
|
||||
{
|
||||
private Action<object?> execute;
|
||||
private Func<object?, bool>? canExecute;
|
||||
|
||||
public event EventHandler? CanExecuteChanged
|
||||
{
|
||||
add { CommandManager.RequerySuggested += value; }
|
||||
remove { CommandManager.RequerySuggested -= value; }
|
||||
}
|
||||
|
||||
public RelayCommand(Action<object?> execute, Func<object?, bool>? canExecute = null)
|
||||
{
|
||||
this.execute = execute;
|
||||
this.canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
return canExecute == null || canExecute(parameter);
|
||||
}
|
||||
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
execute(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
Client/Application/Components/Item.xaml
Normal file
@@ -0,0 +1,36 @@
|
||||
<Button x:Class="Client.Application.Components.Item"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client.Application.Components"
|
||||
xmlns:services="clr-namespace:Client.Application.Services"
|
||||
mc:Ignorable="d"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
x:Name="root">
|
||||
<Button.InputBindings>
|
||||
<MouseBinding Gesture="LeftClick" Command="{Binding MouseLeftClickCommand}" />
|
||||
<MouseBinding Gesture="RightClick" Command="{Binding MouseRightClickCommand}" />
|
||||
</Button.InputBindings>
|
||||
<Button.Resources>
|
||||
<services:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<services:NullToVisibilityConverter x:Key="NullToVisibilityConverter"/>
|
||||
<DataTemplate x:Key="ToolTipContent">
|
||||
<StackPanel MaxWidth="300">
|
||||
<TextBlock Text="{Binding Source={x:Reference root},Path=ItemName,Mode=OneWay}" TextWrapping="Wrap" FontWeight="Bold" FontSize="14" Margin="0,0,0,5" />
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Source={x:Reference root},Path=Description,Mode=OneWay}"
|
||||
/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</Button.Resources>
|
||||
<Button.Content>
|
||||
<Grid>
|
||||
<Image Source="{Binding Path=ImageSource,ElementName=root}" Height="32" Width="32" />
|
||||
</Grid>
|
||||
</Button.Content>
|
||||
<Button.ToolTip >
|
||||
<ContentControl ContentTemplate="{StaticResource ToolTipContent}"/>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
50
Client/Application/Components/Item.xaml.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Item.xaml
|
||||
/// </summary>
|
||||
public partial class Item : Button
|
||||
{
|
||||
public static readonly DependencyProperty ImageSourceProperty =
|
||||
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(Item), new PropertyMetadata(default(ImageSource)));
|
||||
public static readonly DependencyProperty ItemNameProperty =
|
||||
DependencyProperty.Register("ItemName", typeof(string), typeof(Item), new PropertyMetadata("Item"));
|
||||
public static readonly DependencyProperty DescriptionProperty =
|
||||
DependencyProperty.Register("Description", typeof(string), typeof(Item), new PropertyMetadata(""));
|
||||
|
||||
public Item()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ImageSource ImageSource
|
||||
{
|
||||
get { return (ImageSource)GetValue(ImageSourceProperty); }
|
||||
set { SetValue(ImageSourceProperty, value); }
|
||||
}
|
||||
public string ItemName
|
||||
{
|
||||
get { return (string)GetValue(ItemNameProperty); }
|
||||
set { SetValue(ItemNameProperty, value); }
|
||||
}
|
||||
public string? Description
|
||||
{
|
||||
get { return (string?)GetValue(DescriptionProperty); }
|
||||
set { SetValue(DescriptionProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
304
Client/Application/Components/Map.xaml
Normal file
@@ -0,0 +1,304 @@
|
||||
<ContentControl x:Class="Client.Application.Components.Map"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:services="clr-namespace:Client.Application.Services"
|
||||
xmlns:components="clr-namespace:Client.Application.Components"
|
||||
mc:Ignorable="d"
|
||||
services:SizeObserver.Observe="True"
|
||||
services:SizeObserver.ObservedWidth="{Binding ViewportWidth, Mode=OneWayToSource}"
|
||||
services:SizeObserver.ObservedHeight="{Binding ViewportHeight, Mode=OneWayToSource}"
|
||||
MouseWheel="ContentControl_MouseWheel"
|
||||
MouseLeave="ContentControl_MouseLeave"
|
||||
MouseMove="ContentControl_MouseMove"
|
||||
>
|
||||
<Grid Background="Transparent">
|
||||
<Grid.InputBindings>
|
||||
<MouseBinding Gesture="LeftClick" Command="{Binding MouseLeftClickCommand}" CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Grid}}" />
|
||||
</Grid.InputBindings>
|
||||
<ItemsControl ItemsSource="{Binding Path=Blocks}">
|
||||
<ItemsControl.Resources>
|
||||
<services:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
</ItemsControl.Resources>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas ClipToBounds="True"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Image
|
||||
Source="{Binding ImageSource,Mode=OneWay}"
|
||||
Width="{Binding Size,Mode=OneWay}"
|
||||
Height="{Binding Size,Mode=OneWay}"
|
||||
Visibility="{Binding Visible,Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
>
|
||||
<Image.RenderTransform>
|
||||
<TranslateTransform X="{Binding DeltaX}" Y="{Binding DeltaY}"/>
|
||||
</Image.RenderTransform>
|
||||
</Image>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Grid DataContext="{Binding CombatZone}" ClipToBounds="True">
|
||||
<Path StrokeThickness="2" Fill="#1100ff00" Stroke="#3300ff00" >
|
||||
<Path.Data>
|
||||
<EllipseGeometry
|
||||
RadiusX="{Binding Radius,Mode=OneWay}"
|
||||
RadiusY="{Binding Radius,Mode=OneWay}"/>
|
||||
</Path.Data>
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="{Binding Center.X,Mode=OneWay}" Y="{Binding Center.Y,Mode=OneWay}"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Grid>
|
||||
<ItemsControl ItemsSource="{Binding Path=Creatures}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas ClipToBounds="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Path x:Name="CreatureAggroRadius" StrokeThickness="2" Visibility="Hidden" Fill="#11ff0000" Stroke="#33ff0000">
|
||||
<Path.Data>
|
||||
<EllipseGeometry
|
||||
RadiusX="{Binding AggroRadius,Mode=OneWay}"
|
||||
RadiusY="{Binding AggroRadius,Mode=OneWay}" />
|
||||
</Path.Data>
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="{Binding Position.X,Mode=OneWay}" Y="{Binding Position.Y,Mode=OneWay}"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding IsAggressive,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="CreatureAggroRadius" Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding Path=Creatures}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas ClipToBounds="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid x:Name="CreatureMain">
|
||||
<Grid.InputBindings>
|
||||
<MouseBinding Gesture="LeftClick" Command="{Binding MouseLeftClickCommand}" />
|
||||
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding MouseLeftDoubleClickCommand}" />
|
||||
<MouseBinding Gesture="RightClick" Command="{Binding MouseRightClickCommand}" />
|
||||
</Grid.InputBindings>
|
||||
<Path x:Name="CreatureBody" StrokeThickness="2" Fill="Transparent">
|
||||
<Path.Data>
|
||||
<EllipseGeometry
|
||||
RadiusX="{Binding Radius,Mode=OneWay}"
|
||||
RadiusY="{Binding Radius,Mode=OneWay}" />
|
||||
</Path.Data>
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="{Binding Position.X,Mode=OneWay}" Y="{Binding Position.Y,Mode=OneWay}"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
<Line x:Name="CreatureDirection" X1="0" Y1="0" X2="{Binding Direction.X,Mode=OneWay}" Y2="{Binding Direction.Y,Mode=OneWay}" StrokeThickness="2">
|
||||
<Line.RenderTransform>
|
||||
<TranslateTransform X="{Binding Position.X,Mode=OneWay}" Y="{Binding Position.Y,Mode=OneWay}"/>
|
||||
</Line.RenderTransform>
|
||||
</Line>
|
||||
</Grid>
|
||||
<Grid x:Name="CreatureName" Visibility="Hidden" VerticalAlignment="Top" HorizontalAlignment="Left">
|
||||
<Grid.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="-2" ScaleY="-1" />
|
||||
<TranslateTransform
|
||||
X="{Binding Path=ActualWidth,RelativeSource={RelativeSource AncestorType=Grid}}"
|
||||
Y="{Binding Path=ActualHeight,RelativeSource={RelativeSource AncestorType=Grid}}"
|
||||
/>
|
||||
<ScaleTransform ScaleX="-0.5" ScaleY="-1" />
|
||||
<ScaleTransform ScaleY="-0.5" />
|
||||
<TranslateTransform Y="{Binding Radius}" />
|
||||
<ScaleTransform ScaleY="-2" />
|
||||
<TranslateTransform X="{Binding Position.X,Mode=OneWay}" Y="{Binding Position.Y,Mode=OneWay}"/>
|
||||
</TransformGroup>
|
||||
</Grid.RenderTransform>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="{Binding Name,Mode=OneWay}" Foreground="Black">
|
||||
<TextBlock.Effect>
|
||||
<BlurEffect
|
||||
Radius="2"
|
||||
KernelType="Box"/>
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding Name,Mode=OneWay}" Foreground="White" />
|
||||
<components:StatsBar
|
||||
Grid.Row="1"
|
||||
BackgroundSource="/Assets/icons/ps_hpbar_back.png"
|
||||
ForegroundSource="/Assets/icons/ps_hpbar.png"
|
||||
Current="{Binding VitalStats.Hp}"
|
||||
Total="{Binding VitalStats.MaxHp}"
|
||||
Height="{Binding Radius}"
|
||||
OnlyBar="True"
|
||||
Margin="0 2 0 0"
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding Type,Mode=OneWay}" Value="NPC">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="DarkGreen" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="DarkGreen" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsHostile,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="LimeGreen" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="LimeGreen" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsDead,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="Gray" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="Gray" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Type,Mode=OneWay}" Value="Player">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="Blue" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="Blue" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Type,Mode=OneWay}" Value="Hero">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="Black" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="Black" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsAttacker,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="Red" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="Red" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsSweepable,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="CreatureBody" Property="Stroke" Value="Magenta" />
|
||||
<Setter TargetName="CreatureDirection" Property="Stroke" Value="Magenta" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsTarget,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="CreatureName" Property="Visibility" Value="Visible" />
|
||||
</DataTrigger>
|
||||
<Trigger SourceName="CreatureMain" Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="CreatureName" Property="Visibility" Value="Visible"></Setter>
|
||||
</Trigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding Path=Drops}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas ClipToBounds="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid x:Name="DropMain">
|
||||
<Grid.InputBindings>
|
||||
<MouseBinding Gesture="LeftClick" Command="{Binding MouseLeftClickCommand}" />
|
||||
<MouseBinding Gesture="RightClick" Command="{Binding MouseRightClickCommand}" />
|
||||
</Grid.InputBindings>
|
||||
<Path StrokeThickness="2" Stroke="Gold" Fill="Transparent">
|
||||
<Path.Data>
|
||||
<EllipseGeometry
|
||||
RadiusX="{Binding Radius,Mode=OneWay}"
|
||||
RadiusY="{Binding Radius,Mode=OneWay}" />
|
||||
</Path.Data>
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="{Binding Position.X,Mode=OneWay}" Y="{Binding Position.Y,Mode=OneWay}"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Grid>
|
||||
<Grid x:Name="DropName" Visibility="Hidden" VerticalAlignment="Top" HorizontalAlignment="Left">
|
||||
<Grid.RenderTransform>
|
||||
<TransformGroup>
|
||||
<ScaleTransform ScaleX="-2" ScaleY="-1" />
|
||||
<TranslateTransform
|
||||
X="{Binding Path=ActualWidth,RelativeSource={RelativeSource AncestorType=Grid}}"
|
||||
Y="{Binding Path=ActualHeight,RelativeSource={RelativeSource AncestorType=Grid}}"
|
||||
/>
|
||||
<ScaleTransform ScaleX="-0.5" ScaleY="-1" />
|
||||
<ScaleTransform ScaleY="-0.5" />
|
||||
<TranslateTransform Y="{Binding Radius}" />
|
||||
<ScaleTransform ScaleY="-2" />
|
||||
<TranslateTransform X="{Binding Position.X,Mode=OneWay}" Y="{Binding Position.Y,Mode=OneWay}"/>
|
||||
</TransformGroup>
|
||||
</Grid.RenderTransform>
|
||||
<TextBlock Text="{Binding Name,Mode=OneWay}" Foreground="Black" FontSize="11">
|
||||
<TextBlock.Effect>
|
||||
<BlurEffect
|
||||
Radius="2"
|
||||
KernelType="Box"/>
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding Name,Mode=OneWay}" Foreground="White" FontSize="11"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<Trigger SourceName="DropMain" Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="DropName" Property="Visibility" Value="Visible"></Setter>
|
||||
</Trigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<ItemsControl ItemsSource="{Binding Path=Path}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<Canvas ClipToBounds="True" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Line
|
||||
X1="{Binding From.X}"
|
||||
Y1="{Binding From.Y}"
|
||||
X2="{Binding To.X}"
|
||||
Y2="{Binding To.Y}"
|
||||
Stroke="Red"
|
||||
StrokeDashArray="1 3"
|
||||
StrokeThickness="1"
|
||||
/>
|
||||
<Path
|
||||
Stroke="Red"
|
||||
StrokeThickness="1"
|
||||
>
|
||||
<Path.Data>
|
||||
<EllipseGeometry
|
||||
RadiusX="{Binding Radius,Mode=OneWay}"
|
||||
RadiusY="{Binding Radius,Mode=OneWay}" />
|
||||
</Path.Data>
|
||||
<Path.RenderTransform>
|
||||
<TranslateTransform X="{Binding To.X,Mode=OneWay}" Y="{Binding To.Y,Mode=OneWay}"/>
|
||||
</Path.RenderTransform>
|
||||
</Path>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Right" Background="#66ffffff">
|
||||
<Grid Margin="10 5">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="90"></ColumnDefinition>
|
||||
<ColumnDefinition Width="30"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Padding="0 0 0 3">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0:F0}, {1:F0}">
|
||||
<Binding Path="MousePosition.X" Mode="OneWay"/>
|
||||
<Binding Path="MousePosition.Y" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Column="1" Text="{Binding Scale,Mode=OneWay,StringFormat='{}1:{0}'}" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ContentControl>
|
||||
55
Client/Application/Components/Map.xaml.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Client.Application.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Map.xaml
|
||||
/// </summary>
|
||||
public partial class Map : ContentControl
|
||||
{
|
||||
public Map()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ContentControl_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
if (DataContext is MapViewModel)
|
||||
{
|
||||
var model = (MapViewModel)DataContext;
|
||||
model.OnMouseWheel(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ContentControl_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (DataContext is MapViewModel)
|
||||
{
|
||||
var model = (MapViewModel)DataContext;
|
||||
model.OnMouseLeave(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ContentControl_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (DataContext is MapViewModel)
|
||||
{
|
||||
var model = (MapViewModel)DataContext;
|
||||
model.OnMouseMove(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
102
Client/Application/Components/MultipleObjectSelector.xaml
Normal file
@@ -0,0 +1,102 @@
|
||||
<UserControl x:Class="Client.Application.Components.MultipleObjectSelector"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Client.Application.Components"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
x:Name="root">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="{Binding Header,ElementName=root}" />
|
||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||
<TextBox
|
||||
x:Name="sourceSearch"
|
||||
HorizontalAlignment="Stretch">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="KeyUp">
|
||||
<i:InvokeCommandAction
|
||||
Command="{x:Static local:MultipleObjectSelector.SearchSourceCommand}"
|
||||
CommandParameter="{Binding Text,ElementName=sourceSearch}"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
<ListBox
|
||||
ItemsSource="{Binding Source,ElementName=root}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Height="100"
|
||||
Width="Auto"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
x:Name="source">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}">
|
||||
<TextBlock.InputBindings>
|
||||
<MouseBinding
|
||||
MouseAction="LeftDoubleClick"
|
||||
Command="{x:Static local:MultipleObjectSelector.AddItemCommand}"
|
||||
CommandParameter="{Binding SelectedValue,ElementName=source}"/>
|
||||
</TextBlock.InputBindings>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="2" Grid.Column="0">
|
||||
<Button
|
||||
Width="20"
|
||||
Command="{x:Static local:MultipleObjectSelector.AddItemCommand}"
|
||||
CommandParameter="{Binding SelectedValue,ElementName=source}"
|
||||
>↓</Button>
|
||||
<Button
|
||||
Width="20"
|
||||
Command="{x:Static local:MultipleObjectSelector.RemoveItemCommand}"
|
||||
CommandParameter="{Binding SelectedValue,ElementName=target}"
|
||||
>↑</Button>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="3" Grid.Column="0">
|
||||
<TextBox
|
||||
x:Name="targetSearch"
|
||||
HorizontalAlignment="Stretch">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="KeyUp">
|
||||
<i:InvokeCommandAction
|
||||
Command="{x:Static local:MultipleObjectSelector.SearchTargetCommand}"
|
||||
CommandParameter="{Binding Text,ElementName=targetSearch}"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</TextBox>
|
||||
<ListBox
|
||||
ItemsSource="{Binding Target,ElementName=root}"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Height="100"
|
||||
Width="Auto"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
x:Name="target">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name}">
|
||||
<TextBlock.InputBindings>
|
||||
<MouseBinding
|
||||
MouseAction="LeftDoubleClick"
|
||||
Command="{x:Static local:MultipleObjectSelector.RemoveItemCommand}"
|
||||
CommandParameter="{Binding SelectedValue,ElementName=target}"/>
|
||||
</TextBlock.InputBindings>
|
||||
</TextBlock>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
109
Client/Application/Components/MultipleObjectSelector.xaml.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Client.Domain.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MobSelector.xaml
|
||||
/// </summary>
|
||||
public partial class MultipleObjectSelector : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty SourceProperty =
|
||||
DependencyProperty.Register("Source", typeof(ICollection<ObjectInfo>), typeof(MultipleObjectSelector), new PropertyMetadata(default(ICollection<ObjectInfo>)));
|
||||
public ICollection<ObjectInfo> Source
|
||||
{
|
||||
get { return (ICollection<ObjectInfo>)GetValue(SourceProperty); }
|
||||
set { SetValue(SourceProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty TargetProperty =
|
||||
DependencyProperty.Register("Target", typeof(ICollection<ObjectInfo>), typeof(MultipleObjectSelector), new PropertyMetadata(default(ICollection<ObjectInfo>)));
|
||||
public ICollection<ObjectInfo> Target
|
||||
{
|
||||
get { return (ICollection<ObjectInfo>)GetValue(TargetProperty); }
|
||||
set { SetValue(TargetProperty, value); }
|
||||
}
|
||||
public string Header
|
||||
{
|
||||
get { return (string)GetValue(HeaderProperty); }
|
||||
set { SetValue(HeaderProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty HeaderProperty =
|
||||
DependencyProperty.Register("Header", typeof(string), typeof(MultipleObjectSelector), new PropertyMetadata(""));
|
||||
|
||||
public static RoutedUICommand AddItemCommand { get; } = new RoutedUICommand(
|
||||
"Add item",
|
||||
nameof(AddItemCommand),
|
||||
typeof(MultipleObjectSelector)
|
||||
);
|
||||
public static RoutedUICommand RemoveItemCommand { get; } = new RoutedUICommand(
|
||||
"Remove item",
|
||||
nameof(RemoveItemCommand),
|
||||
typeof(MultipleObjectSelector)
|
||||
);
|
||||
public static RoutedUICommand SearchSourceCommand { get; } = new RoutedUICommand(
|
||||
"Search in source",
|
||||
nameof(SearchSourceCommand),
|
||||
typeof(MultipleObjectSelector)
|
||||
);
|
||||
public static RoutedUICommand SearchTargetCommand { get; } = new RoutedUICommand(
|
||||
"Search in target",
|
||||
nameof(SearchTargetCommand),
|
||||
typeof(MultipleObjectSelector)
|
||||
);
|
||||
|
||||
|
||||
public MultipleObjectSelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
CommandBindings.Add(new CommandBinding(AddItemCommand, AddItem));
|
||||
CommandBindings.Add(new CommandBinding(RemoveItemCommand, RemoveItem));
|
||||
CommandBindings.Add(new CommandBinding(SearchSourceCommand, SearchSource));
|
||||
CommandBindings.Add(new CommandBinding(SearchTargetCommand, SearchTarget));
|
||||
}
|
||||
|
||||
private void AddItem(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
var item = e.Parameter as ObjectInfo;
|
||||
if (item != null)
|
||||
{
|
||||
Source.Remove(item);
|
||||
Target.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveItem(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
var item = e.Parameter as ObjectInfo;
|
||||
if (item != null)
|
||||
{
|
||||
Target.Remove(item);
|
||||
Source.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchSource(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
var searchPredicate = (string)e.Parameter ?? null;
|
||||
|
||||
if (searchPredicate != null)
|
||||
{
|
||||
CollectionViewSource.GetDefaultView(Source).Filter = item => (item as ObjectInfo)?.Name.Contains(searchPredicate, StringComparison.OrdinalIgnoreCase) ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchTarget(object sender, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
var searchPredicate = (string)e.Parameter ?? null;
|
||||
|
||||
if (searchPredicate != null)
|
||||
{
|
||||
CollectionViewSource.GetDefaultView(Target).Filter = item => (item as ObjectInfo)?.Name.Contains(searchPredicate, StringComparison.OrdinalIgnoreCase) ?? false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Client/Application/Components/ObjectSelector.xaml
Normal file
@@ -0,0 +1,30 @@
|
||||
<UserControl x:Class="Client.Application.Components.ObjectSelector"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Client.Application.Components"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
mc:Ignorable="d"
|
||||
x:Name="root">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Content="{Binding Header,ElementName=root}" Grid.Row="0" Grid.Column="0"/>
|
||||
<ComboBox
|
||||
Grid.Row="1" Grid.Column="0"
|
||||
SelectedValuePath="Id"
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding Source,ElementName=root}"
|
||||
SelectedValue="{Binding SelectedValue,ElementName=root}"
|
||||
>
|
||||
<ComboBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ComboBox.ItemsPanel>
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
55
Client/Application/Components/ObjectSelector.xaml.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for SearchableCombobox.xaml
|
||||
/// </summary>
|
||||
public partial class ObjectSelector : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty SourceProperty =
|
||||
DependencyProperty.Register("Source", typeof(ICollection<ObjectInfo>), typeof(ObjectSelector), new PropertyMetadata(default(ICollection<ObjectInfo>)));
|
||||
public ICollection<ObjectInfo> Source
|
||||
{
|
||||
get { return (ICollection<ObjectInfo>)GetValue(SourceProperty); }
|
||||
set { SetValue(SourceProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SelectedValueProperty =
|
||||
DependencyProperty.Register("SelectedValue", typeof(object), typeof(ObjectSelector), new PropertyMetadata(default(object)));
|
||||
public object SelectedValue
|
||||
{
|
||||
get { return GetValue(SelectedValueProperty); }
|
||||
set { SetValue(SelectedValueProperty, value); }
|
||||
}
|
||||
|
||||
public string Header
|
||||
{
|
||||
get { return (string)GetValue(HeaderProperty); }
|
||||
set { SetValue(HeaderProperty, value); }
|
||||
}
|
||||
public static readonly DependencyProperty HeaderProperty =
|
||||
DependencyProperty.Register("Header", typeof(string), typeof(ObjectSelector), new PropertyMetadata(""));
|
||||
|
||||
public ObjectSelector()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
53
Client/Application/Components/Skill.xaml
Normal file
@@ -0,0 +1,53 @@
|
||||
<Button x:Class="Client.Application.Components.Skill"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client.Application.Components"
|
||||
xmlns:services="clr-namespace:Client.Application.Services"
|
||||
mc:Ignorable="d"
|
||||
IsEnabled="{Binding Path=IsButtonActive,ElementName=root,Mode=OneWay}"
|
||||
ToolTipService.ShowOnDisabled="True"
|
||||
x:Name="root"
|
||||
Command="{Binding MouseLeftClickCommand}">
|
||||
<Button.Resources>
|
||||
<services:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<services:NullToVisibilityConverter x:Key="NullToVisibilityConverter"/>
|
||||
<DataTemplate x:Key="ToolTipContent">
|
||||
<StackPanel MaxWidth="300">
|
||||
<TextBlock TextWrapping="Wrap" FontWeight="Bold" FontSize="14" Margin="0,0,0,5">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0} Lv {1}">
|
||||
<Binding Path="SkillName" Mode="OneWay" Source="{x:Reference root}"/>
|
||||
<Binding Path="Level" Mode="OneWay" Source="{x:Reference root}"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Source={x:Reference root},Path=Cost,Mode=OneWay,StringFormat='MP Cost {0}'}"
|
||||
Visibility="{Binding Source={x:Reference root},Path=Cost,Converter={StaticResource NullToVisibilityConverter},ConverterParameter=Hidden,Mode=OneWay}"
|
||||
/>
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Source={x:Reference root},Path=Range,Mode=OneWay,StringFormat='Range {0}'}"
|
||||
Visibility="{Binding Source={x:Reference root},Path=Range,Converter={StaticResource NullToVisibilityConverter},ConverterParameter=Hidden,Mode=OneWay}"
|
||||
/>
|
||||
<TextBlock
|
||||
TextWrapping="Wrap"
|
||||
Text="{Binding Source={x:Reference root},Path=Description,Mode=OneWay}"
|
||||
Visibility="{Binding Source={x:Reference root},Path=Description,Converter={StaticResource NullToVisibilityConverter},ConverterParameter=Hidden,Mode=OneWay}"
|
||||
/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</Button.Resources>
|
||||
<Button.Content>
|
||||
<Grid>
|
||||
<Image Source="{Binding Path=ImageSource,ElementName=root}" Height="32" Width="32" />
|
||||
<Rectangle Fill="Black" Opacity=".5" Visibility="{Binding Path=IsReadyToUse,ElementName=root,Converter={StaticResource BooleanToVisibilityConverter},ConverterParameter=Inverted,Mode=OneWay}"/>
|
||||
</Grid>
|
||||
</Button.Content>
|
||||
<Button.ToolTip >
|
||||
<ContentControl ContentTemplate="{StaticResource ToolTipContent}"/>
|
||||
</Button.ToolTip>
|
||||
</Button>
|
||||
105
Client/Application/Components/Skill.xaml.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Skill.xaml
|
||||
/// </summary>
|
||||
public partial class Skill : Button
|
||||
{
|
||||
public static readonly DependencyProperty IsButtonActiveProperty =
|
||||
DependencyProperty.Register("IsButtonActive", typeof(bool), typeof(Skill), new PropertyMetadata(true, null, OnCoerceButtonActivity));
|
||||
public static readonly DependencyProperty ImageSourceProperty =
|
||||
DependencyProperty.Register("ImageSource", typeof(ImageSource), typeof(Skill), new PropertyMetadata(default(ImageSource)));
|
||||
public static readonly DependencyProperty IsReadyToUseProperty =
|
||||
DependencyProperty.Register("IsReadyToUse", typeof(bool), typeof(Skill), new PropertyMetadata(true, OnButtonActivityChanged));
|
||||
public static readonly DependencyProperty SkillNameProperty =
|
||||
DependencyProperty.Register("SkillName", typeof(string), typeof(Skill), new PropertyMetadata("Skill"));
|
||||
public static readonly DependencyProperty LevelProperty =
|
||||
DependencyProperty.Register("Level", typeof(uint), typeof(Skill), new PropertyMetadata((uint)1));
|
||||
public static readonly DependencyProperty CostProperty =
|
||||
DependencyProperty.Register("Cost", typeof(uint?), typeof(Skill), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty RangeProperty =
|
||||
DependencyProperty.Register("Range", typeof(int?), typeof(Skill), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty DescriptionProperty =
|
||||
DependencyProperty.Register("Description", typeof(string), typeof(Skill), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty IsActiveProperty =
|
||||
DependencyProperty.Register("IsActive", typeof(bool), typeof(Skill), new PropertyMetadata(true, OnButtonActivityChanged));
|
||||
|
||||
private static void OnButtonActivityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var model = (Skill)d;
|
||||
model.CoerceValue(IsButtonActiveProperty);
|
||||
}
|
||||
|
||||
private static object OnCoerceButtonActivity(DependencyObject d, object baseValue)
|
||||
{
|
||||
var model = (Skill)d;
|
||||
|
||||
return model.IsReadyToUse && model.IsActive;
|
||||
}
|
||||
|
||||
public Skill()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public bool IsButtonActive
|
||||
{
|
||||
get { return (bool)GetValue(IsButtonActiveProperty); }
|
||||
set { SetValue(IsButtonActiveProperty, value); }
|
||||
}
|
||||
public ImageSource ImageSource
|
||||
{
|
||||
get { return (ImageSource)GetValue(ImageSourceProperty); }
|
||||
set { SetValue(ImageSourceProperty, value); }
|
||||
}
|
||||
public bool IsReadyToUse
|
||||
{
|
||||
get { return (bool)GetValue(IsReadyToUseProperty); }
|
||||
set { SetValue(IsReadyToUseProperty, value); }
|
||||
}
|
||||
public string SkillName
|
||||
{
|
||||
get { return (string)GetValue(SkillNameProperty); }
|
||||
set { SetValue(SkillNameProperty, value); }
|
||||
}
|
||||
public uint Level
|
||||
{
|
||||
get { return (uint)GetValue(LevelProperty); }
|
||||
set { SetValue(LevelProperty, value); }
|
||||
}
|
||||
public uint? Cost
|
||||
{
|
||||
get { return (uint?)GetValue(CostProperty); }
|
||||
set { SetValue(CostProperty, value); }
|
||||
}
|
||||
public int? Range
|
||||
{
|
||||
get { return (int?)GetValue(RangeProperty); }
|
||||
set { SetValue(RangeProperty, value); }
|
||||
}
|
||||
public string? Description
|
||||
{
|
||||
get { return (string?)GetValue(DescriptionProperty); }
|
||||
set { SetValue(DescriptionProperty, value); }
|
||||
}
|
||||
public bool IsActive
|
||||
{
|
||||
get { return (bool)GetValue(IsActiveProperty); }
|
||||
set { SetValue(IsActiveProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Client/Application/Components/StatsBar.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<UserControl x:Class="Client.Application.Components.StatsBar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client.Application.Components"
|
||||
x:Name="root"
|
||||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Image Stretch="Fill" Source="{Binding BackgroundSource,ElementName=root,Mode=OneWay}" />
|
||||
<Image Stretch="Fill" Source="{Binding ForegroundSource,ElementName=root,Mode=OneWay}" Width="{Binding ForegroundWidth,ElementName=root,Mode=OneWay}" HorizontalAlignment="Left" />
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Text,ElementName=root,Mode=OneWay}" Foreground="Black">
|
||||
<TextBlock.Effect>
|
||||
<BlurEffect
|
||||
Radius="1.0"
|
||||
KernelType="Box"/>
|
||||
</TextBlock.Effect>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding Text,ElementName=root,Mode=OneWay}" Foreground="White" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
141
Client/Application/Components/StatsBar.xaml.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Components
|
||||
{
|
||||
public partial class StatsBar : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty BackgroundSourceProperty =
|
||||
DependencyProperty.Register("BackgroundSource", typeof(ImageSource), typeof(StatsBar), new PropertyMetadata(default(ImageSource)));
|
||||
public static readonly DependencyProperty ForegroundSourceProperty =
|
||||
DependencyProperty.Register("ForegroundSource", typeof(ImageSource), typeof(StatsBar), new PropertyMetadata(default(ImageSource)));
|
||||
public static readonly DependencyProperty CurrentProperty =
|
||||
DependencyProperty.Register("Current", typeof(double), typeof(StatsBar), new PropertyMetadata(0.0, OnDataChanged));
|
||||
public static readonly DependencyProperty TotalProperty =
|
||||
DependencyProperty.Register("Total", typeof(double), typeof(StatsBar), new PropertyMetadata(0.0, OnDataChanged));
|
||||
public static readonly DependencyProperty FormatProperty =
|
||||
DependencyProperty.Register("Format", typeof(string), typeof(StatsBar), new PropertyMetadata("{0}/{1}", OnFormatChanged));
|
||||
public static readonly DependencyProperty ForegroundWidthProperty =
|
||||
DependencyProperty.Register("ForegroundWidth", typeof(double), typeof(StatsBar), new PropertyMetadata(0.0, null, OnCoerceForegroundWidth));
|
||||
public static readonly DependencyProperty TextProperty =
|
||||
DependencyProperty.Register("Text", typeof(string), typeof(StatsBar), new PropertyMetadata("", null, OnCoerceText));
|
||||
public static readonly DependencyProperty OnlyBarProperty =
|
||||
DependencyProperty.Register("OnlyBar", typeof(bool), typeof(StatsBar), new PropertyMetadata(false, OnOnlyBarChanged));
|
||||
|
||||
private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var model = (StatsBar)d;
|
||||
model.CoerceValue(ForegroundWidthProperty);
|
||||
model.CoerceValue(TextProperty);
|
||||
}
|
||||
|
||||
private static void OnOnlyBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var model = (StatsBar)d;
|
||||
model.CoerceValue(TextProperty);
|
||||
}
|
||||
|
||||
private static void OnFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var model = (StatsBar)d;
|
||||
model.CoerceValue(TextProperty);
|
||||
}
|
||||
|
||||
private static object OnCoerceForegroundWidth(DependencyObject d, object baseValue)
|
||||
{
|
||||
var model = (StatsBar)d;
|
||||
var actualWidth = (double)model.GetValue(ActualWidthProperty);
|
||||
|
||||
return actualWidth / 100 * model.GetPercent();
|
||||
}
|
||||
|
||||
private static object OnCoerceText(DependencyObject d, object baseValue)
|
||||
{
|
||||
var model = (StatsBar)d;
|
||||
|
||||
return model.OnlyBar ? "" : string.Format(model.Format, model.Current, model.Total, model.GetPercent());
|
||||
}
|
||||
|
||||
public StatsBar()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
SizeChanged += StatsBar_SizeChanged;
|
||||
}
|
||||
|
||||
private void StatsBar_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (e.WidthChanged)
|
||||
{
|
||||
var model = (StatsBar)sender;
|
||||
model.CoerceValue(ForegroundWidthProperty);
|
||||
}
|
||||
}
|
||||
|
||||
private double GetPercent()
|
||||
{
|
||||
var percent = Current;
|
||||
if (Total > 0)
|
||||
{
|
||||
percent = Current / Total * 100;
|
||||
}
|
||||
|
||||
return percent;
|
||||
}
|
||||
|
||||
public ImageSource BackgroundSource
|
||||
{
|
||||
get { return (ImageSource)GetValue(BackgroundSourceProperty); }
|
||||
set { SetValue(BackgroundSourceProperty, value); }
|
||||
}
|
||||
public ImageSource ForegroundSource
|
||||
{
|
||||
get { return (ImageSource)GetValue(ForegroundSourceProperty); }
|
||||
set { SetValue(ForegroundSourceProperty, value); }
|
||||
}
|
||||
public double ForegroundWidth
|
||||
{
|
||||
get { return (double)GetValue(ForegroundWidthProperty); }
|
||||
set { SetValue(ForegroundWidthProperty, value); }
|
||||
}
|
||||
public double Current
|
||||
{
|
||||
get { return (double)GetValue(CurrentProperty); }
|
||||
set { SetValue(CurrentProperty, value); }
|
||||
}
|
||||
public double Total
|
||||
{
|
||||
get { return (double)GetValue(TotalProperty); }
|
||||
set { SetValue(TotalProperty, value); }
|
||||
}
|
||||
public string Text
|
||||
{
|
||||
get { return (string)GetValue(TextProperty); }
|
||||
set { SetValue(TextProperty, value); }
|
||||
}
|
||||
public string Format
|
||||
{
|
||||
get { return (string)GetValue(FormatProperty); }
|
||||
set { SetValue(FormatProperty, value); }
|
||||
}
|
||||
public bool OnlyBar
|
||||
{
|
||||
get { return (bool)GetValue(OnlyBarProperty); }
|
||||
set { SetValue(OnlyBarProperty, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Client/Application/Services/BooleanToVisibilityConverter.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Client.Application.Services
|
||||
{
|
||||
public class BooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var isInverted = parameter == null ? false : true;
|
||||
var preparedValue = value == null ? false : (bool)value;
|
||||
preparedValue = isInverted ? !preparedValue : preparedValue;
|
||||
return innerConverter.Convert(preparedValue, targetType, parameter, culture);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
System.Windows.Controls.BooleanToVisibilityConverter innerConverter = new System.Windows.Controls.BooleanToVisibilityConverter();
|
||||
}
|
||||
}
|
||||
37
Client/Application/Services/EqualityConverter.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Client.Application.Services
|
||||
{
|
||||
public class EqualityConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Length < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var firstValue = values.First();
|
||||
for (var i = 1; i < values.Length; i++)
|
||||
{
|
||||
if (!firstValue.Equals(values[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Client/Application/Services/NullToVisibilityConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Client.Application.Services
|
||||
{
|
||||
public class NullToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var isCollapsedWhenNull = parameter == null ? false : true;
|
||||
var nullVisibility = isCollapsedWhenNull ? Visibility.Collapsed : Visibility.Hidden;
|
||||
return value == null ? nullVisibility : Visibility.Visible;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
92
Client/Application/Services/SizeObserver.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace Client.Application.Services
|
||||
{
|
||||
public static class SizeObserver
|
||||
{
|
||||
public static readonly DependencyProperty ObserveProperty = DependencyProperty.RegisterAttached(
|
||||
"Observe",
|
||||
typeof(bool),
|
||||
typeof(SizeObserver),
|
||||
new FrameworkPropertyMetadata(OnObserveChanged));
|
||||
|
||||
public static readonly DependencyProperty ObservedWidthProperty = DependencyProperty.RegisterAttached(
|
||||
"ObservedWidth",
|
||||
typeof(double),
|
||||
typeof(SizeObserver));
|
||||
|
||||
public static readonly DependencyProperty ObservedHeightProperty = DependencyProperty.RegisterAttached(
|
||||
"ObservedHeight",
|
||||
typeof(double),
|
||||
typeof(SizeObserver));
|
||||
|
||||
public static bool GetObserve(FrameworkElement frameworkElement)
|
||||
{
|
||||
return (bool)frameworkElement.GetValue(ObserveProperty);
|
||||
}
|
||||
|
||||
public static void SetObserve(FrameworkElement frameworkElement, bool observe)
|
||||
{
|
||||
frameworkElement.SetValue(ObserveProperty, observe);
|
||||
}
|
||||
|
||||
public static double GetObservedWidth(FrameworkElement frameworkElement)
|
||||
{
|
||||
return (double)frameworkElement.GetValue(ObservedWidthProperty);
|
||||
}
|
||||
|
||||
public static void SetObservedWidth(FrameworkElement frameworkElement, double observedWidth)
|
||||
{
|
||||
frameworkElement.SetValue(ObservedWidthProperty, observedWidth);
|
||||
}
|
||||
|
||||
public static double GetObservedHeight(FrameworkElement frameworkElement)
|
||||
{
|
||||
return (double)frameworkElement.GetValue(ObservedHeightProperty);
|
||||
}
|
||||
|
||||
public static void SetObservedHeight(FrameworkElement frameworkElement, double observedHeight)
|
||||
{
|
||||
frameworkElement.SetValue(ObservedHeightProperty, observedHeight);
|
||||
}
|
||||
|
||||
private static void OnObserveChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var frameworkElement = (FrameworkElement)dependencyObject;
|
||||
|
||||
if ((bool)e.NewValue)
|
||||
{
|
||||
frameworkElement.Loaded += OnFrameworkElementLoaded;
|
||||
}
|
||||
else
|
||||
{
|
||||
frameworkElement.SizeChanged -= OnFrameworkElementSizeChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnFrameworkElementLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var frameworkElement = (FrameworkElement)sender;
|
||||
|
||||
frameworkElement.SizeChanged += OnFrameworkElementSizeChanged;
|
||||
frameworkElement.Loaded -= OnFrameworkElementLoaded;
|
||||
UpdateObservedSizesForFrameworkElement(frameworkElement);
|
||||
}
|
||||
|
||||
private static void OnFrameworkElementSizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
UpdateObservedSizesForFrameworkElement((FrameworkElement)sender);
|
||||
}
|
||||
|
||||
private static void UpdateObservedSizesForFrameworkElement(FrameworkElement frameworkElement)
|
||||
{
|
||||
frameworkElement.SetCurrentValue(ObservedWidthProperty, frameworkElement.ActualWidth);
|
||||
frameworkElement.SetCurrentValue(ObservedHeightProperty, frameworkElement.ActualHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Client/Application/ViewModels/AICombatZoneMapViewModel.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using Client.Domain.AI.Combat;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class AICombatZoneMapViewModel : ObservableObject
|
||||
{
|
||||
public void MapUpdated(float scale, float viewportWidth, float viewportHeight)
|
||||
{
|
||||
Scale = scale;
|
||||
VieportSize = new Vector3(viewportWidth, viewportHeight, 0);
|
||||
}
|
||||
|
||||
public AICombatZoneMapViewModel(CombatZone combatZone, Hero hero)
|
||||
{
|
||||
this.combatZone = combatZone;
|
||||
this.hero = hero;
|
||||
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
combatZone.PropertyChanged += CombatZone_PropertyChanged;
|
||||
combatZone.Center.PropertyChanged += CombatZoneCenter_PropertyChanged;
|
||||
}
|
||||
|
||||
private void CombatZoneCenter_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Center");
|
||||
}
|
||||
|
||||
private void CombatZone_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Radius")
|
||||
{
|
||||
OnPropertyChanged("Radius");
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 Center => new Vector3(
|
||||
(combatZone.Center.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(combatZone.Center.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
|
||||
public float Radius => combatZone.Radius / scale;
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale != value)
|
||||
{
|
||||
scale = value;
|
||||
OnPropertyChanged("Center");
|
||||
OnPropertyChanged("Radius");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 VieportSize
|
||||
{
|
||||
get => vieportSize;
|
||||
set
|
||||
{
|
||||
if (vieportSize != value)
|
||||
{
|
||||
vieportSize = value;
|
||||
OnPropertyChanged("Center");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Center");
|
||||
}
|
||||
|
||||
private readonly CombatZone combatZone;
|
||||
private readonly Hero hero;
|
||||
private float scale = 1;
|
||||
private Vector3 vieportSize = new Vector3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
344
Client/Application/ViewModels/AIConfigViewModel.cs
Normal file
@@ -0,0 +1,344 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Application.Components;
|
||||
using Client.Application.Views;
|
||||
using Client.Domain.AI;
|
||||
using Client.Domain.AI.IO;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Events;
|
||||
using Client.Domain.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class AIConfigViewModel :
|
||||
ObservableObject,
|
||||
EventHandlerInterface<HeroCreatedEvent>,
|
||||
EventHandlerInterface<HeroDeletedEvent>
|
||||
{
|
||||
public void Handle(HeroCreatedEvent @event)
|
||||
{
|
||||
hero = @event.Hero;
|
||||
}
|
||||
|
||||
public void Handle(HeroDeletedEvent @event)
|
||||
{
|
||||
hero = null;
|
||||
}
|
||||
|
||||
public class SkillCondition : ObservableObject
|
||||
{
|
||||
private uint id;
|
||||
private byte maxTargetPercentHp = 100;
|
||||
private byte minPlayerPercentMp = 0;
|
||||
private byte maxPlayerPercentHp = 100;
|
||||
|
||||
public uint Id { get => id; set { if (value != id) { id = value; OnPropertyChanged(); } } }
|
||||
public byte MaxTargetPercentHp { get => maxTargetPercentHp; set { if (value != maxTargetPercentHp) { maxTargetPercentHp = value; OnPropertyChanged(); } } }
|
||||
public byte MinPlayerPercentMp { get => minPlayerPercentMp; set { if (value != minPlayerPercentMp) { minPlayerPercentMp = value; OnPropertyChanged(); } } }
|
||||
public byte MaxPlayerPercentHp { get => maxPlayerPercentHp; set { if (value != maxPlayerPercentHp) { maxPlayerPercentHp = value; OnPropertyChanged(); } } }
|
||||
}
|
||||
|
||||
public class CombatZone : ObservableObject
|
||||
{
|
||||
private float x = 0;
|
||||
private float y = 0;
|
||||
private float radius = 0;
|
||||
|
||||
public float X { get => x; set { if (value != x) { x = value; OnPropertyChanged(); } } }
|
||||
public float Y { get => y; set { if (value != y) { y = value; OnPropertyChanged(); } } }
|
||||
public float Radius { get => radius; set { if (value != radius) { radius = value; OnPropertyChanged(); } } }
|
||||
}
|
||||
|
||||
public AIConfigViewModel(NpcInfoHelperInterface npcInfoHelper, ItemInfoHelperInterface itemInfoHelper, SkillInfoHelperInterface skillInfoHelper, Config config, ConfigSerializerInterface configSerializer, ConfigDeserializerInterface configDeserializer)
|
||||
{
|
||||
this.npcInfoHelper = npcInfoHelper;
|
||||
this.itemInfoHelper = itemInfoHelper;
|
||||
this.skillInfoHelper = skillInfoHelper;
|
||||
this.config = config;
|
||||
this.configSerializer = configSerializer;
|
||||
this.configDeserializer = configDeserializer;
|
||||
SaveDialogCommand = new RelayCommand(OnSaveDialog);
|
||||
OpenDialogCommand = new RelayCommand(OnOpenDialog);
|
||||
SaveCommand = new RelayCommand(OnSave);
|
||||
ResetCommand = new RelayCommand(OnReset);
|
||||
GetHeroPosition = new RelayCommand(OnGetHeroPosition);
|
||||
Skills = new ObservableCollection<ObjectInfo>(skillInfoHelper.GetAllSkills().Select(x => x.Value).Where(x => x.IsActive).ToList());
|
||||
}
|
||||
|
||||
public ICommand SaveDialogCommand { get; }
|
||||
public ICommand OpenDialogCommand { get; }
|
||||
public ICommand SaveCommand { get; }
|
||||
public ICommand ResetCommand { get; }
|
||||
public ICommand GetHeroPosition { get; }
|
||||
public Action? Close { get; set; }
|
||||
public Action<string>? OpenSaveDialog { get; set; }
|
||||
public Func<string?>? OpenOpenDialog { get; set; }
|
||||
|
||||
public ObservableCollection<ObjectInfo> Skills { get; set; }
|
||||
|
||||
public uint MobsMaxDeltaZ { get => mobsMaxDeltaZ; set { if (value != mobsMaxDeltaZ) { mobsMaxDeltaZ = value; OnPropertyChanged(); } } }
|
||||
public ObservableCollection<ObjectInfo> ExcludedMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> SelectedExcludedMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> IncludedMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> SelectedIncludedMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public byte? MobLevelLowerLimit { get => mobLevelLowerLimit; set { if (value != mobLevelLowerLimit) { mobLevelLowerLimit = value; OnPropertyChanged(); } } }
|
||||
public byte? MobLevelUpperLimit { get => mobLevelUpperLimit; set { if (value != mobLevelUpperLimit) { mobLevelUpperLimit = value; OnPropertyChanged(); } } }
|
||||
public ObservableCollection<ObjectInfo> ExcludedSpoilMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> SelectedExcludedSpoilMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> IncludedSpoilMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> SelectedIncludedSpoilMobs { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public bool SpoilIfPossible { get => spoilIfPossible; set { if (value != spoilIfPossible) { spoilIfPossible = value; OnPropertyChanged(); } } }
|
||||
public bool SpoilIsPriority { get => spoilIsPriority; set { if (value != spoilIsPriority) { spoilIsPriority = value; OnPropertyChanged(); } } }
|
||||
public uint SpoilSkillId { get => spoilSkillId; set { if (value != spoilSkillId) { spoilSkillId = value; OnPropertyChanged(); } } }
|
||||
public uint SweeperSkillId { get => sweeperSkillId; set { if (value != sweeperSkillId) { sweeperSkillId = value; OnPropertyChanged(); } } }
|
||||
public byte SweepAttemptsCount { get => sweepAttemptsCount; set { if (value != sweepAttemptsCount) { sweepAttemptsCount = value; OnPropertyChanged(); } } }
|
||||
public ObservableCollection<ObjectInfo> ExcludedItems { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> SelectedExcludedItems { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> IncludedItems { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public ObservableCollection<ObjectInfo> SelectedIncludedItems { get; set; } = new ObservableCollection<ObjectInfo>();
|
||||
public bool PickupIfPossible { get => pickupIfPossible; set { if (value != pickupIfPossible) { pickupIfPossible = value; OnPropertyChanged(); } } }
|
||||
public uint PickupMaxDeltaZ { get => pickupMaxDeltaZ; set { if (value != pickupMaxDeltaZ) { pickupMaxDeltaZ = value; OnPropertyChanged(); } } }
|
||||
public byte PickupAttemptsCount { get => pickupAttemptsCount; set { if (value != pickupAttemptsCount) { pickupAttemptsCount = value; OnPropertyChanged(); } } }
|
||||
public byte RestStartPercentHp { get => restStartPercentHp; set { if (value != restStartPercentHp) { restStartPercentHp = value; OnPropertyChanged(); } } }
|
||||
public byte RestEndPercentHp { get => restEndPercentHp; set { if (value != restEndPercentHp) { restEndPercentHp = value; OnPropertyChanged(); } } }
|
||||
public byte RestStartPercentMp { get => restStartPercentMp; set { if (value != restStartPercentMp) { restStartPercentMp = value; OnPropertyChanged(); } } }
|
||||
public byte RestEndPercentMp { get => restEndPercentMp; set { if (value != restEndPercentMp) { restEndPercentMp = value; OnPropertyChanged(); } } }
|
||||
public ObservableCollection<SkillCondition> CombatSkills { get; set; } = new ObservableCollection<SkillCondition>();
|
||||
public bool AutoUseShots { get => autoUseShots; set { if (value != autoUseShots) { autoUseShots = value; OnPropertyChanged(); } } }
|
||||
public uint AttackDistanceMili { get => attackDistanceMili; set { if (value != attackDistanceMili) { attackDistanceMili = value; OnPropertyChanged(); } } }
|
||||
public uint AttackDistanceBow { get => attackDistanceBow; set { if (value != attackDistanceBow) { attackDistanceBow = value; OnPropertyChanged(); } } }
|
||||
public bool UseOnlySkills { get => useOnlySkills; set { if (value != useOnlySkills) { useOnlySkills = value; OnPropertyChanged(); } } }
|
||||
public CombatZone Zone { get => combatZone; set { if (value != combatZone) { combatZone = value; OnPropertyChanged(); } } }
|
||||
public byte DelevelingTargetLevel { get => delevelingTargetLevel; set { if (value != delevelingTargetLevel) { delevelingTargetLevel = value; OnPropertyChanged(); } } }
|
||||
public uint DelevelingAttackDistance { get => delevelingAttackDistance; set { if (value != delevelingAttackDistance) { delevelingAttackDistance = value; OnPropertyChanged(); } } }
|
||||
public uint DelevelingSkillId { get => delevelingSkillId; set { if (value != delevelingSkillId) { delevelingSkillId = value; OnPropertyChanged(); } } }
|
||||
|
||||
public void LoadConfig()
|
||||
{
|
||||
LoadConfigFrom(config);
|
||||
}
|
||||
|
||||
private void LoadConfigFrom(Config config)
|
||||
{
|
||||
LoadCollections(config);
|
||||
MobsMaxDeltaZ = config.Combat.MobsMaxDeltaZ;
|
||||
MobLevelLowerLimit = config.Combat.MobLevelLowerLimit;
|
||||
MobLevelUpperLimit = config.Combat.MobLevelUpperLimit;
|
||||
SpoilIfPossible = config.Combat.SpoilIfPossible;
|
||||
SpoilIsPriority = config.Combat.SpoilIsPriority;
|
||||
SpoilSkillId = config.Combat.SpoilSkillId;
|
||||
SweeperSkillId = config.Combat.SweeperSkillId;
|
||||
SweepAttemptsCount = config.Combat.SweepAttemptsCount;
|
||||
PickupIfPossible = config.Combat.PickupIfPossible;
|
||||
PickupMaxDeltaZ = config.Combat.PickupMaxDeltaZ;
|
||||
PickupAttemptsCount = config.Combat.PickupAttemptsCount;
|
||||
RestStartPercentHp = config.Combat.RestStartPercentHp;
|
||||
RestEndPercentHp = config.Combat.RestEndPecentHp;
|
||||
RestStartPercentMp = config.Combat.RestStartPecentMp;
|
||||
RestEndPercentMp = config.Combat.RestEndPecentMp;
|
||||
AutoUseShots = config.Combat.AutoUseShots;
|
||||
AttackDistanceMili = config.Combat.AttackDistanceMili;
|
||||
AttackDistanceBow = config.Combat.AttackDistanceBow;
|
||||
UseOnlySkills = config.Combat.UseOnlySkills;
|
||||
Zone.X = config.Combat.Zone.Center.X;
|
||||
Zone.Y = config.Combat.Zone.Center.Y;
|
||||
Zone.Radius = config.Combat.Zone.Radius;
|
||||
DelevelingTargetLevel = config.Deleveling.TargetLevel;
|
||||
DelevelingAttackDistance = config.Deleveling.AttackDistance;
|
||||
DelevelingSkillId = config.Deleveling.SkillId;
|
||||
}
|
||||
|
||||
private void SaveConfig()
|
||||
{
|
||||
config.Combat.MobsMaxDeltaZ = MobsMaxDeltaZ;
|
||||
config.Combat.MobLevelLowerLimit = MobLevelLowerLimit;
|
||||
config.Combat.MobLevelUpperLimit = MobLevelUpperLimit;
|
||||
config.Combat.SpoilIfPossible = SpoilIfPossible;
|
||||
config.Combat.SpoilIsPriority = SpoilIsPriority;
|
||||
config.Combat.SpoilSkillId = SpoilSkillId;
|
||||
config.Combat.SweeperSkillId = SweeperSkillId;
|
||||
config.Combat.SweepAttemptsCount = SweepAttemptsCount;
|
||||
config.Combat.PickupIfPossible = PickupIfPossible;
|
||||
config.Combat.PickupMaxDeltaZ = PickupMaxDeltaZ;
|
||||
config.Combat.PickupAttemptsCount = PickupAttemptsCount;
|
||||
config.Combat.RestStartPercentHp = RestStartPercentHp;
|
||||
config.Combat.RestEndPecentHp = RestEndPercentHp;
|
||||
config.Combat.RestStartPecentMp = RestStartPercentMp;
|
||||
config.Combat.RestEndPecentMp = RestEndPercentMp;
|
||||
config.Combat.AutoUseShots = AutoUseShots;
|
||||
config.Combat.AttackDistanceMili = AttackDistanceMili;
|
||||
config.Combat.AttackDistanceBow = AttackDistanceBow;
|
||||
config.Combat.UseOnlySkills = UseOnlySkills;
|
||||
config.Combat.Zone.Center.X = Zone.X;
|
||||
config.Combat.Zone.Center.Y = Zone.Y;
|
||||
config.Combat.Zone.Center.Z = 0;
|
||||
config.Combat.Zone.Radius = Zone.Radius;
|
||||
config.Deleveling.TargetLevel = DelevelingTargetLevel;
|
||||
config.Deleveling.AttackDistance = DelevelingAttackDistance;
|
||||
config.Deleveling.SkillId = DelevelingSkillId;
|
||||
SaveCollections();
|
||||
}
|
||||
|
||||
private void LoadCollections(Config config)
|
||||
{
|
||||
ExcludedMobs.Clear();
|
||||
npcInfoHelper.GetAllNpc().ForEach(n => ExcludedMobs.Add(n));
|
||||
SelectedExcludedMobs.Clear();
|
||||
IncludedMobs.Clear();
|
||||
npcInfoHelper.GetAllNpc().ForEach(n => IncludedMobs.Add(n));
|
||||
SelectedIncludedMobs.Clear();
|
||||
ExcludedSpoilMobs.Clear();
|
||||
npcInfoHelper.GetAllNpc().ForEach(n => ExcludedSpoilMobs.Add(n));
|
||||
SelectedExcludedSpoilMobs.Clear();
|
||||
IncludedSpoilMobs.Clear();
|
||||
npcInfoHelper.GetAllNpc().ForEach(n => IncludedSpoilMobs.Add(n));
|
||||
SelectedIncludedSpoilMobs.Clear();
|
||||
ExcludedItems.Clear();
|
||||
itemInfoHelper.GetAllItems().ForEach(n => ExcludedItems.Add(n));
|
||||
SelectedExcludedItems.Clear();
|
||||
IncludedItems.Clear();
|
||||
itemInfoHelper.GetAllItems().ForEach(n => IncludedItems.Add(n));
|
||||
SelectedIncludedItems.Clear();
|
||||
|
||||
var loadCollection = (ObservableCollection<ObjectInfo> items, ObservableCollection<ObjectInfo> selectedItems, Dictionary<uint, bool> configItems) =>
|
||||
{
|
||||
for (var i = items.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var mob = items[i];
|
||||
if (configItems.ContainsKey(mob.Id))
|
||||
{
|
||||
items.Remove(mob);
|
||||
selectedItems.Add(mob);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
loadCollection(ExcludedMobs, SelectedExcludedMobs, config.Combat.ExcludedMobIds);
|
||||
loadCollection(IncludedMobs, SelectedIncludedMobs, config.Combat.IncludedMobIds);
|
||||
loadCollection(ExcludedSpoilMobs, SelectedExcludedSpoilMobs, config.Combat.ExcludedSpoilMobIds);
|
||||
loadCollection(IncludedSpoilMobs, SelectedIncludedSpoilMobs, config.Combat.IncludedSpoilMobIds);
|
||||
loadCollection(ExcludedItems, SelectedExcludedItems, config.Combat.ExcludedItemIdsToPickup);
|
||||
loadCollection(IncludedItems, SelectedIncludedItems, config.Combat.IncludedItemIdsToPickup);
|
||||
|
||||
CombatSkills.RemoveAll();
|
||||
config.Combat.SkillConditions.ForEach(x =>
|
||||
{
|
||||
CombatSkills.Add(new SkillCondition()
|
||||
{
|
||||
Id = x.Id,
|
||||
MaxTargetPercentHp = x.MaxTargetPercentHp,
|
||||
MinPlayerPercentMp = x.MinPlayerPercentMp,
|
||||
MaxPlayerPercentHp = x.MaxPlayerPercentHp
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void SaveCollections()
|
||||
{
|
||||
config.Combat.ExcludedMobIds = SelectedExcludedMobs.ToDictionary(x => x.Id, x => true);
|
||||
config.Combat.IncludedMobIds = SelectedIncludedMobs.ToDictionary(x => x.Id, x => true);
|
||||
|
||||
config.Combat.ExcludedSpoilMobIds = SelectedExcludedSpoilMobs.ToDictionary(x => x.Id, x => true);
|
||||
config.Combat.IncludedSpoilMobIds = SelectedIncludedSpoilMobs.ToDictionary(x => x.Id, x => true);
|
||||
|
||||
config.Combat.ExcludedItemIdsToPickup = SelectedExcludedItems.ToDictionary(x => x.Id, x => true);
|
||||
config.Combat.IncludedItemIdsToPickup = SelectedIncludedItems.ToDictionary(x => x.Id, x => true);
|
||||
|
||||
config.Combat.SkillConditions = CombatSkills.Select(x => new Config.SkillCondition()
|
||||
{
|
||||
Id = x.Id,
|
||||
MaxTargetPercentHp = x.MaxTargetPercentHp,
|
||||
MinPlayerPercentMp = x.MinPlayerPercentMp,
|
||||
MaxPlayerPercentHp = x.MaxPlayerPercentHp
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private void OnSaveDialog(object? sender)
|
||||
{
|
||||
SaveConfig();
|
||||
if (OpenSaveDialog != null)
|
||||
{
|
||||
OpenSaveDialog(configSerializer.Serialize(config));
|
||||
}
|
||||
if (Close != null)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOpenDialog(object? sender)
|
||||
{
|
||||
if (OpenOpenDialog != null)
|
||||
{
|
||||
var data = OpenOpenDialog();
|
||||
if (data != null)
|
||||
{
|
||||
var config = configDeserializer.Deserialize(data);
|
||||
if (config != null)
|
||||
{
|
||||
LoadConfigFrom(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSave(object? sender)
|
||||
{
|
||||
SaveConfig();
|
||||
if (Close != null)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReset(object? sender)
|
||||
{
|
||||
LoadConfigFrom(config);
|
||||
}
|
||||
|
||||
private void OnGetHeroPosition(object? sender)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Zone.X = hero.Transform.Position.X;
|
||||
Zone.Y = hero.Transform.Position.Y;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly NpcInfoHelperInterface npcInfoHelper;
|
||||
private readonly ItemInfoHelperInterface itemInfoHelper;
|
||||
private readonly SkillInfoHelperInterface skillInfoHelper;
|
||||
private readonly Config config;
|
||||
private readonly ConfigSerializerInterface configSerializer;
|
||||
private readonly ConfigDeserializerInterface configDeserializer;
|
||||
private uint mobsMaxDeltaZ = 0;
|
||||
private byte? mobLevelLowerLimit = null;
|
||||
private byte? mobLevelUpperLimit = null;
|
||||
private bool spoilIfPossible = false;
|
||||
private bool spoilIsPriority = false;
|
||||
private uint spoilSkillId = 0;
|
||||
private uint sweeperSkillId = 0;
|
||||
private byte sweepAttemptsCount = 0;
|
||||
private bool pickupIfPossible = false;
|
||||
private uint pickupMaxDeltaZ = 0;
|
||||
private byte pickupAttemptsCount = 0;
|
||||
private byte restStartPercentHp = 0;
|
||||
private byte restEndPercentHp = 0;
|
||||
private byte restStartPercentMp = 0;
|
||||
private byte restEndPercentMp = 0;
|
||||
private bool autoUseShots = false;
|
||||
private uint attackDistanceMili = 0;
|
||||
private uint attackDistanceBow = 0;
|
||||
private bool useOnlySkills = false;
|
||||
private CombatZone combatZone = new CombatZone();
|
||||
private Hero? hero;
|
||||
private byte delevelingTargetLevel = 0;
|
||||
private uint delevelingAttackDistance = 0;
|
||||
private uint delevelingSkillId = 0;
|
||||
}
|
||||
}
|
||||
55
Client/Application/ViewModels/ChatMessageViewModel.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using Client.Domain.Enums;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class ChatMessageViewModel
|
||||
{
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
return (message.Name != "" ? message.Name + ": " : "") + message.Text;
|
||||
}
|
||||
}
|
||||
|
||||
public SolidColorBrush Color
|
||||
{
|
||||
get
|
||||
{
|
||||
SolidColorBrush? color;
|
||||
if (!colors.TryGetValue(message.Channel, out color))
|
||||
{
|
||||
color = defaultColor;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
public ChatMessageViewModel(ChatMessage message)
|
||||
{
|
||||
this.message = message;
|
||||
|
||||
colors = new Dictionary<ChatChannelEnum, SolidColorBrush>
|
||||
{
|
||||
{ ChatChannelEnum.Shout, Brushes.OrangeRed },
|
||||
{ ChatChannelEnum.Tell, Brushes.Magenta },
|
||||
{ ChatChannelEnum.Party, Brushes.LimeGreen },
|
||||
{ ChatChannelEnum.Clan, Brushes.Violet },
|
||||
{ ChatChannelEnum.Gm, Brushes.Red },
|
||||
{ ChatChannelEnum.Trade, Brushes.HotPink }
|
||||
};
|
||||
}
|
||||
|
||||
private readonly ChatMessage message;
|
||||
private readonly Dictionary<ChatChannelEnum, SolidColorBrush> colors;
|
||||
private readonly SolidColorBrush defaultColor = Brushes.Black;
|
||||
}
|
||||
}
|
||||
106
Client/Application/ViewModels/CreatureListViewModel.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class CreatureListViewModel : ObservableObject
|
||||
{
|
||||
public uint Id => creature.Id;
|
||||
|
||||
public string Name => creature.Name;
|
||||
|
||||
public string BriefInfo => creature.BriefInfo;
|
||||
|
||||
public float Distance => creature.Distance(hero);
|
||||
|
||||
public float DeltaZ => creature.DeltaZ(hero);
|
||||
|
||||
public bool IsTarget => Id == hero.TargetId;
|
||||
|
||||
public bool IsAttacker => hero.AttackerIds.Contains(creature.Id);
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
public ICommand MouseLeftDoubleClickCommand { get; }
|
||||
public ICommand MouseRightClickCommand { get; }
|
||||
private void OnMouseLeftClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestAcquireTarget(Id);
|
||||
}
|
||||
|
||||
private void OnMouseLeftDoubleClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestAttackOrFollow(Id);
|
||||
}
|
||||
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
await pathMover.MoveUntilReachedAsync(creature.Transform.Position);
|
||||
}
|
||||
|
||||
public CreatureListViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, CreatureInterface creature, Hero hero)
|
||||
{
|
||||
creature.PropertyChanged += Creature_PropertyChanged;
|
||||
creature.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
hero.PropertyChanged += Hero_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseLeftDoubleClickCommand = new RelayCommand(OnMouseLeftDoubleClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
|
||||
this.creature = creature;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Distance");
|
||||
OnPropertyChanged("DeltaZ");
|
||||
}
|
||||
|
||||
private void Position_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Distance");
|
||||
OnPropertyChanged("DeltaZ");
|
||||
}
|
||||
|
||||
private void Creature_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Name")
|
||||
{
|
||||
OnPropertyChanged("Name");
|
||||
}
|
||||
if (e.PropertyName == "BriefInfo")
|
||||
{
|
||||
OnPropertyChanged("BriefInfo");
|
||||
}
|
||||
}
|
||||
|
||||
private void Hero_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "TargetId")
|
||||
{
|
||||
OnPropertyChanged("IsTarget");
|
||||
}
|
||||
if (e.PropertyName == "AttackerIds")
|
||||
{
|
||||
OnPropertyChanged("IsAttacker");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly CreatureInterface creature;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
}
|
||||
}
|
||||
178
Client/Application/ViewModels/CreatureMapViewModel.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Enums;
|
||||
using Client.Domain.Service;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows;
|
||||
using Client.Application.Commands;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class CreatureMapViewModel : ObservableObject
|
||||
{
|
||||
public void MapUpdated(float scale, float viewportWidth, float viewportHeight)
|
||||
{
|
||||
Scale = scale;
|
||||
VieportSize = new Vector3(viewportWidth, viewportHeight, 0);
|
||||
}
|
||||
|
||||
public uint Id => creature.Id;
|
||||
public string Name => creature.Name;
|
||||
public Vector3 Position => new Vector3(
|
||||
(creature.Transform.Position.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(creature.Transform.Position.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
public Vector3 Direction => new Vector3(
|
||||
creature.Transform.Direction.X * Radius * 2f,
|
||||
creature.Transform.Direction.Y * Radius * 2f,
|
||||
0
|
||||
);
|
||||
public VitalStats VitalStats => creature.VitalStats;
|
||||
public float Radius => MAX_RADIUS - (1/MapViewModel.MIN_SCALE - 1/scale) / (1/MapViewModel.MIN_SCALE - 1/MapViewModel.MAX_SCALE) * (MAX_RADIUS - MIN_RADIUS);
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale != value)
|
||||
{
|
||||
scale = value;
|
||||
OnPropertyChanged("Position");
|
||||
OnPropertyChanged("Direction");
|
||||
OnPropertyChanged("Radius");
|
||||
OnPropertyChanged("AggroRadius");
|
||||
}
|
||||
}
|
||||
}
|
||||
public Vector3 VieportSize
|
||||
{
|
||||
get => vieportSize;
|
||||
set
|
||||
{
|
||||
if (vieportSize != value)
|
||||
{
|
||||
vieportSize = value;
|
||||
OnPropertyChanged("Position");
|
||||
OnPropertyChanged("Direction");
|
||||
}
|
||||
}
|
||||
}
|
||||
public CreatureTypeEnum Type => creature.Type;
|
||||
public bool IsTarget => Id == hero.TargetId;
|
||||
public bool IsAggressive => creature.AggroRadius > 0 && !creature.VitalStats.IsDead && creature.IsHostile;
|
||||
public float AggroRadius => creature.AggroRadius / scale;
|
||||
public bool IsAttacker => hero.AttackerIds.Contains(creature.Id);
|
||||
public bool IsDead => creature.VitalStats.IsDead;
|
||||
public bool IsHostile => creature.IsHostile;
|
||||
public bool IsSweepable => creature is NPC && ((NPC) creature).SpoilState == SpoilStateEnum.Sweepable;
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
public ICommand MouseLeftDoubleClickCommand { get; }
|
||||
public ICommand MouseRightClickCommand { get; }
|
||||
private void OnMouseLeftClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestAcquireTarget(Id);
|
||||
}
|
||||
|
||||
private void OnMouseLeftDoubleClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestAttackOrFollow(Id);
|
||||
}
|
||||
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
await pathMover.MoveUntilReachedAsync(creature.Transform.Position);
|
||||
}
|
||||
|
||||
public CreatureMapViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, CreatureInterface creature, Hero hero)
|
||||
{
|
||||
this.creature = creature;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
creature.PropertyChanged += Creature_PropertyChanged;
|
||||
creature.Transform.PropertyChanged += Transform_PropertyChanged;
|
||||
creature.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
creature.VitalStats.PropertyChanged += VitalStats_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
hero.PropertyChanged += Hero_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseLeftDoubleClickCommand = new RelayCommand(OnMouseLeftDoubleClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
}
|
||||
|
||||
private void VitalStats_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Hp" || e.PropertyName == "MaxHp")
|
||||
{
|
||||
OnPropertyChanged("VitalStats");
|
||||
}
|
||||
if (e.PropertyName == "IsDead")
|
||||
{
|
||||
OnPropertyChanged("IsAggressive");
|
||||
OnPropertyChanged("IsDead");
|
||||
}
|
||||
}
|
||||
|
||||
private void Hero_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "TargetId")
|
||||
{
|
||||
OnPropertyChanged("IsTarget");
|
||||
}
|
||||
if (e.PropertyName == "AttackerIds")
|
||||
{
|
||||
OnPropertyChanged("IsAttacker");
|
||||
}
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Position");
|
||||
OnPropertyChanged("Direction");
|
||||
}
|
||||
|
||||
private void Position_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Position");
|
||||
OnPropertyChanged("Direction");
|
||||
}
|
||||
|
||||
private void Transform_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Direction")
|
||||
{
|
||||
OnPropertyChanged("Direction");
|
||||
}
|
||||
}
|
||||
|
||||
private void Creature_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Name")
|
||||
{
|
||||
OnPropertyChanged("Name");
|
||||
}
|
||||
if (e.PropertyName == "SpoilState")
|
||||
{
|
||||
OnPropertyChanged("IsSweepable");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly CreatureInterface creature;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private float scale = 1;
|
||||
private static readonly float MAX_RADIUS = 10;
|
||||
private static readonly float MIN_RADIUS = 2;
|
||||
private Vector3 vieportSize = new Vector3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
132
Client/Application/ViewModels/DropListViewModel.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class DropListViewModel : ObservableObject
|
||||
{
|
||||
public uint Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return drop.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return drop.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public uint Amount
|
||||
{
|
||||
get
|
||||
{
|
||||
return drop.Amount;
|
||||
}
|
||||
}
|
||||
|
||||
public uint ItemId
|
||||
{
|
||||
get
|
||||
{
|
||||
return drop.ItemId;
|
||||
}
|
||||
}
|
||||
|
||||
public float Distance
|
||||
{
|
||||
get
|
||||
{
|
||||
return drop.Transform.Position.HorizontalDistance(hero.Transform.Position);
|
||||
}
|
||||
}
|
||||
public float DeltaZ
|
||||
{
|
||||
get
|
||||
{
|
||||
return (drop.Transform.Position.Z - hero.Transform.Position.Z);
|
||||
}
|
||||
}
|
||||
|
||||
public string IconName
|
||||
{
|
||||
get
|
||||
{
|
||||
return "/Assets/icons/" + drop.IconName + ".png";
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
public ICommand MouseRightClickCommand { get; }
|
||||
private void OnMouseLeftClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestPickUp(Id);
|
||||
}
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
await pathMover.MoveUntilReachedAsync(drop.Transform.Position);
|
||||
}
|
||||
|
||||
public DropListViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, Drop drop, Hero hero)
|
||||
{
|
||||
this.drop = drop;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
drop.PropertyChanged += Drop_PropertyChanged;
|
||||
drop.Transform.Position.PropertyChanged += DropPosition_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Distance");
|
||||
OnPropertyChanged("DeltaZ");
|
||||
}
|
||||
|
||||
private void DropPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Distance");
|
||||
OnPropertyChanged("DeltaZ");
|
||||
}
|
||||
|
||||
private void Drop_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Name")
|
||||
{
|
||||
OnPropertyChanged("Name");
|
||||
}
|
||||
if (e.PropertyName == "Amount")
|
||||
{
|
||||
OnPropertyChanged("Amount");
|
||||
}
|
||||
if (e.PropertyName == "ItemId")
|
||||
{
|
||||
OnPropertyChanged("ItemId");
|
||||
}
|
||||
if (e.PropertyName == "IconName")
|
||||
{
|
||||
OnPropertyChanged("IconName");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Drop drop;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
}
|
||||
}
|
||||
110
Client/Application/ViewModels/DropMapViewModel.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Enums;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel;
|
||||
using Client.Domain.Service;
|
||||
using System.Windows.Input;
|
||||
using Client.Application.Commands;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class DropMapViewModel : ObservableObject
|
||||
{
|
||||
public void MapUpdated(float scale, float viewportWidth, float viewportHeight)
|
||||
{
|
||||
Scale = scale;
|
||||
VieportSize = new Vector3(viewportWidth, viewportHeight, 0);
|
||||
}
|
||||
|
||||
public uint Id => drop.Id;
|
||||
public string Name => drop.Name + " (" + drop.Amount + ")";
|
||||
public Vector3 Position => new Vector3(
|
||||
(drop.Transform.Position.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(drop.Transform.Position.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
public float Radius => MathF.Max(MAX_RADIUS / scale, MIN_RADIUS);
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale != value)
|
||||
{
|
||||
scale = value;
|
||||
OnPropertyChanged("Position");
|
||||
OnPropertyChanged("Radius");
|
||||
}
|
||||
}
|
||||
}
|
||||
public Vector3 VieportSize
|
||||
{
|
||||
get => vieportSize;
|
||||
set
|
||||
{
|
||||
if (vieportSize != value)
|
||||
{
|
||||
vieportSize = value;
|
||||
OnPropertyChanged("Position");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
public ICommand MouseRightClickCommand { get; }
|
||||
private void OnMouseLeftClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestPickUp(Id);
|
||||
}
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
await pathMover.MoveUntilReachedAsync(drop.Transform.Position);
|
||||
}
|
||||
|
||||
public DropMapViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, Drop drop, Hero hero)
|
||||
{
|
||||
this.drop = drop;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
drop.PropertyChanged += Creature_PropertyChanged;
|
||||
drop.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Position");
|
||||
}
|
||||
|
||||
private void Position_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Position");
|
||||
}
|
||||
|
||||
private void Creature_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Name" || e.PropertyName == "Amount")
|
||||
{
|
||||
OnPropertyChanged("Name");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Drop drop;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private float scale = 1;
|
||||
private static readonly float MAX_RADIUS = 8;
|
||||
private static readonly float MIN_RADIUS = 2;
|
||||
private Vector3 vieportSize = new Vector3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
151
Client/Application/ViewModels/HeroSummaryInfoViewModel.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class HeroSummaryInfoViewModel : ObservableObject
|
||||
{
|
||||
public bool IsVisible {
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public FullName Fullname
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.FullName;
|
||||
}
|
||||
}
|
||||
public Phenotype Phenotype
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.Phenotype;
|
||||
}
|
||||
}
|
||||
public Transform Transform
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.Transform;
|
||||
}
|
||||
}
|
||||
public ExperienceInfo Experience
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.ExperienceInfo;
|
||||
}
|
||||
}
|
||||
public VitalStats VitalStats
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.VitalStats;
|
||||
}
|
||||
}
|
||||
public InventoryInfo InventoryInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.InventoryInfo;
|
||||
}
|
||||
}
|
||||
public ulong Money
|
||||
{
|
||||
get
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public TargetSummaryInfoViewModel? Target
|
||||
{
|
||||
get
|
||||
{
|
||||
return target;
|
||||
}
|
||||
}
|
||||
public List<uint> Attackers
|
||||
{
|
||||
get
|
||||
{
|
||||
return hero.AttackerIds.ToList();
|
||||
}
|
||||
}
|
||||
public HeroSummaryInfoViewModel(Hero hero)
|
||||
{
|
||||
this.hero = hero;
|
||||
|
||||
hero.FullName.PropertyChanged += FullName_PropertyChanged;
|
||||
hero.Phenotype.PropertyChanged += Phenotype_PropertyChanged;
|
||||
hero.ExperienceInfo.PropertyChanged += ExperienceInfo_PropertyChanged;
|
||||
hero.Transform.PropertyChanged += Transform_PropertyChanged;
|
||||
hero.VitalStats.PropertyChanged += VitalStats_PropertyChanged;
|
||||
hero.InventoryInfo.PropertyChanged += InventoryInfo_PropertyChanged;
|
||||
hero.PropertyChanged += Hero_PropertyChanged;
|
||||
}
|
||||
|
||||
private void Hero_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Target")
|
||||
{
|
||||
if (target == null && hero.Target != null)
|
||||
{
|
||||
target = new TargetSummaryInfoViewModel(hero.Target, hero);
|
||||
OnPropertyChanged("Target");
|
||||
}
|
||||
else if (target != null && hero.Target == null)
|
||||
{
|
||||
target = null;
|
||||
OnPropertyChanged("Target");
|
||||
}
|
||||
}
|
||||
else if (e.PropertyName == "AttackerIds")
|
||||
{
|
||||
OnPropertyChanged("Attackers");
|
||||
}
|
||||
}
|
||||
|
||||
private void InventoryInfo_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("InventoryInfo");
|
||||
}
|
||||
|
||||
private void VitalStats_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("VitalStats");
|
||||
}
|
||||
|
||||
private void Transform_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Transform");
|
||||
}
|
||||
|
||||
private void Phenotype_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Phenotype");
|
||||
}
|
||||
|
||||
private void ExperienceInfo_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Experience");
|
||||
}
|
||||
|
||||
private void FullName_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Fullname");
|
||||
}
|
||||
|
||||
private readonly Hero hero;
|
||||
private TargetSummaryInfoViewModel? target;
|
||||
}
|
||||
}
|
||||
46
Client/Application/ViewModels/ItemListViewModel.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Application.Components;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class ItemListViewModel : ObservableObject
|
||||
{
|
||||
public uint Id => item.Id;
|
||||
public string Name => item.Name;
|
||||
public string Description => item.FullDescription;
|
||||
public string IconName => "/Assets/icons/" + item.IconName + ".png";
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
public ICommand MouseRightClickCommand { get; }
|
||||
private void OnLeftMouseClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestUseItem(Id);
|
||||
}
|
||||
private void OnRightMouseClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestToggleAutouseSoulshot(Id);
|
||||
}
|
||||
|
||||
public ItemListViewModel(WorldHandler worldHandler, ItemInterface item)
|
||||
{
|
||||
this.worldHandler = worldHandler;
|
||||
this.item = item;
|
||||
|
||||
//skill.PropertyChanged += Skill_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnLeftMouseClick);
|
||||
MouseRightClickCommand = new RelayCommand(OnRightMouseClick);
|
||||
}
|
||||
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly ItemInterface item;
|
||||
}
|
||||
}
|
||||
210
Client/Application/ViewModels/MainViewModel.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Application.Components;
|
||||
using Client.Domain.AI;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Events;
|
||||
using Client.Domain.Service;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class MainViewModel :
|
||||
ObservableObject,
|
||||
EventHandlerInterface<HeroCreatedEvent>,
|
||||
EventHandlerInterface<HeroDeletedEvent>,
|
||||
EventHandlerInterface<CreatureCreatedEvent>,
|
||||
EventHandlerInterface<CreatureDeletedEvent>,
|
||||
EventHandlerInterface<DropCreatedEvent>,
|
||||
EventHandlerInterface<DropDeletedEvent>,
|
||||
EventHandlerInterface<ChatMessageCreatedEvent>,
|
||||
EventHandlerInterface<SkillCreatedEvent>,
|
||||
EventHandlerInterface<SkillDeletedEvent>,
|
||||
EventHandlerInterface<ItemCreatedEvent>,
|
||||
EventHandlerInterface<ItemDeletedEvent>
|
||||
{
|
||||
|
||||
public void Handle(HeroCreatedEvent @event)
|
||||
{
|
||||
Hero = new HeroSummaryInfoViewModel(@event.Hero);
|
||||
hero = @event.Hero;
|
||||
Map.Hero = hero;
|
||||
Map.CombatZone = new AICombatZoneMapViewModel(aiConfig.Combat.Zone, hero);
|
||||
AddCreature(hero);
|
||||
OnPropertyChanged("Hero");
|
||||
OnPropertyChanged("Map");
|
||||
}
|
||||
|
||||
public void Handle(HeroDeletedEvent @event)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
RemoveCreature(hero.Id);
|
||||
}
|
||||
Hero = null;
|
||||
hero = null;
|
||||
Map.Hero = null;
|
||||
Map.CombatZone = null;
|
||||
OnPropertyChanged("Hero");
|
||||
OnPropertyChanged("Map");
|
||||
}
|
||||
|
||||
public void Handle(CreatureCreatedEvent @event)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Creatures.Add(new CreatureListViewModel(worldHandler, pathMover, @event.Creature, hero));
|
||||
AddCreature(@event.Creature);
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(CreatureDeletedEvent @event)
|
||||
{
|
||||
Creatures.RemoveAll(x => x.Id == @event.Id);
|
||||
RemoveCreature(@event.Id);
|
||||
}
|
||||
|
||||
public void Handle(DropCreatedEvent @event)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Drops.Add(new DropListViewModel(worldHandler, pathMover, @event.Drop, hero));
|
||||
Map.Drops.Add(new DropMapViewModel(worldHandler, pathMover, @event.Drop, hero));
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(DropDeletedEvent @event)
|
||||
{
|
||||
Drops.RemoveAll(x => x.Id == @event.Id);
|
||||
Map.Drops.RemoveAll(x => x.Id == @event.Id);
|
||||
}
|
||||
|
||||
public void Handle(ChatMessageCreatedEvent @event)
|
||||
{
|
||||
ChatMessages.Add(new ChatMessageViewModel(@event.Message));
|
||||
}
|
||||
|
||||
public void Handle(SkillCreatedEvent @event)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
if (@event.Skill.IsActive)
|
||||
{
|
||||
ActiveSkills.Add(new SkillListViewModel(worldHandler, @event.Skill));
|
||||
}
|
||||
else
|
||||
{
|
||||
PassiveSkills.Add(new SkillListViewModel(worldHandler, @event.Skill));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SkillDeletedEvent @event)
|
||||
{
|
||||
ActiveSkills.RemoveAll(x => x.Id == @event.Id);
|
||||
PassiveSkills.RemoveAll(x => x.Id == @event.Id);
|
||||
}
|
||||
|
||||
public void Handle(ItemCreatedEvent @event)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
if (@event.Item is EtcItem && ((EtcItem) @event.Item).IsQuest)
|
||||
{
|
||||
QuestItems.Add(new ItemListViewModel(worldHandler, @event.Item));
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.Add(new ItemListViewModel(worldHandler, @event.Item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(ItemDeletedEvent @event)
|
||||
{
|
||||
Items.RemoveAll(x => x.Id == @event.Id);
|
||||
QuestItems.RemoveAll(x => x.Id == @event.Id);
|
||||
}
|
||||
|
||||
public Dictionary<TypeEnum, string> AITypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return Enum.GetValues(typeof(TypeEnum)).Cast<TypeEnum>().ToDictionary(x => x, x => x.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void AddCreature(CreatureInterface creature)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Map.Creatures.Add(new CreatureMapViewModel(worldHandler, pathMover, creature, hero));
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveCreature(uint id)
|
||||
{
|
||||
Map.Creatures.RemoveAll(x => x.Id == id);
|
||||
}
|
||||
|
||||
private void OnToggleAI(object? sender)
|
||||
{
|
||||
ai.Toggle();
|
||||
OnPropertyChanged("AIStatus");
|
||||
}
|
||||
|
||||
private void OnChangeAIType(object? param)
|
||||
{
|
||||
if (!(param is TypeEnum))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ai.Type = (TypeEnum) param;
|
||||
OnPropertyChanged("AIType");
|
||||
}
|
||||
|
||||
public MainViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, AIInterface ai, Config aiConfig)
|
||||
{
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
this.ai = ai;
|
||||
this.aiConfig = aiConfig;
|
||||
Map = new MapViewModel(pathMover);
|
||||
ToggleAICommand = new RelayCommand(OnToggleAI);
|
||||
ChangeAITypeCommand = new RelayCommand(OnChangeAIType);
|
||||
}
|
||||
|
||||
public ICommand ToggleAICommand { get; set; }
|
||||
public ICommand ChangeAITypeCommand { get; set; }
|
||||
|
||||
public ObservableCollection<ChatMessageViewModel> ChatMessages { get; } = new ObservableCollection<ChatMessageViewModel>();
|
||||
public ObservableCollection<CreatureListViewModel> Creatures { get; } = new ObservableCollection<CreatureListViewModel>();
|
||||
public ObservableCollection<DropListViewModel> Drops { get; } = new ObservableCollection<DropListViewModel>();
|
||||
public ObservableCollection<SkillListViewModel> ActiveSkills { get; } = new ObservableCollection<SkillListViewModel>();
|
||||
public ObservableCollection<SkillListViewModel> PassiveSkills { get; } = new ObservableCollection<SkillListViewModel>();
|
||||
public ObservableCollection<ItemListViewModel> Items { get; } = new ObservableCollection<ItemListViewModel>();
|
||||
public ObservableCollection<ItemListViewModel> QuestItems { get; } = new ObservableCollection<ItemListViewModel>();
|
||||
public HeroSummaryInfoViewModel? Hero { get; private set; }
|
||||
public MapViewModel Map { get; private set; }
|
||||
public bool AIStatus => ai.IsEnabled;
|
||||
public TypeEnum AIType => ai.Type;
|
||||
|
||||
public Hero? hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private readonly AIInterface ai;
|
||||
private readonly Config aiConfig;
|
||||
}
|
||||
}
|
||||
58
Client/Application/ViewModels/MapBlockViewModel.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class MapBlockViewModel : ObservableObject
|
||||
{
|
||||
public string ImageSource => "/Assets/maps/" + mapBlock.BlockX + "_" + mapBlock.BlockY + ".jpg";
|
||||
public float DeltaX => mapBlock.DeltaX;
|
||||
public float DeltaY => mapBlock.DeltaY;
|
||||
public float Size => mapBlock.Size;
|
||||
public bool Visible
|
||||
{
|
||||
get => visible;
|
||||
set
|
||||
{
|
||||
if (visible != value)
|
||||
{
|
||||
visible = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
public MapBlock MapBlock => mapBlock;
|
||||
|
||||
public MapBlockViewModel(MapBlock mapBlock)
|
||||
{
|
||||
this.mapBlock = mapBlock;
|
||||
|
||||
mapBlock.PropertyChanged += MapBlock_PropertyChanged;
|
||||
}
|
||||
|
||||
private void MapBlock_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "DeltaX")
|
||||
{
|
||||
OnPropertyChanged("DeltaX");
|
||||
}
|
||||
if (e.PropertyName == "DeltaY")
|
||||
{
|
||||
OnPropertyChanged("DeltaY");
|
||||
}
|
||||
if (e.PropertyName == "Size")
|
||||
{
|
||||
OnPropertyChanged("Size");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly MapBlock mapBlock;
|
||||
private bool visible = true;
|
||||
}
|
||||
}
|
||||
340
Client/Application/ViewModels/MapViewModel.cs
Normal file
@@ -0,0 +1,340 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.DTO;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class MapViewModel : ObservableObject
|
||||
{
|
||||
public delegate void MapUpdatedEventHandler(float scale, float viewportWidth, float viewportHeight);
|
||||
private event MapUpdatedEventHandler? MapUpdated;
|
||||
|
||||
public Hero? Hero
|
||||
{
|
||||
get => hero;
|
||||
set
|
||||
{
|
||||
if (hero != value)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
hero.Transform.Position.PropertyChanged -= HeroPosition_PropertyChanged;
|
||||
}
|
||||
hero = value;
|
||||
if (hero != null)
|
||||
{
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
}
|
||||
UpdateMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double ViewportWidth
|
||||
{
|
||||
get => viewportWidth;
|
||||
set
|
||||
{
|
||||
if (viewportWidth != value)
|
||||
{
|
||||
viewportWidth = value;
|
||||
UpdateMap();
|
||||
OnPropertyChanged("MousePosition");
|
||||
}
|
||||
}
|
||||
}
|
||||
public double ViewportHeight
|
||||
{
|
||||
get => viewportHeight;
|
||||
set
|
||||
{
|
||||
if (viewportHeight != value)
|
||||
{
|
||||
viewportHeight = value;
|
||||
UpdateMap();
|
||||
OnPropertyChanged("MousePosition");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale != value)
|
||||
{
|
||||
scale = value;
|
||||
UpdateMap();
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged("MousePosition");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 MousePosition
|
||||
{
|
||||
get => mousePosition;
|
||||
set => mousePosition = value;
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateMap();
|
||||
if (e.PropertyName == "X" || e.PropertyName == "Y")
|
||||
{
|
||||
OnPropertyChanged("MousePosition");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMap()
|
||||
{
|
||||
foreach (var block in Blocks)
|
||||
{
|
||||
block.Visible = false;
|
||||
}
|
||||
|
||||
if (hero != null)
|
||||
{
|
||||
var blocks = selector.SelectImages((float)ViewportWidth, (float)ViewportHeight, hero.Transform.Position, Scale);
|
||||
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
if (this.blocks.ContainsKey(block.Id))
|
||||
{
|
||||
this.blocks[block.Id].MapBlock.DeltaX = block.DeltaX;
|
||||
this.blocks[block.Id].MapBlock.DeltaY = block.DeltaY;
|
||||
this.blocks[block.Id].MapBlock.Size = block.Size;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var model = new MapBlockViewModel(block);
|
||||
this.blocks.Add(block.Id, model);
|
||||
Blocks.Add(model);
|
||||
}
|
||||
|
||||
this.blocks[block.Id].Visible = true;
|
||||
}
|
||||
|
||||
|
||||
if (MapUpdated != null)
|
||||
{
|
||||
MapUpdated(scale, (float)ViewportWidth, (float)ViewportHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
private async Task OnLeftMouseClick(object? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (hero == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Point mousePos = Mouse.GetPosition((IInputElement)obj);
|
||||
var location = new Vector3(
|
||||
(float)(mousePos.X - ViewportWidth / 2) * scale + hero.Transform.Position.X,
|
||||
(float)(mousePos.Y - ViewportHeight / 2) * scale + hero.Transform.Position.Y,
|
||||
hero.Transform.Position.Z
|
||||
);
|
||||
|
||||
await pathMover.MoveUntilReachedAsync(location);
|
||||
}
|
||||
|
||||
public void OnMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
var newScale = Scale - e.Delta / Mouse.MouseWheelDeltaForOneLine;
|
||||
Scale = MathF.Max(MathF.Min(newScale, MAX_SCALE), MIN_SCALE);
|
||||
}
|
||||
|
||||
public void OnMouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
mousePosition.X = 0;
|
||||
mousePosition.Y = 0;
|
||||
}
|
||||
|
||||
public void OnMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (hero == null)
|
||||
{
|
||||
mousePosition.X = 0;
|
||||
mousePosition.Y = 0;
|
||||
return;
|
||||
}
|
||||
var el = (IInputElement)sender;
|
||||
var mousePos = e.GetPosition(el);
|
||||
|
||||
mousePosition.X = (float)(mousePos.X - ViewportWidth / 2) * scale + hero.Transform.Position.X;
|
||||
mousePosition.Y = (float)(mousePos.Y - ViewportHeight / 2) * scale + hero.Transform.Position.Y;
|
||||
}
|
||||
|
||||
public MapViewModel(AsyncPathMoverInterface pathMover)
|
||||
{
|
||||
Creatures.CollectionChanged += Creatures_CollectionChanged;
|
||||
Drops.CollectionChanged += Drops_CollectionChanged;
|
||||
Path.CollectionChanged += Path_CollectionChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(async (o) => await OnLeftMouseClick(o));
|
||||
mousePosition.PropertyChanged += MousePosition_PropertyChanged;
|
||||
BindingOperations.EnableCollectionSynchronization(Path, pathCollectionLock);
|
||||
this.pathMover = pathMover;
|
||||
this.pathMover.Path.CollectionChanged += PathMover_Path_CollectionChanged;
|
||||
}
|
||||
|
||||
private void PathMover_Path_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
lock(pathCollectionLock)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var node = (PathSegment)item;
|
||||
Path.Add(new PathNodeViewModel(node.From, node.To, hero));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
|
||||
{
|
||||
foreach (var item in e.OldItems)
|
||||
{
|
||||
Path.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
Path.RemoveAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Path_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var node = (PathNodeViewModel)item;
|
||||
MapUpdated += node.MapUpdated;
|
||||
node.MapUpdated(scale, (float)ViewportWidth, (float)ViewportHeight);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
|
||||
{
|
||||
foreach (var item in e.OldItems)
|
||||
{
|
||||
var node = (PathNodeViewModel)item;
|
||||
MapUpdated -= node.MapUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MousePosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("MousePosition");
|
||||
}
|
||||
|
||||
private void Drops_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var drop = (DropMapViewModel)item;
|
||||
MapUpdated += drop.MapUpdated;
|
||||
drop.MapUpdated(scale, (float)ViewportWidth, (float)ViewportHeight);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
|
||||
{
|
||||
foreach (var item in e.OldItems)
|
||||
{
|
||||
var drop = (DropMapViewModel)item;
|
||||
MapUpdated -= drop.MapUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Creatures_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var creature = (CreatureMapViewModel)item;
|
||||
MapUpdated += creature.MapUpdated;
|
||||
creature.MapUpdated(scale, (float)ViewportWidth, (float)ViewportHeight);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
|
||||
{
|
||||
foreach (var item in e.OldItems)
|
||||
{
|
||||
var creature = (CreatureMapViewModel)item;
|
||||
MapUpdated -= creature.MapUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObservableCollection<MapBlockViewModel> Blocks { get; } = new ObservableCollection<MapBlockViewModel>();
|
||||
public ObservableCollection<CreatureMapViewModel> Creatures { get; } = new ObservableCollection<CreatureMapViewModel>();
|
||||
public ObservableCollection<DropMapViewModel> Drops { get; } = new ObservableCollection<DropMapViewModel>();
|
||||
public ObservableCollection<PathNodeViewModel> Path { get; } = new ObservableCollection<PathNodeViewModel>();
|
||||
public AICombatZoneMapViewModel? CombatZone {
|
||||
get
|
||||
{
|
||||
return combatZone;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value != combatZone)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
if (combatZone != null)
|
||||
{
|
||||
MapUpdated -= combatZone.MapUpdated;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MapUpdated += value.MapUpdated;
|
||||
}
|
||||
combatZone = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public readonly static float MIN_SCALE = 1;
|
||||
public readonly static float MAX_SCALE = 128;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private MapImageSelector selector = new MapImageSelector();
|
||||
private Dictionary<uint, MapBlockViewModel> blocks = new Dictionary<uint, MapBlockViewModel>();
|
||||
private Hero? hero;
|
||||
private float scale = 8;
|
||||
private double viewportWidth = 0;
|
||||
private double viewportHeight = 0;
|
||||
private Vector3 mousePosition = new Vector3(0, 0, 0);
|
||||
private object pathCollectionLock = new object();
|
||||
private AICombatZoneMapViewModel? combatZone = null;
|
||||
}
|
||||
}
|
||||
86
Client/Application/ViewModels/PathNodeViewModel.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class PathNodeViewModel : ObservableObject
|
||||
{
|
||||
public void MapUpdated(float scale, float viewportWidth, float viewportHeight)
|
||||
{
|
||||
Scale = scale;
|
||||
VieportSize = new Vector3(viewportWidth, viewportHeight, 0);
|
||||
}
|
||||
|
||||
public Vector3 From => new Vector3(
|
||||
(from.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(from.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
|
||||
public Vector3 To => new Vector3(
|
||||
(to.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(to.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
|
||||
public float Radius => MAX_RADIUS - (1 / MapViewModel.MIN_SCALE - 1 / scale) / (1 / MapViewModel.MIN_SCALE - 1 / MapViewModel.MAX_SCALE) * (MAX_RADIUS - MIN_RADIUS);
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale != value)
|
||||
{
|
||||
scale = value;
|
||||
OnPropertyChanged("From");
|
||||
OnPropertyChanged("To");
|
||||
OnPropertyChanged("Radius");
|
||||
}
|
||||
}
|
||||
}
|
||||
public Vector3 VieportSize
|
||||
{
|
||||
get => vieportSize;
|
||||
set
|
||||
{
|
||||
if (vieportSize != value)
|
||||
{
|
||||
vieportSize = value;
|
||||
OnPropertyChanged("From");
|
||||
OnPropertyChanged("To");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PathNodeViewModel(Vector3 from, Vector3 to, Hero hero)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.hero = hero;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("From");
|
||||
OnPropertyChanged("To");
|
||||
}
|
||||
|
||||
private readonly Vector3 from;
|
||||
private readonly Vector3 to;
|
||||
private readonly Hero hero;
|
||||
private float scale = 1;
|
||||
private static readonly float MAX_RADIUS = 10;
|
||||
private static readonly float MIN_RADIUS = 2;
|
||||
private Vector3 vieportSize = new Vector3(0, 0, 0);
|
||||
}
|
||||
}
|
||||
78
Client/Application/ViewModels/SkillListViewModel.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using System.Windows.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Client.Application.Commands;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class SkillListViewModel : ObservableObject
|
||||
{
|
||||
public uint Id => skill.Id;
|
||||
public string Name => skill.Name;
|
||||
public uint Level => skill.Level;
|
||||
public string Description=> skill.Description;
|
||||
public string IconName => "/Assets/icons/" + skill.IconName + ".png";
|
||||
public bool IsActive => skill.IsActive;
|
||||
public bool IsReadyToUse => skill.IsReadyToUse;
|
||||
public bool IsBusy => !skill.IsReadyToUse;
|
||||
public uint? Cost => skill.Cost == 0 ? null : skill.Cost;
|
||||
public int? Range => skill.Range <= 0 ? null : skill.Range;
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
private void OnLeftMouseClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestUseSkill(Id, false, false);
|
||||
}
|
||||
|
||||
public SkillListViewModel(WorldHandler worldHandler, Skill skill)
|
||||
{
|
||||
this.worldHandler = worldHandler;
|
||||
this.skill = skill;
|
||||
|
||||
skill.PropertyChanged += Skill_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnLeftMouseClick);
|
||||
}
|
||||
|
||||
private void Skill_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Description")
|
||||
{
|
||||
OnPropertyChanged("Description");
|
||||
}
|
||||
if (e.PropertyName == "IsReadyToUse")
|
||||
{
|
||||
OnPropertyChanged("IsBusy");
|
||||
OnPropertyChanged("IsReadyToUse");
|
||||
}
|
||||
if (e.PropertyName == "Level")
|
||||
{
|
||||
OnPropertyChanged("Level");
|
||||
}
|
||||
if (e.PropertyName == "Cost")
|
||||
{
|
||||
OnPropertyChanged("Cost");
|
||||
}
|
||||
if (e.PropertyName == "Range")
|
||||
{
|
||||
OnPropertyChanged("Range");
|
||||
}
|
||||
if (e.PropertyName == "Name")
|
||||
{
|
||||
OnPropertyChanged("Name");
|
||||
}
|
||||
if (e.PropertyName == "IconName")
|
||||
{
|
||||
OnPropertyChanged("IconName");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly Skill skill;
|
||||
}
|
||||
}
|
||||
81
Client/Application/ViewModels/TargetSummaryInfoViewModel.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class TargetSummaryInfoViewModel : ObservableObject
|
||||
{
|
||||
public uint Id => creature.Id;
|
||||
|
||||
public string Name => creature.Name;
|
||||
|
||||
public Vector3 Position => creature.Transform.Position;
|
||||
|
||||
public string BriefInfo => creature.BriefInfo;
|
||||
|
||||
public float Distance => creature.Distance(hero);
|
||||
|
||||
public float DeltaZ => creature.DeltaZ(hero);
|
||||
|
||||
public uint Hp => creature.VitalStats.Hp;
|
||||
|
||||
public uint MaxHp => creature.VitalStats.MaxHp;
|
||||
|
||||
public TargetSummaryInfoViewModel(CreatureInterface creature, Hero hero)
|
||||
{
|
||||
creature.PropertyChanged += Creature_PropertyChanged;
|
||||
creature.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
creature.VitalStats.PropertyChanged += VitalStats_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
|
||||
this.creature = creature;
|
||||
this.hero = hero;
|
||||
}
|
||||
|
||||
private void VitalStats_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Hp")
|
||||
{
|
||||
OnPropertyChanged("Hp");
|
||||
}
|
||||
if (e.PropertyName == "MaxHp")
|
||||
{
|
||||
OnPropertyChanged("MaxHp");
|
||||
}
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Distance");
|
||||
OnPropertyChanged("DeltaZ");
|
||||
}
|
||||
|
||||
private void Position_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("Distance");
|
||||
OnPropertyChanged("DeltaZ");
|
||||
OnPropertyChanged("Transform");
|
||||
}
|
||||
|
||||
private void Creature_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "Name")
|
||||
{
|
||||
OnPropertyChanged("Name");
|
||||
}
|
||||
if (e.PropertyName == "BriefInfo")
|
||||
{
|
||||
OnPropertyChanged("BriefInfo");
|
||||
}
|
||||
}
|
||||
|
||||
private readonly CreatureInterface creature;
|
||||
private readonly Hero hero;
|
||||
}
|
||||
}
|
||||
373
Client/Application/Views/AIConfig.xaml
Normal file
@@ -0,0 +1,373 @@
|
||||
<Window x:Class="Client.Application.Views.AIConfig"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client.Application.Views"
|
||||
xmlns:components="clr-namespace:Client.Application.Components"
|
||||
mc:Ignorable="d"
|
||||
IsVisibleChanged="Window_IsVisibleChanged"
|
||||
Closing="Window_Closing"
|
||||
SizeToContent="Height"
|
||||
ResizeMode="NoResize"
|
||||
Title="Combat AI Config" Height="600" Width="800"
|
||||
x:Name="root">
|
||||
<Grid Margin="0,0,0,10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Menu>
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Open" Command="{Binding OpenDialogCommand}"/>
|
||||
<MenuItem Header="Save" Command="{Binding SaveDialogCommand}"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<TabControl Grid.Row="1" TabStripPlacement="Left">
|
||||
<TabItem>
|
||||
<TabItem.Header>Combat AI</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<TabControl>
|
||||
<TabItem>
|
||||
<TabItem.Header>Combat</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<CheckBox Grid.Row="0" Grid.Column="0" IsChecked="{Binding AutoUseShots}">Auto use soul and spiritshots</CheckBox>
|
||||
<CheckBox Grid.Row="1" Grid.Column="0" IsChecked="{Binding UseOnlySkills}">Use only skills</CheckBox>
|
||||
<StackPanel Grid.Row="2" Grid.Column="0">
|
||||
<Label>Attack distance for mili weapon:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="AttackDistanceMili" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="3" Grid.Column="0">
|
||||
<Label>Attack distance for bows:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="AttackDistanceBow" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="4" Grid.Column="0">
|
||||
<Label>Skill conditions:</Label>
|
||||
<DataGrid
|
||||
AutoGenerateColumns="False"
|
||||
Height="150"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
ItemsSource="{Binding CombatSkills}">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTemplateColumn Header="Skill" Width="300">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<ComboBox
|
||||
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Skills}"
|
||||
SelectedValuePath="Id"
|
||||
SelectedValue="{Binding Id}"
|
||||
DisplayMemberPath="Name">
|
||||
<ComboBox.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ComboBox.ItemsPanel>
|
||||
</ComboBox>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
<DataGridTextColumn Header="Max target % HP" Width="100" Binding="{Binding MaxTargetPercentHp}" />
|
||||
<DataGridTextColumn Header="Min player % MP" Width="100" Binding="{Binding MinPlayerPercentMp}" />
|
||||
<DataGridTextColumn Header="Max player % HP" Width="100" Binding="{Binding MaxPlayerPercentHp}" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="5" Grid.Column="0">
|
||||
<Label>Combat zone:</Label>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="100"></ColumnDefinition>
|
||||
<ColumnDefinition Width="120"></ColumnDefinition>
|
||||
<ColumnDefinition Width="80"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0">X:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="1">
|
||||
<TextBox.Text>
|
||||
<Binding Path="Zone.X" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
<Button Grid.Row="0" Grid.Column="2" Command="{Binding GetHeroPosition}">Current</Button>
|
||||
<Label Grid.Row="1" Grid.Column="0">Y:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left" Grid.Row="1" Grid.Column="1">
|
||||
<TextBox.Text>
|
||||
<Binding Path="Zone.Y" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
<Label Grid.Row="2" Grid.Column="0">Radius:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="1">
|
||||
<TextBox.Text>
|
||||
<Binding Path="Zone.Radius" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Mobs</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<Label>Max delta z:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="MobsMaxDeltaZ" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<components:MultipleObjectSelector
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Source="{Binding ExcludedMobs}"
|
||||
Target="{Binding SelectedExcludedMobs}"
|
||||
Header="Excluded:"/>
|
||||
<components:MultipleObjectSelector
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Source="{Binding IncludedMobs}"
|
||||
Target="{Binding SelectedIncludedMobs}"
|
||||
Header="Included:"/>
|
||||
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<Label>Mobs level range:</Label>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Width="100">
|
||||
<TextBox.Text>
|
||||
<Binding Path="MobLevelLowerLimit" UpdateSourceTrigger="PropertyChanged" TargetNullValue=""/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
<TextBlock><= Player level <=</TextBlock>
|
||||
<TextBox Width="100">
|
||||
<TextBox.Text>
|
||||
<Binding Path="MobLevelUpperLimit" UpdateSourceTrigger="PropertyChanged" TargetNullValue=""/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Drop</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<CheckBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" IsChecked="{Binding PickupIfPossible}">Pickup if possible</CheckBox>
|
||||
<StackPanel Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<Label>Max delta z:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="PickupMaxDeltaZ" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<Label>Pickup attempts count:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="PickupAttemptsCount" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<components:MultipleObjectSelector
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Source="{Binding ExcludedItems}"
|
||||
Target="{Binding SelectedExcludedItems}"
|
||||
Header="Excluded:"/>
|
||||
<components:MultipleObjectSelector
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Source="{Binding IncludedItems}"
|
||||
Target="{Binding SelectedIncludedItems}"
|
||||
Header="Included:"/>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Spoil</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<CheckBox Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" IsChecked="{Binding SpoilIfPossible}">Spoil if possible</CheckBox>
|
||||
<CheckBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" IsChecked="{Binding SpoilIsPriority}">Spoil is priority</CheckBox>
|
||||
<StackPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<Label>Sweep attempts count:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="SweepAttemptsCount" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<components:MultipleObjectSelector
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Source="{Binding ExcludedSpoilMobs}"
|
||||
Target="{Binding SelectedExcludedSpoilMobs}"
|
||||
Header="Excluded:"/>
|
||||
<components:MultipleObjectSelector
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Source="{Binding IncludedSpoilMobs}"
|
||||
Target="{Binding SelectedIncludedSpoilMobs}"
|
||||
Header="Included:"/>
|
||||
<StackPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<components:ObjectSelector
|
||||
Source="{Binding Skills}"
|
||||
SelectedValue="{Binding SpoilSkillId, Mode=TwoWay}"
|
||||
Header="Spoil skill:"/>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<components:ObjectSelector
|
||||
Source="{Binding Skills}"
|
||||
SelectedValue="{Binding SweeperSkillId, Mode=TwoWay}"
|
||||
Header="Sweeper skill:"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Rest</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0">
|
||||
<Label>% HP range:</Label>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Width="100">
|
||||
<TextBox.Text>
|
||||
<Binding Path="RestStartPercentHp" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
<TextBlock>-</TextBlock>
|
||||
<TextBox Width="100">
|
||||
<TextBox.Text>
|
||||
<Binding Path="RestEndPercentHp" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1">
|
||||
<Label>% MP range:</Label>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox Width="100">
|
||||
<TextBox.Text>
|
||||
<Binding Path="RestStartPercentMp" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
<TextBlock>-</TextBlock>
|
||||
<TextBox Width="100">
|
||||
<TextBox.Text>
|
||||
<Binding Path="RestEndPercentMp" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Deleveling AI</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Grid.Row="0" Grid.Column="0">
|
||||
<Label>Target level:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="DelevelingTargetLevel" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" Grid.Column="0">
|
||||
<Label>Attack distance:</Label>
|
||||
<TextBox Width="100" HorizontalAlignment="Left">
|
||||
<TextBox.Text>
|
||||
<Binding Path="DelevelingAttackDistance" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="2" Grid.Column="0">
|
||||
<components:ObjectSelector
|
||||
Source="{Binding Skills}"
|
||||
SelectedValue="{Binding DelevelingSkillId, Mode=TwoWay}"
|
||||
Header="Attacking skill:"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="2" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,10,10,0">
|
||||
<StackPanel.Resources>
|
||||
<Style TargetType="{x:Type Button}">
|
||||
<Setter Property="Margin" Value="8,0,0,0"/>
|
||||
</Style>
|
||||
</StackPanel.Resources>
|
||||
<Button Command="{Binding SaveCommand}">Save</Button>
|
||||
<Button Command="{Binding ResetCommand}">Reset</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
83
Client/Application/Views/AIConfig.xaml.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Application.ViewModels;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for CombatAIConfigView.xaml
|
||||
/// </summary>
|
||||
public partial class AIConfig : Window
|
||||
{
|
||||
private AIConfigViewModel viewModel;
|
||||
|
||||
public AIConfig(AIConfigViewModel viewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.viewModel = viewModel;
|
||||
DataContext = viewModel;
|
||||
if (viewModel.Close == null)
|
||||
{
|
||||
viewModel.Close = () => Close();
|
||||
}
|
||||
if (viewModel.OpenSaveDialog == null)
|
||||
{
|
||||
viewModel.OpenSaveDialog = (string data) =>
|
||||
{
|
||||
var dialog = new SaveFileDialog()
|
||||
{
|
||||
Filter = "Json files(*.json)|*.json"
|
||||
};
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
File.WriteAllText(dialog.FileName, data);
|
||||
}
|
||||
};
|
||||
}
|
||||
if (viewModel.OpenOpenDialog == null)
|
||||
{
|
||||
viewModel.OpenOpenDialog = () =>
|
||||
{
|
||||
var dialog = new OpenFileDialog()
|
||||
{
|
||||
Filter = "Json files(*.json)|*.json"
|
||||
};
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
return File.ReadAllText(dialog.FileName);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if ((bool) e.NewValue)
|
||||
{
|
||||
viewModel.LoadConfig();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Client/Application/Views/ItemPanel.xaml
Normal file
@@ -0,0 +1,23 @@
|
||||
<ItemsControl x:Class="Client.Application.Views.ItemPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client.Application.Views"
|
||||
xmlns:components="clr-namespace:Client.Application.Components"
|
||||
mc:Ignorable="d">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<components:Item
|
||||
ImageSource="{Binding Path=IconName,Mode=OneWay}"
|
||||
ItemName="{Binding Path=Name,Mode=OneWay}"
|
||||
Description="{Binding Path=Description,Mode=OneWay}"
|
||||
/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
27
Client/Application/Views/ItemPanel.xaml.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for ItemPanel.xaml
|
||||
/// </summary>
|
||||
public partial class ItemPanel : ItemsControl
|
||||
{
|
||||
public ItemPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
303
Client/Application/Views/MainWindow.xaml
Normal file
@@ -0,0 +1,303 @@
|
||||
<Window x:Class="Client.Application.Views.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client"
|
||||
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
|
||||
xmlns:services="clr-namespace:Client.Application.Services"
|
||||
xmlns:components="clr-namespace:Client.Application.Components"
|
||||
xmlns:views="clr-namespace:Client.Application.Views"
|
||||
mc:Ignorable="d"
|
||||
Title="L2Bot 2.0 Client" Height="600" Width="1024">
|
||||
<Window.Resources>
|
||||
<CollectionViewSource x:Key="SortedCreatures" Source="{Binding Creatures, Mode=OneWay}" IsLiveSortingRequested="True">
|
||||
<CollectionViewSource.SortDescriptions>
|
||||
<scm:SortDescription PropertyName="Distance" Direction="Ascending" />
|
||||
</CollectionViewSource.SortDescriptions>
|
||||
</CollectionViewSource>
|
||||
<CollectionViewSource x:Key="SortedDrops" Source="{Binding Drops, Mode=OneWay}" IsLiveSortingRequested="True">
|
||||
<CollectionViewSource.SortDescriptions>
|
||||
<scm:SortDescription PropertyName="Distance" Direction="Ascending" />
|
||||
</CollectionViewSource.SortDescriptions>
|
||||
</CollectionViewSource>
|
||||
<services:NullToVisibilityConverter x:Key="NullToVisibilityConverter"/>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
<ColumnDefinition Width="444"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="22"></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition Height="240"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<Menu Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2">
|
||||
<MenuItem Header="AI options">
|
||||
<MenuItem Command="{Binding ToggleAICommand}">
|
||||
<MenuItem.Style>
|
||||
<Style TargetType="MenuItem">
|
||||
<Setter Property="Header" Value="Start"></Setter>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding AIStatus, Mode=OneWay}" Value="True">
|
||||
<Setter Property="Header" Value="Stop"></Setter>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.Style>
|
||||
</MenuItem>
|
||||
<MenuItem ItemsSource="{Binding AITypes}" Header="AI type">
|
||||
<MenuItem.ItemContainerStyle>
|
||||
<Style>
|
||||
<Setter Property="MenuItem.Header" Value="{Binding Value}"/>
|
||||
<Setter Property="MenuItem.Command" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ChangeAITypeCommand}"/>
|
||||
<Setter Property="MenuItem.CommandParameter" Value="{Binding Key}"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Value="True">
|
||||
<DataTrigger.Binding>
|
||||
<MultiBinding>
|
||||
<MultiBinding.Converter>
|
||||
<services:EqualityConverter />
|
||||
</MultiBinding.Converter>
|
||||
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type Window}}" Path="DataContext.AIType" />
|
||||
<Binding Path="Key" />
|
||||
</MultiBinding>
|
||||
</DataTrigger.Binding>
|
||||
<Setter Property="MenuItem.IsChecked" Value="True"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</MenuItem.ItemContainerStyle>
|
||||
</MenuItem>
|
||||
<MenuItem Header="Config" Click="AIConfig_Click"/>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<ListBox x:Name="listBox" Grid.Row="2" Grid.Column="0" ItemsSource="{Binding ChatMessages, Mode=OneWay}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Path=Text, Mode=OneWay}" Foreground="{Binding Path=Color, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<components:Map Grid.Column="0" Grid.Row="1" DataContext="{Binding Map}" />
|
||||
<TabControl Grid.Row="1" Grid.Column="1">
|
||||
<TabItem>
|
||||
<TabItem.Header>Environment</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*"></RowDefinition>
|
||||
<RowDefinition Height="1*"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<ListBox ItemsSource="{Binding Source={StaticResource SortedCreatures}, Mode=OneWay}" HorizontalContentAlignment="Stretch">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid x:Name="Item">
|
||||
<StackPanel Margin="5">
|
||||
<StackPanel.InputBindings>
|
||||
<MouseBinding Gesture="LeftClick" Command="{Binding MouseLeftClickCommand}" />
|
||||
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding MouseLeftDoubleClickCommand}" />
|
||||
<MouseBinding Gesture="RightClick" Command="{Binding MouseRightClickCommand}" />
|
||||
</StackPanel.InputBindings>
|
||||
<TextBlock FontSize="16" Text="{Binding Path=Name,Mode=OneWay}" />
|
||||
<TextBlock FontSize="11">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}; distance: {1:F0}; delta z: {2:F0}">
|
||||
<Binding Path="BriefInfo" Mode="OneWay"/>
|
||||
<Binding Path="Distance" Mode="OneWay"/>
|
||||
<Binding Path="DeltaZ" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<DataTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding IsTarget,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="Item" Property="Background" Value="#330000ff" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding IsAttacker,Mode=OneWay}" Value="True">
|
||||
<Setter TargetName="Item" Property="Background" Value="#33ff0000" />
|
||||
</DataTrigger>
|
||||
</DataTemplate.Triggers>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<ListBox ItemsSource="{Binding Source={StaticResource SortedDrops}, Mode=OneWay}" Grid.Row="1" HorizontalContentAlignment="Stretch">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DockPanel>
|
||||
<DockPanel.InputBindings>
|
||||
<MouseBinding Gesture="LeftClick" Command="{Binding MouseLeftClickCommand}" />
|
||||
<MouseBinding Gesture="RightClick" Command="{Binding MouseRightClickCommand}" />
|
||||
</DockPanel.InputBindings>
|
||||
<Image DockPanel.Dock="Left" Source="{Binding Path=IconName, FallbackValue=./Assets/icons/_fallback.png, Mode=OneWay}" Height="32" Width="32" />
|
||||
<StackPanel Margin="5">
|
||||
<TextBlock FontSize="16">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}[{1}]">
|
||||
<Binding Path="Name" Mode="OneWay"/>
|
||||
<Binding Path="ItemId" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}Count {0}; distance: {1:F0}; delta z: {2:F0}">
|
||||
<Binding Path="Amount" Mode="OneWay"/>
|
||||
<Binding Path="Distance" Mode="OneWay"/>
|
||||
<Binding Path="DeltaZ" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Skills</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<TabControl>
|
||||
<TabItem>
|
||||
<TabItem.Header>Active</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<views:SkillPanel ItemsSource="{Binding ActiveSkills,Mode=OneWay}" />
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Passive</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<views:SkillPanel ItemsSource="{Binding PassiveSkills,Mode=OneWay}" />
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Inventory</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<TabControl>
|
||||
<TabItem>
|
||||
<TabItem.Header>Items</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<views:ItemPanel ItemsSource="{Binding Items,Mode=OneWay}" />
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
<TabItem>
|
||||
<TabItem.Header>Quest Items</TabItem.Header>
|
||||
<TabItem.Content>
|
||||
<views:ItemPanel ItemsSource="{Binding QuestItems,Mode=OneWay}" />
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</TabItem.Content>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<Grid Grid.Row="2" Grid.Column="1" DataContext="{Binding Hero, Mode=OneWay}" Margin="4" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"></ColumnDefinition>
|
||||
<ColumnDefinition Width="1*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<StackPanel Margin="4">
|
||||
<TextBlock FontSize="16" Text="{Binding Path=Fullname.Nickname, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock>
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}, {1} {2}lvl">
|
||||
<Binding Path="Phenotype.Race" Mode="OneWay"/>
|
||||
<Binding Path="Phenotype.Class" Mode="OneWay"/>
|
||||
<Binding Path="Experience.Level" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<views:StatsPanel DataContext="{Binding ., Mode=OneWay}" Margin="4" Grid.Row="1" />
|
||||
<DockPanel Grid.Row="2" Margin="4">
|
||||
<StackPanel DockPanel.Dock="Left" Margin="0 0 5 0">
|
||||
<TextBlock Padding="0 0 0 3">Position:</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">Exp:</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">Weight:</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">Adena:</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">Inv. slots:</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Padding="0 0 0 3">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0:F0}, {1:F0}, {2:F0}">
|
||||
<Binding Path="Transform.Position.X" Mode="OneWay"/>
|
||||
<Binding Path="Transform.Position.Y" Mode="OneWay"/>
|
||||
<Binding Path="Transform.Position.Z" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}/{1}">
|
||||
<Binding Path="Experience.Exp" Mode="OneWay"/>
|
||||
<Binding Path="Experience.ExpToLevel" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}/{1}">
|
||||
<Binding Path="InventoryInfo.Weight" Mode="OneWay"/>
|
||||
<Binding Path="InventoryInfo.MaxWeight" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding Path=Money, Mode=OneWay}" Padding="0 0 0 3"></TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0}/{1}">
|
||||
<Binding Path="InventoryInfo.Slots" Mode="OneWay"/>
|
||||
<Binding Path="InventoryInfo.Slots" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<StackPanel Grid.Column="1" DataContext="{Binding Target, Mode=OneWay}" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}" Margin="4">
|
||||
<TextBlock FontSize="16" Text="{Binding Path=Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Text="{Binding Path=BriefInfo, Mode=OneWay}"></TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Margin="4" Grid.Column="1" Grid.Row="1" DataContext="{Binding Target, Mode=OneWay}" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<components:StatsBar
|
||||
BackgroundSource="/Assets/icons/ps_hpbar_back.png"
|
||||
ForegroundSource="/Assets/icons/ps_hpbar.png"
|
||||
Current="{Binding Path=Hp,Mode=OneWay}"
|
||||
Total="{Binding Path=MaxHp,Mode=OneWay}"
|
||||
Height="15"
|
||||
/>
|
||||
</StackPanel>
|
||||
<DockPanel Grid.Column="1" Grid.Row="2" Margin="4" DataContext="{Binding Target, Mode=OneWay}" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<StackPanel DockPanel.Dock="Left" Margin="0 0 5 0">
|
||||
<TextBlock Padding="0 0 0 3">Position:</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">Distance:</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3">Delta Z:</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel>
|
||||
<TextBlock Padding="0 0 0 3">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding StringFormat="{}{0:F0}, {1:F0}, {2:F0}">
|
||||
<Binding Path="Position.X" Mode="OneWay"/>
|
||||
<Binding Path="Position.Y" Mode="OneWay"/>
|
||||
<Binding Path="Position.Z" Mode="OneWay"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
<TextBlock Padding="0 0 0 3" Text="{Binding Distance,Mode=OneWay,StringFormat='{}{0:F0}'}"></TextBlock>
|
||||
<TextBlock Padding="0 0 0 3" Text="{Binding DeltaZ,Mode=OneWay,StringFormat='{}{0:F0}'}"></TextBlock>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
47
Client/Application/Views/MainWindow.xaml.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Client.Application.Components;
|
||||
using Client.Application.ViewModels;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly MainViewModel mainViewModel;
|
||||
private readonly AIConfigViewModel aiConfigViewModel;
|
||||
private AIConfig aiConfigView;
|
||||
|
||||
public MainWindow(MainViewModel mainViewModel, AIConfigViewModel aiConfigViewModel)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = mainViewModel;
|
||||
this.mainViewModel = mainViewModel;
|
||||
this.aiConfigViewModel = aiConfigViewModel;
|
||||
aiConfigView = new AIConfig(aiConfigViewModel);
|
||||
}
|
||||
|
||||
private void AIConfig_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
aiConfigView.Owner = this;
|
||||
aiConfigView.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
28
Client/Application/Views/SkillPanel.xaml
Normal file
@@ -0,0 +1,28 @@
|
||||
<ItemsControl x:Class="Client.Application.Views.SkillPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Client.Application.Views"
|
||||
xmlns:components="clr-namespace:Client.Application.Components"
|
||||
mc:Ignorable="d">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<components:Skill
|
||||
ImageSource="{Binding Path=IconName,Mode=OneWay}"
|
||||
IsReadyToUse="{Binding Path=IsReadyToUse,Mode=OneWay}"
|
||||
IsActive="{Binding Path=IsActive,Mode=OneWay}"
|
||||
SkillName="{Binding Path=Name,Mode=OneWay}"
|
||||
Level="{Binding Path=Level,Mode=OneWay}"
|
||||
Cost="{Binding Path=Cost,Mode=OneWay}"
|
||||
Range="{Binding Path=Range,Mode=OneWay}"
|
||||
Description="{Binding Path=Description,Mode=OneWay}"
|
||||
/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
27
Client/Application/Views/SkillPanel.xaml.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for SkillPanel.xaml
|
||||
/// </summary>
|
||||
public partial class SkillPanel : ItemsControl
|
||||
{
|
||||
public SkillPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Client/Application/Views/StatsPanel.xaml
Normal file
@@ -0,0 +1,40 @@
|
||||
<StackPanel x:Class="Client.Application.Views.StatsPanel"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:components="clr-namespace:Client.Application.Components"
|
||||
mc:Ignorable="d">
|
||||
<components:StatsBar
|
||||
BackgroundSource="/Assets/icons/ps_cpbar_back.png"
|
||||
ForegroundSource="/Assets/icons/ps_cpbar.png"
|
||||
Current="{Binding VitalStats.Cp}"
|
||||
Total="{Binding VitalStats.MaxCp}"
|
||||
Height="15"
|
||||
Margin="0 0 0 2"
|
||||
/>
|
||||
<components:StatsBar
|
||||
BackgroundSource="/Assets/icons/ps_hpbar_back.png"
|
||||
ForegroundSource="/Assets/icons/ps_hpbar.png"
|
||||
Current="{Binding VitalStats.Hp}"
|
||||
Total="{Binding VitalStats.MaxHp}"
|
||||
Height="15"
|
||||
Margin="0 0 0 2"
|
||||
/>
|
||||
<components:StatsBar
|
||||
BackgroundSource="/Assets/icons/ps_mpbar_back.png"
|
||||
ForegroundSource="/Assets/icons/ps_mpbar.png"
|
||||
Current="{Binding VitalStats.Mp}"
|
||||
Total="{Binding VitalStats.MaxMp}"
|
||||
Height="15"
|
||||
Margin="0 0 0 2"
|
||||
/>
|
||||
<components:StatsBar
|
||||
BackgroundSource="/Assets/icons/ps_expbar_back.png"
|
||||
ForegroundSource="/Assets/icons/ps_expbar.png"
|
||||
Current="{Binding Experience.ExpPercent}"
|
||||
Format="{}{0:F2}%"
|
||||
Height="15"
|
||||
Margin="0 0 0 2"
|
||||
/>
|
||||
</StackPanel>
|
||||
27
Client/Application/Views/StatsPanel.xaml.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Client.Application.Views
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for StatsPanel.xaml
|
||||
/// </summary>
|
||||
public partial class StatsPanel : StackPanel
|
||||
{
|
||||
public StatsPanel()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Client/AssemblyInfo.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Windows;
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
352
Client/Assets/data/experience.json
Normal file
@@ -0,0 +1,352 @@
|
||||
{
|
||||
"experience": [
|
||||
{
|
||||
"level": "1",
|
||||
"tolevel": "0"
|
||||
},
|
||||
{
|
||||
"level": "2",
|
||||
"tolevel": "68"
|
||||
},
|
||||
{
|
||||
"level": "3",
|
||||
"tolevel": "363"
|
||||
},
|
||||
{
|
||||
"level": "4",
|
||||
"tolevel": "1168"
|
||||
},
|
||||
{
|
||||
"level": "5",
|
||||
"tolevel": "2884"
|
||||
},
|
||||
{
|
||||
"level": "6",
|
||||
"tolevel": "6038"
|
||||
},
|
||||
{
|
||||
"level": "7",
|
||||
"tolevel": "11287"
|
||||
},
|
||||
{
|
||||
"level": "8",
|
||||
"tolevel": "19423"
|
||||
},
|
||||
{
|
||||
"level": "9",
|
||||
"tolevel": "31378"
|
||||
},
|
||||
{
|
||||
"level": "10",
|
||||
"tolevel": "48229"
|
||||
},
|
||||
{
|
||||
"level": "11",
|
||||
"tolevel": "71201"
|
||||
},
|
||||
{
|
||||
"level": "12",
|
||||
"tolevel": "101676"
|
||||
},
|
||||
{
|
||||
"level": "13",
|
||||
"tolevel": "141192"
|
||||
},
|
||||
{
|
||||
"level": "14",
|
||||
"tolevel": "191452"
|
||||
},
|
||||
{
|
||||
"level": "15",
|
||||
"tolevel": "254327"
|
||||
},
|
||||
{
|
||||
"level": "16",
|
||||
"tolevel": "331864"
|
||||
},
|
||||
{
|
||||
"level": "17",
|
||||
"tolevel": "426284"
|
||||
},
|
||||
{
|
||||
"level": "18",
|
||||
"tolevel": "539995"
|
||||
},
|
||||
{
|
||||
"level": "19",
|
||||
"tolevel": "675590"
|
||||
},
|
||||
{
|
||||
"level": "20",
|
||||
"tolevel": "835854"
|
||||
},
|
||||
{
|
||||
"level": "21",
|
||||
"tolevel": "1023775"
|
||||
},
|
||||
{
|
||||
"level": "22",
|
||||
"tolevel": "1242536"
|
||||
},
|
||||
{
|
||||
"level": "23",
|
||||
"tolevel": "1495531"
|
||||
},
|
||||
{
|
||||
"level": "24",
|
||||
"tolevel": "1786365"
|
||||
},
|
||||
{
|
||||
"level": "25",
|
||||
"tolevel": "2118860"
|
||||
},
|
||||
{
|
||||
"level": "26",
|
||||
"tolevel": "2497059"
|
||||
},
|
||||
{
|
||||
"level": "27",
|
||||
"tolevel": "2925229"
|
||||
},
|
||||
{
|
||||
"level": "28",
|
||||
"tolevel": "3407873"
|
||||
},
|
||||
{
|
||||
"level": "29",
|
||||
"tolevel": "3949727"
|
||||
},
|
||||
{
|
||||
"level": "30",
|
||||
"tolevel": "4555766"
|
||||
},
|
||||
{
|
||||
"level": "31",
|
||||
"tolevel": "5231213"
|
||||
},
|
||||
{
|
||||
"level": "32",
|
||||
"tolevel": "5981539"
|
||||
},
|
||||
{
|
||||
"level": "33",
|
||||
"tolevel": "6812472"
|
||||
},
|
||||
{
|
||||
"level": "34",
|
||||
"tolevel": "7729999"
|
||||
},
|
||||
{
|
||||
"level": "35",
|
||||
"tolevel": "8740372"
|
||||
},
|
||||
{
|
||||
"level": "36",
|
||||
"tolevel": "9850111"
|
||||
},
|
||||
{
|
||||
"level": "37",
|
||||
"tolevel": "11066012"
|
||||
},
|
||||
{
|
||||
"level": "38",
|
||||
"tolevel": "12395149"
|
||||
},
|
||||
{
|
||||
"level": "39",
|
||||
"tolevel": "13844879"
|
||||
},
|
||||
{
|
||||
"level": "40",
|
||||
"tolevel": "15422851"
|
||||
},
|
||||
{
|
||||
"level": "41",
|
||||
"tolevel": "17137002"
|
||||
},
|
||||
{
|
||||
"level": "42",
|
||||
"tolevel": "18995573"
|
||||
},
|
||||
{
|
||||
"level": "43",
|
||||
"tolevel": "21007103"
|
||||
},
|
||||
{
|
||||
"level": "44",
|
||||
"tolevel": "23180442"
|
||||
},
|
||||
{
|
||||
"level": "45",
|
||||
"tolevel": "25524751"
|
||||
},
|
||||
{
|
||||
"level": "46",
|
||||
"tolevel": "28049509"
|
||||
},
|
||||
{
|
||||
"level": "47",
|
||||
"tolevel": "30764519"
|
||||
},
|
||||
{
|
||||
"level": "48",
|
||||
"tolevel": "33679907"
|
||||
},
|
||||
{
|
||||
"level": "49",
|
||||
"tolevel": "36806133"
|
||||
},
|
||||
{
|
||||
"level": "50",
|
||||
"tolevel": "40153995"
|
||||
},
|
||||
{
|
||||
"level": "51",
|
||||
"tolevel": "45524865"
|
||||
},
|
||||
{
|
||||
"level": "52",
|
||||
"tolevel": "51262204"
|
||||
},
|
||||
{
|
||||
"level": "53",
|
||||
"tolevel": "57383682"
|
||||
},
|
||||
{
|
||||
"level": "54",
|
||||
"tolevel": "63907585"
|
||||
},
|
||||
{
|
||||
"level": "55",
|
||||
"tolevel": "70852742"
|
||||
},
|
||||
{
|
||||
"level": "56",
|
||||
"tolevel": "80700339"
|
||||
},
|
||||
{
|
||||
"level": "57",
|
||||
"tolevel": "91162131"
|
||||
},
|
||||
{
|
||||
"level": "58",
|
||||
"tolevel": "102265326"
|
||||
},
|
||||
{
|
||||
"level": "59",
|
||||
"tolevel": "114038008"
|
||||
},
|
||||
{
|
||||
"level": "60",
|
||||
"tolevel": "126509030"
|
||||
},
|
||||
{
|
||||
"level": "61",
|
||||
"tolevel": "146307211"
|
||||
},
|
||||
{
|
||||
"level": "62",
|
||||
"tolevel": "167243291"
|
||||
},
|
||||
{
|
||||
"level": "63",
|
||||
"tolevel": "189363788"
|
||||
},
|
||||
{
|
||||
"level": "64",
|
||||
"tolevel": "212716741"
|
||||
},
|
||||
{
|
||||
"level": "65",
|
||||
"tolevel": "237351413"
|
||||
},
|
||||
{
|
||||
"level": "66",
|
||||
"tolevel": "271973532"
|
||||
},
|
||||
{
|
||||
"level": "67",
|
||||
"tolevel": "308441375"
|
||||
},
|
||||
{
|
||||
"level": "68",
|
||||
"tolevel": "346825235"
|
||||
},
|
||||
{
|
||||
"level": "69",
|
||||
"tolevel": "387197529"
|
||||
},
|
||||
{
|
||||
"level": "70",
|
||||
"tolevel": "429632402"
|
||||
},
|
||||
{
|
||||
"level": "71",
|
||||
"tolevel": "474205751"
|
||||
},
|
||||
{
|
||||
"level": "72",
|
||||
"tolevel": "532692055"
|
||||
},
|
||||
{
|
||||
"level": "73",
|
||||
"tolevel": "606319094"
|
||||
},
|
||||
{
|
||||
"level": "74",
|
||||
"tolevel": "696376867"
|
||||
},
|
||||
{
|
||||
"level": "75",
|
||||
"tolevel": "804219972"
|
||||
},
|
||||
{
|
||||
"level": "76",
|
||||
"tolevel": "931275828"
|
||||
},
|
||||
{
|
||||
"level": "77",
|
||||
"tolevel": "1151275834"
|
||||
},
|
||||
{
|
||||
"level": "78",
|
||||
"tolevel": "1511275834"
|
||||
},
|
||||
{
|
||||
"level": "79",
|
||||
"tolevel": "2099275834"
|
||||
},
|
||||
{
|
||||
"level": "80",
|
||||
"tolevel": "4200000000"
|
||||
},
|
||||
{
|
||||
"level": "81",
|
||||
"tolevel": "6300000000"
|
||||
},
|
||||
{
|
||||
"level": "82",
|
||||
"tolevel": "8820000000"
|
||||
},
|
||||
{
|
||||
"level": "83",
|
||||
"tolevel": "11844000000"
|
||||
},
|
||||
{
|
||||
"level": "84",
|
||||
"tolevel": "15472800000"
|
||||
},
|
||||
{
|
||||
"level": "85",
|
||||
"tolevel": "19827360000"
|
||||
},
|
||||
{
|
||||
"level": "86",
|
||||
"tolevel": "25314105600"
|
||||
},
|
||||
{
|
||||
"level": "87",
|
||||
"tolevel": "32211728640"
|
||||
}
|
||||
]
|
||||
}
|
||||
27648
Client/Assets/data/itemInfo.json
Normal file
39502
Client/Assets/data/npcInfo.json
Normal file
10736
Client/Assets/data/skillInfo.json
Normal file
BIN
Client/Assets/icons/CooltimeEnd001.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Client/Assets/icons/CooltimeEnd002.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Client/Assets/icons/CooltimeEnd003.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Client/Assets/icons/CooltimeEnd004.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/CooltimeEnd005.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
Client/Assets/icons/CooltimeEnd006.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
Client/Assets/icons/CooltimeEnd007.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
Client/Assets/icons/CooltimeEnd008.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
Client/Assets/icons/CooltimeEnd009.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/ToggleEffect001.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Client/Assets/icons/ToggleEffect002.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Client/Assets/icons/ToggleEffect003.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Client/Assets/icons/ToggleEffect004.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
Client/Assets/icons/ToggleEffect005.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/ToggleEffect006.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/ToggleEffect007.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/ToggleEffect008.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/ToggleEffect009.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
Client/Assets/icons/ToggleEffect010.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
Client/Assets/icons/ToggleEffect011.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
Client/Assets/icons/ToggleEffect012.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
Client/Assets/icons/ToggleEffect013.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
Client/Assets/icons/_fallback.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
Client/Assets/icons/cooltime0.png
Normal file
|
After Width: | Height: | Size: 960 B |
BIN
Client/Assets/icons/cooltime1.png
Normal file
|
After Width: | Height: | Size: 974 B |
BIN
Client/Assets/icons/cooltime10.png
Normal file
|
After Width: | Height: | Size: 983 B |
BIN
Client/Assets/icons/cooltime100.png
Normal file
|
After Width: | Height: | Size: 981 B |
BIN
Client/Assets/icons/cooltime101.png
Normal file
|
After Width: | Height: | Size: 985 B |
BIN
Client/Assets/icons/cooltime102.png
Normal file
|
After Width: | Height: | Size: 985 B |
BIN
Client/Assets/icons/cooltime103.png
Normal file
|
After Width: | Height: | Size: 985 B |
BIN
Client/Assets/icons/cooltime104.png
Normal file
|
After Width: | Height: | Size: 989 B |
BIN
Client/Assets/icons/cooltime105.png
Normal file
|
After Width: | Height: | Size: 989 B |
BIN
Client/Assets/icons/cooltime106.png
Normal file
|
After Width: | Height: | Size: 989 B |
BIN
Client/Assets/icons/cooltime107.png
Normal file
|
After Width: | Height: | Size: 991 B |
BIN
Client/Assets/icons/cooltime108.png
Normal file
|
After Width: | Height: | Size: 991 B |
BIN
Client/Assets/icons/cooltime109.png
Normal file
|
After Width: | Height: | Size: 991 B |
BIN
Client/Assets/icons/cooltime11.png
Normal file
|
After Width: | Height: | Size: 986 B |
BIN
Client/Assets/icons/cooltime110.png
Normal file
|
After Width: | Height: | Size: 995 B |
BIN
Client/Assets/icons/cooltime111.png
Normal file
|
After Width: | Height: | Size: 995 B |
BIN
Client/Assets/icons/cooltime112.png
Normal file
|
After Width: | Height: | Size: 995 B |
BIN
Client/Assets/icons/cooltime113.png
Normal file
|
After Width: | Height: | Size: 998 B |
BIN
Client/Assets/icons/cooltime114.png
Normal file
|
After Width: | Height: | Size: 998 B |
BIN
Client/Assets/icons/cooltime115.png
Normal file
|
After Width: | Height: | Size: 998 B |
BIN
Client/Assets/icons/cooltime116.png
Normal file
|
After Width: | Height: | Size: 1003 B |
BIN
Client/Assets/icons/cooltime117.png
Normal file
|
After Width: | Height: | Size: 1003 B |
BIN
Client/Assets/icons/cooltime118.png
Normal file
|
After Width: | Height: | Size: 1004 B |
BIN
Client/Assets/icons/cooltime119.png
Normal file
|
After Width: | Height: | Size: 1004 B |
BIN
Client/Assets/icons/cooltime12.png
Normal file
|
After Width: | Height: | Size: 986 B |
BIN
Client/Assets/icons/cooltime120.png
Normal file
|
After Width: | Height: | Size: 1004 B |
BIN
Client/Assets/icons/cooltime121.png
Normal file
|
After Width: | Height: | Size: 1007 B |
BIN
Client/Assets/icons/cooltime122.png
Normal file
|
After Width: | Height: | Size: 1007 B |