summaryrefslogtreecommitdiff
path: root/src/cs2/entity.h
blob: 999f7769e0a3ee96abf5332ffa2f9c04649ea58e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma once
#include "cs2.h"
#include "schema.h"

static U64 cs2_ent_get_list( CS2* p );
inline U64 cs2_ent_from_idx( CS2* p, U32 idx );
inline U64 cs2_ent_from_handle( CS2* p, U32 handle );
class CS2_PLAYERCONTROLLER;

class CS2_PAWN {
public:
  CS2_PAWN( U64 _ptr ) : ptr( _ptr ) {}
  CS2_PAWN() : ptr( 0 ) {}
  operator U64() { return ptr; }

  NETVAR_MOD( I32, m_iHealth, "C_BaseEntity", "client.dll" );
  
  U64 ptr;
  static CS2* cs;
};

class CS2_PLAYERCONTROLLER {
public:
  CS2_PLAYERCONTROLLER( U64 _ptr ) : ptr( _ptr ) {}
  CS2_PLAYERCONTROLLER() : ptr( 0 ) {}
  operator U64() { return ptr; }

  NETVAR_MOD( U32, m_hPawn, "CBasePlayerController", "client.dll" );
  
  STR<128> m_sSanitizedPlayerName() {
    static I32 off = schema_get_offset( cs, "CCSPlayerController", "m_sSanitizedPlayerName", "client.dll" );

    STR<128> ret;
    U64 str = cs->read<U64>( ptr + off );
    cs->read( str, ret, sizeof( ret ) );

    return ret;
  }

  CS2_PAWN get_pawn() {
    return cs2_ent_from_handle( cs, m_hPawn() );
  }
  
  U64 ptr;
  static CS2* cs;
};

// ------------------------------------------------------------------------------------------------

static U64 cs2_ent_get_list( CS2* p ) {
  static U64 entitylist = 0;

  if( !entitylist ) {
    if( !CS2_PLAYERCONTROLLER::cs )
      CS2_PLAYERCONTROLLER::cs = CS2_PAWN::cs = p;
    U64 client = p->mod.client.base;

    // GetEntityByIndex
    // xref str:  '%s' : '%s' (entindex %d) \n,
    // ent_find_index cvar
    U64 call = p->code_match( p->mod.client.base, "E8 ? ? ? ? 48 8B D0 48 8B CE FF D7" );
    assert( !!call );

    U32 off = p->read<U32>( call + 1 ) + 5;
    U64 fn = call + off;

    U8 bytes[32];
    p->read( fn, bytes, sizeof( bytes ) );

    if( bytes[0] != 0x8b || bytes[1] != 0xd1 ||                  // mov edx, ecx
        bytes[2] != 0x48 || bytes[3] != 0x8b || bytes[4] != 0x0d // mov rcx, entlist
    ) {
      assert( false );
      return 0;
    }

    off = *(U32*)&bytes[5];
    entitylist = p->read<U64>( fn + off + 9 );
  }

  return entitylist;
}

// ? ? ? ? ?
// i really wanna know what the actual c++ looks like.
inline U64 cs2_ent_from_idx( CS2* p, U32 idx ) {
  U64 entlist = cs2_ent_get_list( p );
  if( !entlist )
    return 0;

  if( idx >= 0x7fff )
    return 0;

  if( (idx >> 9) > 0x3f )
    return 0;

  U64 v2 = entlist + 8 * (idx >> 9) + 0x10;
  v2 = p->read<U64>( v2 );
  if( !v2 )
    return 0;

  U64 v3 = 0x78 * (idx & 0x1ff) + v2;
  if( !v3 )
    return 0;

  return p->read<U64>( v3 );
}

inline U64 cs2_ent_from_handle( CS2* p, U32 handle ) {
  if( handle == 0xffffffff )
    return 0;

  return cs2_ent_from_idx( p, handle & 0x7fff );
}