Making bots aim for the head

Please post any questions about developing your plugin here. Please use the search function before posting!
Mikeemoo
Junior Member
Posts: 5
Joined: Sat Dec 05, 2015 5:56 pm

Making bots aim for the head

Postby Mikeemoo » Mon Dec 07, 2015 7:10 pm

Bots in CS:GO are pretty poor.

This is a first attempt to try to make them aim at the head instead of the body. It improves them a little bit, but there's still quite a bit more work to do.

I'm not a python coder, and I know very little about source engine - so apologies if this is rubbish!

I'd like to improve bots a lot more, so if anyone has any knowledge of bots I'd love to hear about it. I've been sat looking at IDA for days without getting very far.

Code: Select all

import memory

from memory import find_binary, DataType, Convention
from memory.hooks import PostHook
from players.entity import Player
from entities.helpers import pointer_from_index

server = memory.find_binary('server', False)

PICK_AIM_SPOT = server['_ZN6CCSBot14PickNewAimSpotEv'].make_function(
    Convention.THISCALL,
    (DataType.POINTER,),
    DataType.INT
)

@PostHook(PICK_AIM_SPOT)
def post_pick_aim_spot(args, return_value):
   
   playerPointer = args[0]
   index = playerPointer.get_ushort(20944)
   
   if (index != -1 and index < 32):
      
      entPointer = pointer_from_index(index)
      enemy = memory.make_object(Player, entPointer)
      eyeLocation = enemy.eye_location
      
      botProfile = playerPointer.get_pointer(12108)
      skillLevel = botProfile.get_float(8)
      
      playerPointer.set_float(eyeLocation[0], 20852)
      playerPointer.set_float(eyeLocation[1] - (1 - skillLevel), 20856)
      playerPointer.set_float(eyeLocation[2], 20860)
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Mon Dec 07, 2015 8:10 pm

Wait, does this even work? Here you are getting something from a bot that isn't in its class anymore.

Syntax: Select all

index = playerPointer.get_ushort(20944)
The size of the bots class is currently 12072 in CS:GO.

Syntax: Select all

import memory
from players.entity import Player

# Prints 12072 in CS:GO on Windows (Linux might differ a bit, but shouldn't differ very much)
print(memory.get_size(Player(1)))


Edit: I moved this thread since it sounds more like a question to me.
Mikeemoo
Junior Member
Posts: 5
Joined: Sat Dec 05, 2015 5:56 pm

Postby Mikeemoo » Mon Dec 07, 2015 8:13 pm

Seems to work for me. Without the plugin they aim for the gut, when you enable it they switch their aim to the head.
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Mon Dec 07, 2015 8:14 pm

But what are you retrieving there? Where did you get those values? Have you tried exploring the return type/value?
Mikeemoo
Junior Member
Posts: 5
Joined: Sat Dec 05, 2015 5:56 pm

Postby Mikeemoo » Mon Dec 07, 2015 8:24 pm

I got the values from digging around in IDA.

(ushort) player + 20944 seems to be the player index of the bots current enemy target. I'm then looking up the player for that index, finding their eye position, and setting it as the bots new target aim point.

Edit: I'm setting the Y position based on their skill level which is stored within the botProfile object. Low skilled bots are likely to aim at eyeHeight-1 which seems to be around body area. High skilled bots (skill level: 1.0) are likely to aim at eyeHeight-(1-1) which is the enemy head.
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Mon Dec 07, 2015 8:37 pm

Well, that still doesn't explain why you use an offset that is bigger than the actual class. You must be retrieving something from another object whose memory block must be always behind the bot memory block. I'm not sure if that is true and unfortunately I don't have the time currently to check anything. I'm just typing here my random thoughts.
Ayuto wrote:Have you tried exploring the return type/value?
If the return value is really an integer it might return values between 0 - 10 or something like that. They might define spots like head, arm, gut, etc. So, if this is true it might be easier to just modify the return value.
Mikeemoo
Junior Member
Posts: 5
Joined: Sat Dec 05, 2015 5:56 pm

Postby Mikeemoo » Mon Dec 07, 2015 8:51 pm

Unfortunately CSBot::PickNewAimSpot is... strange.

- it does a lot of checking to see if the enemies various body parts are visible
- but then just ignores it all and aims for body part '1' (GUT).
- then sets the 3 values which seem to be 'next place to aim' (this+20852, this+20856, this+20860)
- the return value seems to be ignored by anything that calls it

So I'm post hooking the method and just setting 'next place to aim' as my own values.

It does work, but the bots are still.. dumb. There seems to be somewhere that's setting random variation to the aiming, but I'm struggling to find it.
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Tue Dec 08, 2015 11:09 am

Which values does it return?
Mikeemoo
Junior Member
Posts: 5
Joined: Sat Dec 05, 2015 5:56 pm

Postby Mikeemoo » Tue Dec 08, 2015 11:33 am

Ayuto wrote:Which values does it return?


It just returns gpGlobals;

Code: Select all

  result = gpGlobals;
  *(float *)(this + 20920) = v26 * v25;
  *(float *)(this + 20924) = (float)(v26 * v25) + *(float *)(result + 16);
  return result;
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Postby Ayuto » Tue Dec 08, 2015 12:18 pm

Ah, okay. The original function probably doesn't return anything (it's a void). The only reason why gpGlobals is returned is that it's stored in the eax register (that's the common return value register) to access an attribute.

I also need to correct my answer I made about the size of the player. The CCSBot class is 21992 bytes big on Windows and 22004 on Linux. So, your code is correct. The reason why my code above prints other values is that it looks up the size of the CCSPlayer class, because the classname of a bot is changed from cs_bot to player on creation.

I can take a closer look at it during the christmas days.
winmillion20
Junior Member
Posts: 1
Joined: Tue Feb 16, 2016 10:40 pm

Postby winmillion20 » Tue Feb 16, 2016 10:41 pm

Sorry if I sound like a noob, but what do I do with this code? How do I install it :confused:
lemeshovich
Junior Member
Posts: 8
Joined: Mon Mar 19, 2018 9:32 pm

Re: Making bots aim for the head

Postby lemeshovich » Mon Mar 19, 2018 10:34 pm

hi, guys
im getting those errors when trying to load that plugin on CS:GO server

Code: Select all

00:31:58 sp plugin load botHeadShot
00:31:58 [SP] Loading plugin 'botHeadShot'...
         
         [SP] Caught an Exception:
         Traceback (most recent call last):
           File "..\addons\source-python\packages\source-python\plugins\command.py", line 162, in load_plugin
             plugin = self.manager.load(plugin_name)
           File "..\addons\source-python\packages\source-python\plugins\manager.py", line 193, in load
             plugin._load()
           File "..\addons\source-python\packages\source-python\plugins\instance.py", line 74, in _load
             self.module = import_module(self.import_name)
           File "..\addons\source-python\plugins\botHeadShot\botHeadShot.py", line 10, in <module>
             PICK_AIM_SPOT = server['_ZN6CCSBot14PickNewAimSpotEv'].make_function(
         
         ValueError: Could not find symbol: _ZN6CCSBot14PickNewAimSpotEv
         
         
         [SP] Plugin 'botHeadShot' was unable to be loaded.

can you help me please?
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: Making bots aim for the head

Postby Ayuto » Tue Mar 20, 2018 7:16 am

This code doesn't work anymore for CSGO, because Valve removed the symbols from the Linux binaries and on Windows they never contained symbols.

If you tell me for which OS you need it. I can update the code for you.
lemeshovich
Junior Member
Posts: 8
Joined: Mon Mar 19, 2018 9:32 pm

Re: Making bots aim for the head

Postby lemeshovich » Tue Mar 20, 2018 4:45 pm

thanks for your reply
i need that for Linux
User avatar
Ayuto
Project Leader
Posts: 2193
Joined: Sat Jul 07, 2012 8:17 am
Location: Germany

Re: Making bots aim for the head

Postby Ayuto » Tue Mar 20, 2018 6:30 pm

Try this (untested):

Syntax: Select all

import memory

from memory import find_binary, DataType, Convention
from memory.hooks import PostHook
from players.entity import Player
from entities.helpers import pointer_from_index

server = memory.find_binary('server', False)

PICK_AIM_SPOT = server[b'\x55\x89\xE5\x57\x56\x53\x81\xEC\x9C\x00\x00\x00\x8B\x5D\x08\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x83\x70\x5A\x00\x00'].make_function(
Convention.THISCALL,
(DataType.POINTER,),
DataType.VOID
)

@PostHook(PICK_AIM_SPOT)
def post_pick_aim_spot(args, return_value):

playerPointer = args[0]
index = playerPointer.get_ushort(23152)

if (index != -1 and index < 32):

entPointer = pointer_from_index(index)
enemy = memory.make_object(Player, entPointer)
eyeLocation = enemy.eye_location

botProfile = playerPointer.get_pointer(14484)
skillLevel = botProfile.get_float(8)

playerPointer.set_float(eyeLocation[0], 23072)
playerPointer.set_float(eyeLocation[1] - (1 - skillLevel), 23076)
playerPointer.set_float(eyeLocation[2], 23080)
lemeshovich
Junior Member
Posts: 8
Joined: Mon Mar 19, 2018 9:32 pm

Re: Making bots aim for the head

Postby lemeshovich » Tue Mar 20, 2018 10:34 pm

Thanks plugin loads now
but now something wrong happens with bots crosshair
looks like plugin moves it left or right randomly instead of moving upper for hitting head
please watch video
lemeshovich
Junior Member
Posts: 8
Joined: Mon Mar 19, 2018 9:32 pm

Re: Making bots aim for the head

Postby lemeshovich » Wed Mar 21, 2018 8:10 pm

please help me with that
I'll be very grateful
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: Making bots aim for the head

Postby Kami » Wed Mar 21, 2018 8:20 pm

Hey, I'm not sure if you really need to change the whole process of the bots aiming. You could also just set the bots aim to the head directly right before they shoot. This is a test I made to see if setting the aim pre weapon_fire works:

Syntax: Select all

from players.entity import Player
from events.hooks import PreEvent

@PreEvent('weapon_fire')
def pre_player_died(game_event):
print('test')
player = Player.from_userid(game_event['userid'])
if player.view_player:
player.view_coordinates = player.view_player.eye_location


You could store the bots current aim target (player) and then when the bot shoots set the aim to whatever part of the body you want with above code and some x/y/z adjustments.
lemeshovich
Junior Member
Posts: 8
Joined: Mon Mar 19, 2018 9:32 pm

Re: Making bots aim for the head

Postby lemeshovich » Wed Mar 21, 2018 8:54 pm

thank you for you answer
im sourcemod developer and im new in python
can you please explain more detail how can i change aim coordinates before bot shoots
if i understand correctly player.view_coordinates is the coordinats bot shoot by default and i should raise bots cursor a bit higher and they will shoot in head
am i right?
User avatar
Kami
Global Moderator
Posts: 263
Joined: Wed Aug 15, 2012 1:24 am
Location: Germany

Re: Making bots aim for the head

Postby Kami » Thu Mar 22, 2018 3:58 pm

This is how I would approach this:

Syntax: Select all

from players.entity import Player
from events.hooks import PreEvent
from random import randint
from mathlib import Vector

bot_difficulty = 1
chance = 25

@PreEvent('weapon_fire')
def pre_player_died(game_event):
player = Player.from_userid(game_event['userid'])
if player.is_bot:
#player.view_player checks if a player entity is in your crosshair. This would be replaced by your stored bot aim target
if player.view_player:
#checking if the chance triggers
chance_check = randint(0,100)
if chance_check <= chance:
#choosing random coordinate modification depending on difficulty
if bot_difficulty == 0:
x_mod = randint(0,15)
y_mod = randint(0,15)
z_mod = randint(0,15)
elif bot_difficulty == 1:
x_mod = randint(0,10)
y_mod = randint(0,10)
z_mod = randint(0,10)
elif bot_difficulty == 2:
x_mod = randint(0,5)
y_mod = randint(0,5)
z_mod = randint(0,5)
#saving the eye (head) location of the player in the crosshair to a vector we safely can do math on
aim_location = Vector(*player.view_player.eye_location)
#adding the previously choosen coordinate modifications to our copy vector
aim_location[0] += float(x_mod)
aim_location[1] += float(y_mod)
aim_location[2] += float(z_mod)
#setting the bots to the previously altered aim_location vector
player.view_coordinates = aim_location


I did not test this code, but I think you get the idea. It basically works on two bases:

1. A chance to trigger the better aim (in this case 25%)

2. A maximum range for the random position modificatior based on the bots difficulty

Return to “Plugin Development Support”

Who is online

Users browsing this forum: No registered users and 23 guests