feat: add hero target

This commit is contained in:
k0t9i 2023-01-31 17:35:18 +04:00
parent d2b20e0666
commit bd50473bfb
9 changed files with 261 additions and 60 deletions

View File

@ -66,6 +66,14 @@ namespace Client.Application.ViewModels
return 0; return 0;
} }
} }
public CreatureListViewModel? Target
{
get
{
return target;
}
}
public HeroSummaryInfoViewModel(Hero hero) public HeroSummaryInfoViewModel(Hero hero)
{ {
this.hero = hero; this.hero = hero;
@ -76,6 +84,24 @@ namespace Client.Application.ViewModels
hero.Transform.PropertyChanged += Transform_PropertyChanged; hero.Transform.PropertyChanged += Transform_PropertyChanged;
hero.VitalStats.PropertyChanged += VitalStats_PropertyChanged; hero.VitalStats.PropertyChanged += VitalStats_PropertyChanged;
hero.InventoryInfo.PropertyChanged += InventoryInfo_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 CreatureListViewModel(hero.Target, hero);
OnPropertyChanged("Target");
}
else if (target != null && hero.Target == null)
{
target = null;
OnPropertyChanged("Target");
}
}
} }
private void InventoryInfo_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) private void InventoryInfo_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
@ -109,5 +135,6 @@ namespace Client.Application.ViewModels
} }
private readonly Hero hero; private readonly Hero hero;
private CreatureListViewModel? target;
} }
} }

View File

@ -97,9 +97,13 @@
</TabItem.Content> </TabItem.Content>
</TabItem> </TabItem>
</TabControl> </TabControl>
<StackPanel Grid.Row="1" Grid.Column="1" DataContext="{Binding Hero, Mode=OneWay}" Margin="4" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}"> <Grid Grid.Row="1" Grid.Column="1">
<TextBlock FontSize="16" Text="{Binding Path=Fullname.Nickname, Mode=OneWay}"></TextBlock> <Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal"> <ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackPanel DataContext="{Binding Hero, Mode=OneWay}" Margin="4" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}">
<TextBlock FontSize="16" Text="{Binding Path=Fullname.Nickname, Mode=OneWay}"></TextBlock>
<TextBlock> <TextBlock>
<TextBlock.Text> <TextBlock.Text>
<MultiBinding StringFormat="{}{0}, {1} {2}lvl"> <MultiBinding StringFormat="{}{0}, {1} {2}lvl">
@ -109,53 +113,77 @@
</MultiBinding> </MultiBinding>
</TextBlock.Text> </TextBlock.Text>
</TextBlock> </TextBlock>
<components:StatsPanel DataContext="{Binding ., Mode=OneWay}" Margin="0 5 0 5" />
<DockPanel>
<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> </StackPanel>
<components:StatsPanel DataContext="{Binding ., Mode=OneWay}" Margin="0 5 0 5" /> <StackPanel Grid.Column="1" DataContext="{Binding Hero.Target, Mode=OneWay}" Margin="4" Visibility="{Binding Path=.,Converter={StaticResource NullToVisibilityConverter}}">
<DockPanel> <TextBlock FontSize="16" Text="{Binding Path=Name, Mode=OneWay}"></TextBlock>
<StackPanel DockPanel.Dock="Left" Margin="0 0 5 0"> <TextBlock Text="{Binding Path=BriefInfo, Mode=OneWay}"></TextBlock>
<TextBlock Padding="0 0 0 3">Position:</TextBlock> <DockPanel>
<TextBlock Padding="0 0 0 3">Exp:</TextBlock> <StackPanel DockPanel.Dock="Left" Margin="0 0 5 0">
<TextBlock Padding="0 0 0 3">Weight:</TextBlock> <TextBlock Padding="0 0 0 3">Position:</TextBlock>
<TextBlock Padding="0 0 0 3">Adena:</TextBlock> <TextBlock Padding="0 0 0 3">Distance:</TextBlock>
<TextBlock Padding="0 0 0 3">Inv. slots:</TextBlock> <TextBlock Padding="0 0 0 3">Delta Z:</TextBlock>
</StackPanel> </StackPanel>
<StackPanel> <StackPanel>
<TextBlock Padding="0 0 0 3"> <TextBlock Padding="0 0 0 3">
<TextBlock.Text> <TextBlock.Text>
<MultiBinding StringFormat="{}{0:F0}, {1:F0}, {2:F0}"> <MultiBinding StringFormat="{}{0:F0}, {1:F0}, {2:F0}">
<Binding Path="Transform.Position.X" Mode="OneWay"/> <Binding Path="Transform.Position.X" Mode="OneWay"/>
<Binding Path="Transform.Position.Y" Mode="OneWay"/> <Binding Path="Transform.Position.Y" Mode="OneWay"/>
<Binding Path="Transform.Position.Z" Mode="OneWay"/> <Binding Path="Transform.Position.Z" Mode="OneWay"/>
</MultiBinding> </MultiBinding>
</TextBlock.Text> </TextBlock.Text>
</TextBlock> </TextBlock>
<TextBlock Padding="0 0 0 3"> <TextBlock Padding="0 0 0 3" Text="{Binding Distance,Mode=OneWay,StringFormat='{}{0:F2}m'}"></TextBlock>
<TextBlock.Text> <TextBlock Padding="0 0 0 3" Text="{Binding DeltaZ,Mode=OneWay,StringFormat='{}{0:F2}m'}"></TextBlock>
<MultiBinding StringFormat="{}{0}/{1}"> </StackPanel>
<Binding Path="Experience.Exp" Mode="OneWay"/> </DockPanel>
<Binding Path="Experience.ExpToLevel" Mode="OneWay"/> </StackPanel>
</MultiBinding> </Grid>
</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> </Grid>
</Window> </Window>

View File

@ -9,6 +9,7 @@ using Client.Application.ViewModels;
using Client.Domain.Events; using Client.Domain.Events;
using Client.Domain.Factories; using Client.Domain.Factories;
using Client.Domain.Parsers; using Client.Domain.Parsers;
using Client.Domain.Service;
using Client.Domain.Transports; using Client.Domain.Transports;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -69,6 +70,13 @@ namespace Client
eventBus.Subscrbe((EventHandlerInterface<HeroDeletedEvent>)viewModel); eventBus.Subscrbe((EventHandlerInterface<HeroDeletedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<CreatureCreatedEvent>)viewModel); eventBus.Subscrbe((EventHandlerInterface<CreatureCreatedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<CreatureDeletedEvent>)viewModel); eventBus.Subscrbe((EventHandlerInterface<CreatureDeletedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<DropCreatedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<DropDeletedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<ChatMessageCreatedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<TargetChangedEvent>)serviceProvider.GetRequiredService<HeroHandler>());
eventBus.Subscrbe((EventHandlerInterface<TargetChangedEvent>)serviceProvider.GetRequiredService<NpcHandler>());
eventBus.Subscrbe((EventHandlerInterface<TargetChangedEvent>)serviceProvider.GetRequiredService<PlayerHandler>());
} }
private void OnMessage(string args) private void OnMessage(string args)

View File

@ -1,29 +1,77 @@
using Client.Domain.ValueObjects; using Client.Domain.Common;
using Client.Domain.ValueObjects;
using System.ComponentModel;
using System.Diagnostics;
namespace Client.Domain.Entities namespace Client.Domain.Entities
{ {
public class Hero : EntityInterface public class Hero : NotifyPropertyChanged, EntityInterface, CreatureInterface
{ {
private FullName fullName;
private Phenotype phenotype;
private CreatureInterface? target;
private uint targetId;
public uint Id { get; set; } public uint Id { get; set; }
public Transform Transform { get; set; } public Transform Transform { get; set; }
public FullName FullName { get; set; }
public VitalStats VitalStats { get; set; } public VitalStats VitalStats { get; set; }
public Phenotype Phenotype { get; set; }
public ExperienceInfo ExperienceInfo { get; set; } public ExperienceInfo ExperienceInfo { get; set; }
public PermanentStats PermanentStats { get; set; } public PermanentStats PermanentStats { get; set; }
public VariableStats VariableStats { get; set; } public VariableStats VariableStats { get; set; }
public Reputation Reputation { get; set; } public Reputation Reputation { get; set; }
public InventoryInfo InventoryInfo { get; set; } public InventoryInfo InventoryInfo { get; set; }
public uint TargetId { get; set; } public uint TargetId { get => targetId; set { if (value != targetId) { targetId = value; OnPropertyChanged("TargetId"); } } }
public CreatureInterface? Target { get => target; set { if (value != target) { target = value; OnPropertyChanged("Target"); } } }
public bool IsStanding { get; set; } public bool IsStanding { get; set; }
public FullName FullName
{
get => fullName;
set
{
fullName = value;
if (fullName != null)
{
FullName.PropertyChanged += FullName_PropertyChanged; ;
}
}
}
public Phenotype Phenotype
{
get => phenotype;
set
{
phenotype = value;
if (phenotype != null)
{
Phenotype.PropertyChanged += Phenotype_PropertyChanged;
}
}
}
public string Name
{
get
{
return FullName.Nickname;
}
}
public string BriefInfo
{
get
{
//todo race and class strings
return Phenotype.Race.ToString() + ", " + Phenotype.Class.ToString();
}
}
public Hero(uint id, Transform transform, FullName fullName, VitalStats vitalStats, Phenotype phenotype, ExperienceInfo experienceInfo, PermanentStats permanentStats, VariableStats variableStats, Reputation reputation, InventoryInfo inventoryInfo, uint targetId, bool isStanding) public Hero(uint id, Transform transform, FullName fullName, VitalStats vitalStats, Phenotype phenotype, ExperienceInfo experienceInfo, PermanentStats permanentStats, VariableStats variableStats, Reputation reputation, InventoryInfo inventoryInfo, uint targetId, bool isStanding)
{ {
Id = id; Id = id;
Transform = transform; Transform = transform;
FullName = fullName; this.fullName = FullName = fullName;
VitalStats = vitalStats; VitalStats = vitalStats;
Phenotype = phenotype; this.phenotype = Phenotype = phenotype;
ExperienceInfo = experienceInfo; ExperienceInfo = experienceInfo;
PermanentStats = permanentStats; PermanentStats = permanentStats;
VariableStats = variableStats; VariableStats = variableStats;
@ -32,5 +80,21 @@ namespace Client.Domain.Entities
TargetId = targetId; TargetId = targetId;
IsStanding = isStanding; IsStanding = isStanding;
} }
private void Phenotype_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Race" || e.PropertyName == "Class")
{
OnPropertyChanged("BriefInfo");
}
}
private void FullName_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Nickname")
{
OnPropertyChanged("Name");
}
}
} }
} }

View File

@ -0,0 +1,19 @@
using Client.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public class TargetChangedEvent : EventInterface
{
public readonly Hero Hero;
public TargetChangedEvent(Hero hero)
{
Hero = hero;
}
}
}

View File

@ -43,6 +43,15 @@ namespace Client.Domain.Service
} }
} }
public T? GetEntity(uint id)
{
T? result = null;
entities.TryGetValue(id, out result);
return result;
}
public virtual void OnCreate(T entity) public virtual void OnCreate(T entity)
{ {

View File

@ -10,12 +10,13 @@ using System.Threading.Tasks;
namespace Client.Domain.Service namespace Client.Domain.Service
{ {
public class HeroHandler : EntityHandler<Hero> public class HeroHandler : EntityHandler<Hero>, EventHandlerInterface<TargetChangedEvent>
{ {
public override void OnCreate(Hero entity) public override void OnCreate(Hero entity)
{ {
entity.ExperienceInfo.ExpToLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level + 1); entity.ExperienceInfo.ExpToLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level + 1);
entity.ExperienceInfo.ExpToPrevLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level); entity.ExperienceInfo.ExpToPrevLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level);
entity.PropertyChanged += Hero_PropertyChanged;
eventBus.Publish(new HeroCreatedEvent(entity)); eventBus.Publish(new HeroCreatedEvent(entity));
} }
@ -39,6 +40,31 @@ namespace Client.Domain.Service
this.experienceHelper = experienceHelper; this.experienceHelper = experienceHelper;
} }
private void Hero_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (sender == null)
{
return;
}
var hero = (Hero)sender;
if (e.PropertyName == "TargetId")
{
hero.Target = null;
eventBus.Publish(new TargetChangedEvent(hero));
}
}
public void Handle(TargetChangedEvent @event)
{
var target = GetEntity(@event.Hero.TargetId);
if (target == null)
{
return;
}
@event.Hero.Target = target;
}
private readonly EventBusInterface eventBus; private readonly EventBusInterface eventBus;
private readonly ExperienceHelperInterface experienceHelper; private readonly ExperienceHelperInterface experienceHelper;
} }

View File

@ -10,7 +10,7 @@ using System.Threading.Tasks;
namespace Client.Domain.Service namespace Client.Domain.Service
{ {
public class NpcHandler : EntityHandler<NPC> public class NpcHandler : EntityHandler<NPC>, EventHandlerInterface<TargetChangedEvent>
{ {
public override void OnCreate(NPC entity) public override void OnCreate(NPC entity)
{ {
@ -23,6 +23,16 @@ namespace Client.Domain.Service
eventBus.Publish(new CreatureDeletedEvent(entity.Id)); eventBus.Publish(new CreatureDeletedEvent(entity.Id));
} }
public void Handle(TargetChangedEvent @event)
{
var target = GetEntity(@event.Hero.TargetId);
if (target == null)
{
return;
}
@event.Hero.Target = target;
}
public NpcHandler(EntityFactoryInterface<NPC> factory, EventBusInterface eventBus, NpcInfoHelperInterface npcInfoHelper) : base(factory) public NpcHandler(EntityFactoryInterface<NPC> factory, EventBusInterface eventBus, NpcInfoHelperInterface npcInfoHelper) : base(factory)
{ {
this.eventBus = eventBus; this.eventBus = eventBus;

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace Client.Domain.Service namespace Client.Domain.Service
{ {
public class PlayerHandler : EntityHandler<Player> public class PlayerHandler : EntityHandler<Player>, EventHandlerInterface<TargetChangedEvent>
{ {
public override void OnCreate(Player entity) public override void OnCreate(Player entity)
{ {
@ -25,6 +25,16 @@ namespace Client.Domain.Service
this.eventBus = eventBus; this.eventBus = eventBus;
} }
public void Handle(TargetChangedEvent @event)
{
var target = GetEntity(@event.Hero.TargetId);
if (target == null)
{
return;
}
@event.Hero.Target = target;
}
private readonly EventBusInterface eventBus; private readonly EventBusInterface eventBus;
} }
} }