Skip to content

Commit

Permalink
keep view model if it already exists when retargeting an actor
Browse files Browse the repository at this point in the history
Fixes #540
relates to #548
  • Loading branch information
Yuki-Codes committed Oct 1, 2021
1 parent 9dd1405 commit 1d46dec
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 37 deletions.
10 changes: 5 additions & 5 deletions Anamnesis/Core/Memory/Types/ActorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class ActorViewModel : ActorBasicViewModel

private short refreshDelay;
private Task? refreshTask;
private IntPtr? previousPlayerPointerBeforeGPose;

public ActorViewModel(IntPtr pointer)
: base(pointer)
Expand All @@ -32,7 +33,6 @@ public ActorViewModel(IntPtr pointer)
public bool AutomaticRefreshEnabled { get; set; } = true;
public bool IsRefreshing { get; set; } = false;
public bool PendingRefresh { get; set; } = false;
public IntPtr? PreviousPointerBeforeGPose { get; set; }

public override void OnRetargeted()
{
Expand All @@ -48,23 +48,23 @@ public override void OnRetargeted()
// Entering gpose
if (this.ObjectKind == ActorTypes.Player)
{
this.PreviousPointerBeforeGPose = this.Pointer;
this.previousPlayerPointerBeforeGPose = this.Pointer;
this.SetObjectKindDirect(ActorTypes.BattleNpc, this.Pointer);

// Sanity check that we do get turned back into a player
Task.Run(async () =>
{
await Task.Delay(3000);
this.SetObjectKindDirect(ActorTypes.Player, this.PreviousPointerBeforeGPose);
this.SetObjectKindDirect(ActorTypes.Player, this.previousPlayerPointerBeforeGPose);
});
}
}
else if (gpose.IsGpose && !gpose.IsChangingState)
{
// Entered gpose
if (this.PreviousPointerBeforeGPose != null)
if (this.previousPlayerPointerBeforeGPose != null)
{
this.SetObjectKindDirect(ActorTypes.Player, this.PreviousPointerBeforeGPose);
this.SetObjectKindDirect(ActorTypes.Player, this.previousPlayerPointerBeforeGPose);
this.SetObjectKindDirect(ActorTypes.Player, this.Pointer);
}
}
Expand Down
98 changes: 66 additions & 32 deletions Anamnesis/Services/TargetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class TargetService : ServiceBase<TargetService>
public ActorViewModel? SelectedActor { get; private set; }
public ObservableCollection<PinnedActor> PinnedActors { get; set; } = new ObservableCollection<PinnedActor>();

private static bool EnableActorTicking { get; set; }

public static async Task PinActor(ActorBasicViewModel basicActor)
{
if (basicActor.Pointer == null)
Expand Down Expand Up @@ -77,7 +79,7 @@ public static void UnpinActor(PinnedActor actor)
{
Instance.PinnedActors.Remove(actor);

if (actor.GetViewModel() == Instance.SelectedActor)
if (actor.ViewModel == Instance.SelectedActor)
{
if (Instance.PinnedActors.Count > 0)
{
Expand Down Expand Up @@ -145,7 +147,7 @@ public override async Task Start()
await PinActor(allaCtors[0]);
}

_ = Task.Run(this.TickSelectedActor);
_ = Task.Run(this.TickPinnedActors);
}

public void ClearSelection()
Expand Down Expand Up @@ -223,40 +225,39 @@ public void SelectActorViewModel(ActorViewModel? actor)
ActorSelected?.Invoke(actor);
}

private async Task TickSelectedActor()
private async Task TickPinnedActors()
{
while (this.IsAlive)
{
await Task.Delay(33);

if (this.SelectedActor == null)
continue;

try
if (!TargetService.EnableActorTicking)
{
this.SelectedActor.ReadChanges();
await Task.Delay(100);
continue;
}
catch (Exception ex)

foreach (PinnedActor actor in this.PinnedActors)
{
Log.Error(ex, "Failed to tick selected actor");
actor.Tick();
}
}
}

[AddINotifyPropertyChangedInterface]
public class PinnedActor : INotifyPropertyChanged
{
private ActorViewModel? viewModel;

public PinnedActor(ActorViewModel actorVm)
{
this.Id = actorVm.Id;
this.viewModel = actorVm;
this.ViewModel = actorVm;
this.Retarget();
}

public event PropertyChangedEventHandler? PropertyChanged;

public ActorViewModel? ViewModel { get; private set; }

public string? Name { get; private set; }
public string Id { get; private set; }
public IntPtr? Pointer { get; private set; }
Expand All @@ -267,7 +268,8 @@ public PinnedActor(ActorViewModel actorVm)
public bool IsValid { get; private set; }
public bool IsPinned => TargetService.Instance.PinnedActors.Contains(this);

public string? DisplayName => this.viewModel == null ? this.Name : this.viewModel.DisplayName;
public string? DisplayName => this.ViewModel == null ? this.Name : this.ViewModel.DisplayName;
public bool IsRetargeting { get; private set; } = false;

public bool IsSelected
{
Expand All @@ -293,15 +295,15 @@ public bool IsSelected

public override string? ToString()
{
if (this.viewModel == null)
if (this.ViewModel == null)
return base.ToString();

return this.viewModel.DisplayName;
return this.ViewModel.DisplayName;
}

public void Dispose()
{
this.viewModel?.Dispose();
this.ViewModel?.Dispose();
}

public void SelectionChanged()
Expand All @@ -312,57 +314,89 @@ public void SelectionChanged()
public ActorViewModel? GetViewModel()
{
this.Retarget();
return this.viewModel;
return this.ViewModel;
}

public override int GetHashCode()
{
return HashCode.Combine(this.Pointer, this.Name);
}

public void Tick()
{
lock (this)
{
if (this.IsRetargeting)
return;

if (this.ViewModel == null)
return;

try
{
this.ViewModel.ReadChanges();
}
catch (Exception ex)
{
Log.Error(ex, "Failed to tick selected actor");
}
}
}

private void Retarget()
{
lock (this)
{
if (this.viewModel != null)
this.viewModel.PropertyChanged -= this.OnViewModelPropertyChanged;
this.IsRetargeting = true;

IntPtr? previousPointerBeforeGPose = this.viewModel?.PreviousPointerBeforeGPose;
if (this.ViewModel != null)
this.ViewModel.PropertyChanged -= this.OnViewModelPropertyChanged;

foreach (ActorBasicViewModel actor in TargetService.GetAllActors())
{
if (actor.Id != this.Id || actor.Pointer == null)
continue;

this.viewModel = new ActorViewModel((IntPtr)actor.Pointer);
this.viewModel.PreviousPointerBeforeGPose = previousPointerBeforeGPose;
this.Name = this.viewModel.Name;
this.viewModel.OnRetargeted();
this.viewModel.PropertyChanged += this.OnViewModelPropertyChanged;
this.Pointer = this.viewModel.Pointer;
this.Kind = this.viewModel.ObjectKind;
this.ModelType = this.viewModel.ModelType;
if (this.ViewModel != null)
{
this.ViewModel.Pointer = actor.Pointer;
this.ViewModel.ReadChanges();
}
else
{
this.ViewModel = new ActorViewModel((IntPtr)actor.Pointer);
}

this.Name = this.ViewModel.Name;
this.ViewModel.OnRetargeted();
this.ViewModel.PropertyChanged += this.OnViewModelPropertyChanged;
this.Pointer = this.ViewModel.Pointer;
this.Kind = this.ViewModel.ObjectKind;
this.ModelType = this.ViewModel.ModelType;

this.UpdateInitials(this.DisplayName);

this.IsValid = true;
Log.Information($"Retargeted actor: {this.Initials}");

this.IsRetargeting = false;

return;
}

this.viewModel?.Dispose();
this.ViewModel?.Dispose();
Log.Warning($"Lost actor: {this.Initials}");

this.IsValid = false;
this.IsRetargeting = false;
}
}

private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (this.viewModel != null && e.PropertyName == nameof(ActorViewModel.DisplayName))
if (this.ViewModel != null && e.PropertyName == nameof(ActorViewModel.DisplayName))
{
this.UpdateInitials(this.viewModel.DisplayName);
this.UpdateInitials(this.ViewModel.DisplayName);
}
}

Expand Down

0 comments on commit 1d46dec

Please sign in to comment.