//
// PetManagerBinding.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using NosSmooth.LocalBinding.Options;
using NosSmooth.LocalBinding.Structs;
using Reloaded.Hooks.Definitions;
using Reloaded.Hooks.Definitions.X86;
using Remora.Results;
namespace NosSmooth.LocalBinding.Objects;
///
/// The binding to NosTale pet manager.
///
public class PetManagerBinding
{
///
/// Create nostale pet manager binding.
///
/// The binding manager.
/// The list of the pet managers.
/// The options.
/// A pet manager binding or and error.
public static Result Create
(NosBindingManager bindingManager, PetManagerList petManagerList, PetManagerBindingOptions options)
{
var petManager = new PetManagerBinding(petManagerList);
var hookResult = bindingManager.CreateHookFromPattern
(
"PetManagerBinding.PetWalk",
petManager.PetWalkDetour,
options.PetWalkPattern,
hook: options.HookPetWalk
);
if (!hookResult.IsSuccess)
{
return Result.FromError(hookResult);
}
petManager._petWalkHook = hookResult.Entity;
return petManager;
}
[Function
(
new[] { FunctionAttribute.Register.eax, FunctionAttribute.Register.edx, FunctionAttribute.Register.ecx },
FunctionAttribute.Register.eax,
FunctionAttribute.StackCleanup.Callee
)]
private delegate bool PetWalkDelegate
(
IntPtr petManagerPtr,
uint position,
short unknown0 = 0,
int unknown1 = 1,
int unknown2 = 1
);
private IHook _petWalkHook = null!;
private PetManagerBinding(PetManagerList petManagerList)
{
PetManagerList = petManagerList;
}
///
/// Gets the hook of the pet walk function.
///
public IHook PetWalkHook => _petWalkHook;
///
/// Gets pet manager list.
///
public PetManagerList PetManagerList { get; }
///
/// Walk the given pet to the given location.
///
/// Index of the pet to walk. -1 for every pet currently available.
/// The x coordinate.
/// The y coordinate.
/// A result returned from NosTale or an error.
public Result PetWalk(int selector, ushort x, ushort y)
{
uint position = ((uint)y << 16) | x;
if (PetManagerList.Length < selector + 1)
{
return new NotFoundError("Could not find the pet using the given selector.");
}
if (selector == -1)
{
bool lastResult = true;
for (int i = 0; i < PetManagerList.Length; i++)
{
lastResult = _petWalkHook.OriginalFunction(PetManagerList[i].Address, position);
}
return lastResult;
}
else
{
return _petWalkHook.OriginalFunction(PetManagerList[selector].Address, position);
}
}
private bool PetWalkDetour
(
IntPtr petManagerPtr,
uint position,
short unknown0 = 0,
int unknown1 = 1,
int unknown2 = 1
)
{
return _petWalkHook.OriginalFunction
(
petManagerPtr,
position,
unknown0,
unknown1,
unknown2
);
}
}