Skip to content
cccskills
FreePublished on GitHub

find-CAttributeList_SetOrAddAttributeValueByName

Find and identify the CAttributeList_SetOrAddAttributeValueByName function in CS2 server binary using IDA Pro MCP. Use this skill when reverse engineering CS2 server.dll or libserver.so to locate the econ attribute-list workhorse that sets an existing float attribute by name or appends a new one. Resolved via a durable caller anchor: the weapon paint-kit/wear/seed/kill-eater applier function, which is itself located by the literal econ keyvalue-system strings "set item texture prefab" / "set item texture wear" / "set item texture seed". This function backs weaponpaints-style plugins that programmatically set an econ item's paint kit / wear / seed / stickers. Trigger: CAttributeList_SetOrAddAttributeValueByName, SetOrAddAttributeValueByName

The English summary is being prepared. Showing the original description.

See how to install

Files included (1)

  • SKILL.md8.4 KB

SKILL.md (original)

Review the instructions the agent will receive before you install.

Find CAttributeList_SetOrAddAttributeValueByName

Locate CAttributeList_SetOrAddAttributeValueByName in CS2 server.dll or libserver.so using IDA Pro MCP tools.

This is a non-virtual, direct-call member function reached through a tiny this-adjustor thunk (no vtable entry of its own — emit a byte sig, not an offset).

Do not anchor the discovery recipe on the raw byte pattern below — bytes/wildcards shift release to release. Use it only to locate/confirm the function on the currently loaded binary, then generate a fresh signature at the end.

Method

1. Locate the durable anchor strings

CAttributeList_SetOrAddAttributeValueByName has no distinctive string of its own (it's a generic hash-lookup + set/append routine), but its caller is the weapon econ-attribute applier used by CS2's own give/equip-weapon code path, and that caller references several literal econ keyvalue strings:

mcp__ida-pro-mcp__find       type="string" targets=["set item texture prefab"]
mcp__ida-pro-mcp__xrefs_to   addrs="<string_va>"

"set item texture prefab" has exactly one code referencer. That containing function (call it the paint-kit applier) also references the sibling literals "set item texture wear", "set item texture seed", "kill eater score type", and "kill eater" — this combination is a very strong, semantically durable fingerprint for "the function that programmatically stamps paint-kit/wear/seed/kill-eater attributes onto a weapon econ item", independent of its address or body shape.

Linux 14168 reference: the string "set item texture prefab" is referenced only from sub_1A9A070 (VA 0x1a9a070, size 0x394).

2. Read off the call sites inside the paint-kit applier

mcp__ida-pro-mcp__decompile addr="<paint_kit_applier_func_va>"

Inside, look for (typically) five calls of the shape helper(pAttributeListView, "<attr-name-literal>", <float-or-int-value>):

helper(v12, "set item texture prefab", (float)*(int *)(a2 + 120));
helper(v12, "set item texture wear",   *(float *)(a2 + 132));
helper(v12, "set item texture seed",   (float)*(int *)(a2 + 136));
helper(v12, "kill eater score type",   *(float *)(a2 + 140));  // only when a flag bit is set
helper(v12, "kill eater",              *(float *)(a2 + 144));  // only when a flag bit is set

helper is not the target itself — on Linux it is a tiny 2-instruction this-adjustor thunk:

add rdi, 0x70      ; adjust `this` from CEconItemView-ish base to the embedded CAttributeList member
jmp  <real_target>

Follow the jmp — its destination is CAttributeList_SetOrAddAttributeValueByName.

Linux 14168 reference: helper is sub_1B598E0 (add rdi, 70h; jmp sub_1B59720), and the real target is sub_1B59720 (VA 0x1b59720, size 0x1b5).

3. Confirm the target function's shape

Decompile the jmp target and confirm it matches:

__int64 __fastcall SetOrAddAttributeValueByName(CAttributeList *this, const char *pszAttribName, float flValue)
{
  pAttribDef = LookupAttributeDefinitionBySymbol(pszAttribName); // via a global symbol table
  if (!pAttribDef) return 0;
  for (each existing CEconItemAttribute entry in this->m_Attributes)
    if (entry's attribute-definition-index matches pAttribDef's index)
    {
      if (entry.value != flValue) { OnAttributeChanged(...); entry.value = flValue; }
      return ...;
    }
  // not found: construct a new attribute pair and append it to this->m_Attributes
  ConstructAttribute(&tmp, pAttribDef->index, flValue);
  AppendAttribute(this, &tmp);
  return ...;
}

Identification rules:

  1. Takes (this, const char *pszAttribName, float flValue) — a name string plus a float value.
  2. First does a hash/symbol lookup of pszAttribName into a global attribute-definition table.
  3. Loops over the object's existing attribute array comparing each entry's definition pointer/index; on a match, conditionally fires a change callback and overwrites the value in place.
  4. If no existing entry matches, constructs a new (index, value) pair and appends it to the list, growing/reallocating via the engine's memory allocator (g_pMemAlloc) if needed.

4. Generate function signature

ALWAYS use SKILL /generate-signature-for-function with addr=<real_target_func_addr>. Emit IDA style verbatim (space hex, ? wildcards).

Reference sig (Linux 14168 build — sanity check only, regenerate per binary): 55 48 89 E5 41 57 41 56 49 89 FE 41 55 41 54 53 48 89 F3 48 83 EC ? F3 0F 11 85

(Last-resort fallback note: if no better anchor is available on some future binary, find_bytes with this reference pattern can locate the function directly one-shot — its prologue is distinctive enough on its own — but prefer the string/caller anchor above since it survives compiler/prologue changes better.)

5. Write func YAML

ALWAYS use SKILL /write-func-as-yaml:

  • func_name: CAttributeList_SetOrAddAttributeValueByName
  • func_addr: <real_target_func_addr>
  • func_sig: validated sig from step 4

Function Characteristics

  • Purpose: Part of CS2's econ "attribute list" system (CAttributeList / CEconItemAttributeDefinition- adjacent). Sets an existing attribute's value by its string name, or appends a new attribute entry if none exists yet. This is the workhorse used by any code that programmatically sets paint-kit/wear/seed/ kill-eater/etc attributes on an econ item's attribute list — including weaponpaints-style plugins.
  • Linkage: non-virtual, direct-call (no vtable entry); reached in practice through a this-adjustor thunk from CEconItemView-shaped callers.
  • Binary: server.dll / libserver.so
  • Parameters: (this /* CAttributeList* */, const char *pszAttribName, float flValue)
  • Return value: implementation-defined status/attribute pointer (callers largely ignore it besides truthiness checks)

Discovery Strategy

  1. The target itself has no unique string, so anchor on its caller's literal econ-keyvalue strings — "set item texture prefab" has exactly one code referencer in the whole module, and that referencer is semantically stable (it is CS2's own paint-kit/wear/seed/kill-eater weapon-attribute applier, a first-party gameplay routine unlikely to disappear across updates).
  2. From that caller, every call into the attribute-setter helper passes a literal attribute-name string as its second argument — a very strong, code-shape-independent fingerprint (helper(this, "<literal>", value), repeated for each of the five known econ attribute names).
  3. On Linux the immediate call target is a two-instruction this-adjustor thunk (add rdi, N; jmp real); simply follow the unconditional jump to reach the real function.
  4. Confirm via body shape (symbol/hash lookup of the name argument, existing-attribute scan-and-update, append-if-missing fallback) — this is independent of exact byte offsets and survives reordering/inlining changes across builds.
  5. Re-generate the byte signature fresh from the resolved function each time, rather than hard-coding one.

This is robust because the anchor strings are first-party gameplay literals (not debug-only strings that could be stripped in release builds), the caller's "distinctive literal string as 2nd argument" call shape is compiler-agnostic, and the final signature is always regenerated rather than pinned.

Output YAML Format

  • server.dll -> CAttributeList_SetOrAddAttributeValueByName.windows.yaml
  • libserver.so -> CAttributeList_SetOrAddAttributeValueByName.linux.yaml

Fields: func_name, func_va, func_rva, func_size, func_sig.

Reviews

No reviews yet. Tell others what you thought.

Comments

No login needed. Share how it worked for you, ask a question, or note where it did not run.

No comments yet. Be the first to write one.

Comments are published right away. Do not include personal information such as email addresses or phone numbers. Up to 2 URLs.

0 / 1,000 characters

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.

More skills from this repository

Clean up the local workspace after a dev branch has been merged into main. Verifies the current dev branch is fully merged into origin/main, then switches to main, pulls the latest, deletes the local dev branch, and deletes the remote dev branch if it still exists. STOPS and warns the user if the current branch is not yet merged. Triggers: cleanup workspace, cleanup branch, delete merged branch, finish dev branch, post-merge cleanup

The English summary is being prepared. Showing the original description.

mrc4tt/CS2_VibeSignatures3Updated Oct 15, 2026

Convert an existing find-XXXX SKILL.md into a preprocessor Python script, updating configs/<GAMEVER>.yaml and removing the old SKILL.md. Covers xref-string-based and LLM_DECOMPILE-based discovery patterns.

The English summary is being prepared. Showing the original description.

mrc4tt/CS2_VibeSignatures3Updated Oct 15, 2026

Create an Agent SKILL.md fallback for an existing find-XXXX finder that relies on a fragile discovery foundation — above all LLM_DECOMPILE (patterns C/D/E), which matches the decompiled shape of a predecessor function against a stored reference and breaks when a symbol is inlined or de-inlined in a way the reference does not cover. The generated fallback coexists with the preprocessor and runs only when it returns failure, recovering every target robustly by decompiling the predecessor and following the inline/de-inline boundary with semantic anchors. Use when a finder broke on a game update, or you want to durably backstop one before it does. The recipe generalizes to any finder foundation. Triggers: create agent skill fallback, add SKILL.md fallback, robust fallback for finder, backstop LLM_DECOMPILE finder, final guarantee skill

The English summary is being prepared. Showing the original description.

mrc4tt/CS2_VibeSignatures3Updated Oct 15, 2026

Create a new cpp_tests entry for validating a C++ interface vtable layout against binary reference YAMLs. Creates the .cpp test file in cpp_tests/ and appends a configs/<GAMEVER>.yaml entry under cpp_tests:. Use when a user asks to add vtable layout validation for a new hl2sdk_cs2 interface class.

The English summary is being prepared. Showing the original description.

mrc4tt/CS2_VibeSignatures3Updated Oct 15, 2026

Create a GitHub pull request from staged task changes or an already-committed current branch. Deliver source/config/ reference changes together with their computed source-owned `bin_artifacts` closure. PR validation routing is owned by the default-branch trusted workflow; snapshots, gamedata, and manifests are Release-derived only.

The English summary is being prepared. Showing the original description.

mrc4tt/CS2_VibeSignatures3Updated Oct 15, 2026

Create a new find-XXXX preprocessor Python script from scratch (no existing SKILL.md), add configs/<GAMEVER>.yaml skill and symbol entries. Covers xref-string-based and LLM_DECOMPILE-based discovery patterns. Use when a GitHub issue or user instruction specifies a new function to find.

The English summary is being prepared. Showing the original description.

mrc4tt/CS2_VibeSignatures3Updated Oct 15, 2026

See all skills by mrc4tt

Report a problem with this skill