Page 1 of 1

Getting IMoveHelper instance?

Posted: Wed Apr 18, 2018 2:12 am
by quartata
Hey all,

So I was going through an old plugin of mine and I noticed in parts that I was using a pre-hook to hook into CBasePlayer::PlayerRunCommand and inject my own usercmds there. I kinda find that a little ugly, so I wanted to try and call PlayerRunCommand directly instead. However when looking at the signature for it, I noticed it also needs an IMoveHelper*... I don't really know what it does, but it seems to be a singleton object -- the SDK calls IMoveHelper::GetSingleton to get a handle to one. However, it's obviously not a virtual function, so I wouldn't know how to call it easily from SP. How can I do this?

Thanks.

Re: Getting IMoveHelper instance?

Posted: Wed Apr 18, 2018 4:40 pm
by quartata
This is the header I found, for reference: https://github.com/ValveSoftware/source ... vehelper.h

This is what one of the SDK sample plugins does: https://github.com/ValveSoftware/source ... p.cpp#L203 Looks like IMoveHelper has separate server and client implementations which obfuscates things

Re: Getting IMoveHelper instance?

Posted: Thu Apr 19, 2018 5:35 pm
by Ayuto
There are multiple ways to retrieve the IMoveHelper instance. A quick and dirty hack would be to hook PlayerRunCommand, store the IMoveHelper instance and then unhook it.

The nice and clean solution is to call MoveHelper() or directly rip out the singleton instance. MoveHelper() is defined in the server binary.

For which game/OS do you need this?

Re: Getting IMoveHelper instance?

Posted: Fri Apr 20, 2018 11:39 pm
by quartata
This is for TF2. I'm developing on Linux currently (do I need to resort to signature scanning?)

I thought of hooking PlayerRunCommand, the only trouble is I can't guarantee that there will be any non-fake clients to run it in the first place... are there any other virtual methods that get the IMoveHelper instance?

Re: Getting IMoveHelper instance?

Posted: Sat Apr 21, 2018 10:12 am
by Ayuto
Since the binaries in TF2 contains symbols on Linux, you don't need signature scanning. You can simply do this:

Syntax: Select all

import memory

from memory import DataType
from memory import Convention

server = memory.find_binary('server')

MoveHelperServer = server['_Z16MoveHelperServerv'].make_function(
Convention.CDECL,
[],
DataType.POINTER)

ptr = MoveHelperServer()

Re: Getting IMoveHelper instance?

Posted: Sun Apr 22, 2018 12:46 am
by quartata
Oh cool! I thought they had starting stripping out the symbols, but maybe that was CS:GO... anyways thanks!

Re: Getting IMoveHelper instance?

Posted: Mon Apr 23, 2018 2:17 am
by quartata
Seem to have had no joy with this test plugin:

Syntax: Select all

import engines.server
import entities.helpers
import memory
import listeners
import players
import players.entity

def load():
bot_ptr = entities.helpers.pointer_from_edict(engines.server.engine_server.create_fake_client("asdf"))

run_command = bot_ptr.make_virtual_function(423, memory.Convention.THISCALL,
(memory.DataType.POINTER, memory.DataType.POINTER, memory.DataType.POINTER),
memory.DataType.VOID)

bot = memory.make_object(players.entity.Player, bot_ptr)
bot.set_team(2)
bot.set_property_uchar("m_Shared.m_iDesiredPlayerClass", 1)
bot.spawn()

server = memory.find_binary("server")

move_helper = server["_Z16MoveHelperServerv"].make_function(memory.Convention.CDECL,
(),
memory.DataType.POINTER)()
set_host = move_helper.make_virtual_function(14, memory.Convention.THISCALL,
(memory.DataType.POINTER, memory.DataType.POINTER),
memory.DataType.VOID)
usercmd = players.UserCmd()
usercmd.buttons = 2
usercmd_ptr = memory.get_object_pointer(usercmd)

@listeners.OnTick
def tick():
set_host(move_helper, bot_ptr)
run_command(bot_ptr, usercmd_ptr, move_helper)


My fake client spawns correctly, but doesn't jump like I expected (no errors or anything, I presume everything goes right up until the actual run_command). Am I missing a step? (423 should be the offset for CBasePlayer::PlayerRunCommand, 14 for CMoveHelperServer::SetHost)

(Perhaps OnTick occurs too late in the game frame to do this? I dunno. I might try hooking PlayerRunCommand to see when it gets normally executed vs when I execute it)

Re: Getting IMoveHelper instance?

Posted: Mon Apr 23, 2018 2:30 am
by quartata
The plot thickens: I just noticed that the scout was actually facing a different direction than it should have... So I'm guessing it applied the view angle correctly, and just not the buttons... maybe I'm setting them wrong?

Re: Getting IMoveHelper instance?

Posted: Mon Apr 23, 2018 6:47 pm
by Ayuto
Ahh, we might have an XY problem here. If you want to create your own bots, then you might want to take a look at this:
https://github.com/Ayuto/ReplayBot

The problem why the bot isn't jumping is probably, because you constantly send the jump key/action, which doesn't make a player jump all the time. The player will only jump once and only if he is able to jump at that specific point.

Re: Getting IMoveHelper instance?

Posted: Mon Apr 23, 2018 8:34 pm
by quartata
Oh, right, because it'll be like it's held. I'll try it with alternating every tick instead

Re: Getting IMoveHelper instance?

Posted: Mon Apr 23, 2018 9:07 pm
by quartata
Oh, huh... I hadn't seen BotController before, is that new? I'd definitely rather use that, if only so it'll work on Windows too. I'll give it a try.

Re: Getting IMoveHelper instance?

Posted: Tue Apr 24, 2018 12:20 am
by quartata
Got it working. You were right, I did need to press the button every other tick, so it wouldn't be held. Thank you.