Skip to content

Commit

Permalink
Add TF2Econ_GetAttributeList native
Browse files Browse the repository at this point in the history
  • Loading branch information
nosoop committed Mar 23, 2023
1 parent 736e4e9 commit dda70cf
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 2 deletions.
13 changes: 13 additions & 0 deletions gamedata/tf2.econ_data.txt
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,12 @@
"linux" "252"
"windows" "252"
}
"CEconItemSchema::m_AttributeMap"
{
// accessed in loop at CEconItemSchema::GetAttributeDefinitionByName
"linux" "448"
"windows" "448"
}
"CEconItemSchema::m_EquipRegions"
{
// the smaller of the two offsets in CEconItemSchema::GetEquipRegionIndexByName()
Expand Down Expand Up @@ -339,6 +345,13 @@
"linux" "8"
"windows" "8"
}
"sizeof(CEconItemAttributeDefinition)"
{
// used for iterating over the attribute map
// this does not include the members of the map itself
"linux" "68"
"windows" "68"
}
}
}
}
23 changes: 23 additions & 0 deletions scripting/include/tf_econ_data.inc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ enum TFEconParticleSet {
*/
typedef ItemFilterCriteria = function bool(int itemdef, any data);

/**
* Callback for `TF2Econ_GetAttributeList`. Return `true` if the specified attribute definition
* index should be added to the returned `ArrayList`.
*
* This prototype is the same as `TF2Econ_GetItemList`. Take care to not mix up the callbacks.
*/
typedef AttributeFilterCriteria = function bool(int attrdef, any data);

/**
* Returns true if there is an item corresponding to the given item definition index.
* TF_ITEMDEF_DEFAULT returns false here.
Expand Down Expand Up @@ -135,6 +143,8 @@ native bool TF2Econ_GetItemDefinitionString(int itemdef, const char[] key,
* callback is passed in, the ArrayList only contains defindexes that the callback returned
* `true` on.
*
* The resulting ArrayList does not have a defined order.
*
* This handle is owned by the calling plugin, so it should be `delete`d when not needed
* anymore.
*/
Expand Down Expand Up @@ -212,6 +222,19 @@ native bool TF2Econ_GetAttributeDefinitionString(int attrdef, const char[] key,
*/
native int TF2Econ_TranslateAttributeNameToDefinitionIndex(const char[] name);

/**
* Returns an ArrayList containing all valid attribute definition indices. If an
* AttributeFilterCriteria callback is passed in, the ArrayList only contains attribute
* definition indices that the callback returned `true` on.
*
* The resulting ArrayList does not have a defined order.
*
* This handle is owned by the calling plugin, so it should be `delete`d when not needed
* anymore.
*/
native ArrayList TF2Econ_GetAttributeList(AttributeFilterCriteria func = INVALID_FUNCTION,
any data = 0);

/**
* Stores the quality name in the given buffer and returns true if given a valid quality value,
* otherwise returns false;
Expand Down
70 changes: 68 additions & 2 deletions scripting/tf_econ_data.sp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <stocksoup/handles>
#include <stocksoup/memory>

#define PLUGIN_VERSION "0.18.4"
#define PLUGIN_VERSION "0.19.0"
public Plugin myinfo = {
name = "[TF2] Econ Data",
author = "nosoop",
Expand All @@ -24,7 +24,11 @@ public Plugin myinfo = {

Address offs_CEconItemSchema_ItemQualities,
offs_CEconItemSchema_ItemList,
offs_CEconItemSchema_nItemCount;
offs_CEconItemSchema_nItemCount,
offs_CEconItemSchema_AttributeMap;

#define ATTRDEF_MAP_OFFSET (view_as<Address>(0x14))
Address sizeof_CEconItemAttributeDefinition;

#include "tf_econ_data/attached_particle_systems.sp"
#include "tf_econ_data/loadout_slot.sp"
Expand Down Expand Up @@ -90,6 +94,9 @@ public APLRes AskPluginLoad2(Handle self, bool late, char[] error, int maxlen) {
CreateNative("TF2Econ_TranslateAttributeNameToDefinitionIndex",
Native_TranslateAttributeNameToDefinitionIndex);

// global attributes
CreateNative("TF2Econ_GetAttributeList", Native_GetAttributeList);

// quality information
CreateNative("TF2Econ_GetQualityName", Native_GetQualityName);
CreateNative("TF2Econ_TranslateQualityNameToValue", Native_TranslateQualityNameToValue);
Expand Down Expand Up @@ -243,6 +250,8 @@ public void OnPluginStart() {
GameConfGetAddressOffset(hGameConf, "CEconItemSchema::m_ItemList");
offs_CEconItemSchema_nItemCount =
GameConfGetAddressOffset(hGameConf, "CEconItemSchema::m_nItemCount");
offs_CEconItemSchema_AttributeMap =
GameConfGetAddressOffset(hGameConf, "CEconItemSchema::m_AttributeMap");
offs_CEconItemSchema_EquipRegions =
GameConfGetAddressOffset(hGameConf, "CEconItemSchema::m_EquipRegions");
offs_CEconItemSchema_ParticleSystemTree =
Expand Down Expand Up @@ -296,6 +305,8 @@ public void OnPluginStart() {
"CProtoBufScriptObjectDefinitionManager::m_PaintList");

sizeof_static_attrib_t = GameConfGetAddressOffset(hGameConf, "sizeof(static_attrib_t)");
sizeof_CEconItemAttributeDefinition = GameConfGetAddressOffset(hGameConf,
"sizeof(CEconItemAttributeDefinition)");

delete hGameConf;

Expand Down Expand Up @@ -363,6 +374,61 @@ int Native_GetItemList(Handle hPlugin, int nParams) {
return MoveHandle(itemList, hPlugin);
}

int Native_GetAttributeList(Handle hPlugin, int nParams) {
Function func = GetNativeFunction(1);
any data = GetNativeCell(2);

Address pSchema = GetEconItemSchema();
if (!pSchema) {
return 0;
}

ArrayList attributeList = new ArrayList();

// this implements FOR_EACH_MAP_FAST
int nAttributeCapacity = LoadFromAddress(
pSchema + offs_CEconItemSchema_AttributeMap + view_as<Address>(0x4),
NumberType_Int32);

Address pAttributeData = DereferencePointer(pSchema + offs_CEconItemSchema_AttributeMap);
for (int i; i < nAttributeCapacity; i++) {
Address pAttributeDataItem = pAttributeData
+ view_as<Address>(i) * (sizeof_CEconItemAttributeDefinition + ATTRDEF_MAP_OFFSET);

// the struct has 0x14 bytes (ATTRDEF_MAP_OFFSET) preceding the definition
// some internal map data
int index = LoadFromAddress(pAttributeDataItem, NumberType_Int32);
if (index == i) {
continue;
}

Address pAttributeDefinition = pAttributeDataItem + ATTRDEF_MAP_OFFSET;
int attrdef = LoadFromAddress(
pAttributeDefinition + offs_CEconItemAttributeDefinition_iAttributeDefinitionIndex,
NumberType_Int16);
if (!attrdef) {
continue;
}

if (func == INVALID_FUNCTION) {
attributeList.Push(attrdef);
continue;
}

bool result;
Call_StartFunction(hPlugin, func);
Call_PushCell(attrdef);
Call_PushCell(data);
Call_Finish(result);

if (result) {
attributeList.Push(attrdef);
}
}

return MoveHandle(attributeList, hPlugin);
}

int Native_GetItemSchemaAddress(Handle hPlugin, int nParams) {
return view_as<int>(GetEconItemSchema());
}
Expand Down

0 comments on commit dda70cf

Please sign in to comment.