// // 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 Reloaded.Memory.Sources; using Remora.Results; namespace NosSmooth.LocalBinding.Objects; /// /// The binding to NosTale pet manager. /// public class PetManagerBinding { private readonly IMemory _memory; /// /// 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(bindingManager.Memory, petManagerList); var hookResult = bindingManager.CreateHookFromPattern ( "PetManagerBinding.PetWalk", petManager.PetWalkDetour, options.PetWalkPattern, enableHook: 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(IMemory memory, PetManagerList petManagerList) { _memory = memory; PetManagerList = petManagerList; } /// /// Event that is called when walk was called by NosTale. /// /// /// The walk must be hooked for this event to be called. /// public event Func? PetWalkCall; /// /// 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, short x, short y) { uint position = Convert.ToUInt32(((ushort)y << 16) | (ushort)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 ) { var result = PetWalkCall?.Invoke(new PetManager(_memory, petManagerPtr), (ushort)(position & 0xFFFF), (ushort)((position >> 16) & 0xFFFF)); if (result ?? true) { return _petWalkHook.OriginalFunction ( petManagerPtr, position, unknown0, unknown1, unknown2 ); } return false; } }