# find-CBasePlayerController_SetPawn

> Find and identify the CBasePlayerController_SetPawn function in CS2 binary using IDA Pro MCP. Use this skill when reverse engineering CS2 server.dll or server.so to locate the SetPawn function by analyzing the cleanup sequence in CBasePlayerController virtual function index around 14 (12 ~ 16) and identifying the characteristic call pattern.

- Skill: `tools-only/find-cbaseplayercontroller-setpawn-4` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/find-cbaseplayercontroller-setpawn-4`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/find-cbaseplayercontroller-setpawn-4/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/find-cbaseplayercontroller-setpawn-4

---


# Find CBasePlayerController_SetPawn

Locate `CBasePlayerController_SetPawn` in CS2 server.dll or server.so using IDA Pro MCP tools.

## Method

### 1. Get CBasePlayerController vtable address

**ALWAYS** Use SKILL `/get-vtable-address` to find vtable for `CBasePlayerController`.

### 2. Decompile virtual function index around 14 (12 ~ 16)

`vfunc_addr = vtable_start + (vtable_index * 8)`

```
mcp__ida-pro-mcp__decompile addr="<vfunc_addr>"
```

### 3. Identify CBasePlayerController_SetPawn call pattern

Look for the following pattern in the decompiled code:

```c
// Pattern to identify:
for ( i = *(_QWORD **)(a1 + 1928); i; i = (_QWORD *)i[7] )
{
  while ( 1 )
  {
    v15 = *(__int64 (__fastcall **)())(*i + 48LL);
    if ( v15 != nullsub_1097 )
      break;
    i = (_QWORD *)i[7];
    if ( !i )
      goto LABEL_22;
  }
  ((void (__fastcall *)(_QWORD *))v15)(i);
}
LABEL_22:
sub_XXXXXXX(a1, 0, 0, 0, 0, 0);  // <- This is CBasePlayerController_SetPawn
v16 = *(void (__fastcall ****)(_QWORD))(a1 + 2472);
if ( v16 )
{
  (**v16)(v16);
  *(_QWORD *)(a1 + 2472) = 0;
}
```

The target function is called:
- Immediately after iterating a linked list at offset 1928
- Each list node invokes virtual function at vtable offset +48, skipping nullsubs
- Called with parent object (a1) as first argument and all remaining arguments set to zero
- Immediately followed by releasing a function pointer at offset 2472

### 4. Rename the function

```
mcp__ida-pro-mcp__rename batch={"func": [{"addr": "<function_addr>", "name": "CBasePlayerController_SetPawn"}]}
```

### 5. Generate and validate unique signature

**ALWAYS** Use SKILL `/generate-signature-for-function` to generate a robust and unique signature for the function.

### 6. Write IDA analysis output as YAML beside the binary

**ALWAYS** Use SKILL `/write-func-as-yaml` to write the analysis results.

Required parameters:
- `func_name`: `CBasePlayerController_SetPawn`
- `func_addr`: The function address from step 3
- `func_sig`: The validated signature from step 5

## Function Characteristics

- **Purpose**: Associates or disassociates a pawn with the player controller
- **Parameters**: `(controller, pawn_ptr, param2, param3, param4, param5)`
  - When called with all zeros: clears/nullifies the pawn assignment
- **Called from**: Virtual function index 14 (CBasePlayerController cleanup/destructor)
- **Function size**: ~0x53c bytes (1340 bytes) - may vary between versions

## Signature Pattern

The function has a distinctive prologue:

```
push    rbp
lea     rax, [rdi+7C0h]     ; Pawn offset in controller (0x7C0 = 1984 decimal)
mov     rbp, rsp
push    r15
mov     r15d, ecx
push    r14
push    r13
mov     r13d, r9d
push    r12
mov     r12, rsi
push    rbx
mov     rbx, rdi
sub     rsp, 68h
mov     ecx, [rdi+7C0h]     ; Same offset appears twice
```

Key identifying features:
- Offset 0x7C0 (1984) appears twice - this is the pawn field offset in CBasePlayerController (note that 0x7C0 can change on game updates)
- Standard function prologue with register preservation
- Stack allocation of 0x68 bytes (can change on game updates too)

## Output YAML Format

The output YAML filename depends on the platform:
- `server.dll` → `CBasePlayerController_SetPawn.windows.yaml`
- `server.so` → `CBasePlayerController_SetPawn.linux.yaml`

