I'm very thankful for having Voided explain to me how to use the OnGiveNamedItem forward in multiple plugins to have full customization over weapons, miscs, and hates. I've developed these stocks to help simplify creating custom weapons and items in my mods so they can work between each other (ex: One plugin adds an unusual effect while the other enhances the item's attributes by 10)
Some of these stocks use tf2itemsinfo. You can download a working one below.
PHP Code:
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod (C)2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This file is part of the SourceMod/SourcePawn SDK.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#if defined _tf2items_extended_stocks
#endinput
#endif
#define _tf2items_extended_stocks
#include <tf2itemsinfo>
/**
* Finds an attribute and its index within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param iAttribute Item attribute to find.
* @return Attribute index if found, -1 otherwise.
*/
stock TF2Items_FindAttributeIndex(Handle:hItem, iAttribute)
{
new iNumAttributes = TF2Items_GetNumAttributes(hItem);
for(new i = 0; i < iNumAttributes; i++)
{
if(TF2Items_GetAttributeId(hItem, i) == iAttribute)
return i;
}
return -1;
}
/**
* Replaces (or inserts) an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param iAttribute Item attribute replace/insert.
* @param flValue Value of the attribute.
* @param bForce Insert a new attribute if attribute can't be replaced?.
* @return True if replaced or inserted, false otherwise.
*/
stock TF2Items_ReplaceAttribute(Handle:hItem, iAttribute, Float:flValue, bool:bInsert = true)
{
new iNumAttributes = TF2Items_GetNumAttributes(hItem);
for(new i = 0; i < iNumAttributes; i++)
{
if(TF2Items_GetAttributeId(hItem, i) == iAttribute)
{
TF2Items_SetAttribute(hItem, i, iAttribute, flValue);
return true;
}
}
/**
* Replaces (or inserts) an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param strAttribute Name of the attribute to replace/insert.
* @param flValue Value of the attribute.
* @param bForce Insert a new attribute if attribute can't be replaced?.
* @return True if replaced or inserted, false otherwise.
*/
stock TF2Items_ReplaceAttributeByName(Handle:hItem, const String:strAttribute[], Float:flValue, bool:bInsert = true)
{
new iNumAttributes = TF2Items_GetNumAttributes(hItem);
decl String:strName[56];
for(new i = 0; i < iNumAttributes; i++)
{
new iAttribute = TF2Items_GetAttributeId(hItem, i);
TF2II_GetAttributeNameByID(iAttribute, strName, sizeof(strName));
if(StrEqual(strAttribute, strName))
{
TF2Items_SetAttribute(hItem, i, iAttribute, flValue);
return true;
}
}
/**
* Adds to an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param iAttribute Index of the attribute to add to.
* @param flValue How much to add to the attribute value.
* @return True if added, false otherwise.
*/
stock bool:TF2Items_AddAttribute(Handle:hItem, iAttribute, Float:flAmount)
{
for(new i = 0; i < TF2Items_GetNumAttributes(hItem); i++)
{
if(TF2Items_GetAttributeId(hItem, i) == iAttribute)
{
new Float:flCurrent = TF2Items_GetAttributeValue(hItem, i);
TF2Items_SetAttribute(hItem, i, iAttribute, flCurrent + flAmount);
return true;
}
}
return false;
}
/**
* Adds to an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param strAttribute Name of the attribute to add to.
* @param flValue How much to add to the attribute value.
* @return True if added, false otherwise.
*/
stock bool:TF2Items_AddAttributeByName(Handle:hItem, const String:strAttribute[], Float:flAmount)
{
decl String:strName[56];
for(new i = 0; i < TF2Items_GetNumAttributes(hItem); i++)
{
TF2II_GetAttribName(TF2Items_GetAttributeId(hItem, i), strName, sizeof(strName));
if(StrEqual(strAttribute, strName))
{
new Float:flCurrent = TF2Items_GetAttributeValue(hItem, i);
TF2Items_SetAttribute(hItem, i, iAttribute, flCurrent + flAmount);
return true;
}
}
return false;
}
/**
* Subtracts from an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param iAttribute Index of the attribute to subtract from.
* @param flValue How much to subtract from the attribute value.
* @return True if subtracted, false otherwise.
*/
stock bool:TF2Items_SubtractAttribute(Handle:hItem, iAttribute, Float:flAmount)
{
for(new i = 0; i < TF2Items_GetNumAttributes(hItem); i++)
{
if(TF2Items_GetAttributeId(hItem, i) == iAttribute)
{
new Float:flCurrent = TF2Items_GetAttributeValue(hItem, i);
TF2Items_SetAttribute(hItem, i, iAttribute, flCurrent - flAmount);
return true;
}
}
return false;
}
/**
* Subtracts from an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param iAttribute Name of the attribute to subtract from.
* @param flValue How much to subtract from the attribute value.
* @return True if subtracted, false otherwise.
*/
stock bool:TF2Items_SubtractAttributeByName(Handle:hItem, const String:strAttribute[], Float:flAmount)
{
decl String:strName[56];
for(new i = 0; i < TF2Items_GetNumAttributes(hItem); i++)
{
TF2II_GetAttribName(TF2Items_GetAttributeId(hItem, i), strName, sizeof(strName));
if(StrEqual(strAttribute, strName))
{
new Float:flCurrent = TF2Items_GetAttributeValue(hItem, i);
TF2Items_SetAttribute(hItem, i, iAttribute, flCurrent - flAmount);
return true;
}
}
return false;
}
/**
* Removes an attribute within a TF2Items item handle.
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @param strAttribute Name of the attribute to remove.
* @return True if removed, false otherwise.
*/
stock TF2Items_RemoveAttributeByName(Handle:hItem, const String:strAttribute[])
{
decl String:strName[56];
decl String:strFormat[56];
for(new i = 0; i < TF2Items_GetNumAttributes(hItem); i++)
{
new iAttribute = TF2Items_GetAttributeId(hItem, i);
TF2II_GetAttribName(iAttribute, strName, sizeof(strName));
if(StrContains(strName, "eater", false) != -1)
continue;
/**
* Removes all default attributes within a TF2Items item handle,
* (default attributes found from items_game.txt).
*
* @param hItem Handle to the TF2Items object that we'll be operating with.
* @noreturn
*/
stock TF2Items_RemoveDefaultAttributes(Handle:hItem)
{
decl String:strName[56];
decl String:strFormat[56];
for(new i = 0; i < TF2Items_GetNumAttributes(hItem); i++)
{
new iAttribute = TF2Items_GetAttributeId(hItem, i);
TF2II_GetAttribName(iAttribute, strName, sizeof(strName));
if(StrContains(strName, "eater", false) != -1)
continue;
#if defined _tf2attributes_included /* @return -1 if no weapon found 0 if weapon found but attribute wasn't added 1 if weapon was found and the attribute was added */ stock TF2Attrib_SetToSlotByName(iClient, iSlot, String:szAttrib[], Float:flValue) { new iWeapon = GetPlayerWeaponSlot(iClient, iSlot); if (iWeapon != -1) { if (TF2Attrib_SetByName(iWeapon, szAttrib, flValue)) { return 1; } return 0; } return -1; }
/* @return -1 if no weapon found 0 if weapon found but attribute wasn't removed 1 if weapon was found and the attribute was added */ stock TF2Attrib_RemoveFromSlotByName(iClient, iSlot, String:szAttrib[]) { new iWeapon = GetPlayerWeaponSlot(iClient, iSlot); if (iWeapon != -1) { if (TF2Attrib_RemoveByName(iWeapon, szAttrib)) { return 1; } return 0; } return -1; }
/* @return -1 if no weapon found 0 if weapon found but attribute wasn't added 1 if weapon was found and the attribute was added */ stock TF2Attrib_SetToSlotByDefIndex(iClient, iSlot, iDefIndex, Float:flValue) { new iWeapon = GetPlayerWeaponSlot(iClient, iSlot); if (iWeapon != -1) { if (TF2Attrib_SetByDefIndex(iWeapon, iDefIndex, flValue)) { return 1; } return 0; } return -1; }
/* @return -1 if no weapon found 0 if weapon found but attribute wasn't removed 1 if weapon was found and the attribute was added */ stock TF2Attrib_RemoveFromSlotByDefIndex(iClient, iSlot, iDefIndex) { new iWeapon = GetPlayerWeaponSlot(iClient, iSlot); if (iWeapon != -1) { if (TF2Attrib_RemoveByDefIndex(iWeapon, iDefIndex)) { return 1; } return 0; } return -1; }
/* Prints out the attribute definition index and its float value to console, based on the weapon slot.
-1 means to list the attributes on the player himself.
Returns false if no weapon was found in the slot. */ stock bool:TF2_AttribListAttributesBySlot(iClient, iSlot = -1) { new iAttribList[16]; new Float:flAttribValues[16]; new Address:aAttr; decl iEntity;
switch (iSlot) { case -1: { iEntity = iClient;
} default: { iEntity = GetPlayerWeaponSlot(iClient, iSlot); if (!IsValidEnt(iEntity)) { PrintToConsole(iClient, "----- No weapon found for (%N) in slot (%i) -----", iClient, iSlot); return false; } } }
PrintToConsole(iClient, "----- Listing attributes for (%N) in slot (%i) -----", iClient, iSlot);
new iCount = TF2Attrib_ListDefIndices(iEntity, iAttribList); if (iCount > 0) { for (new i = 0; i < iCount; i++) { aAttr = TF2Attrib_GetByDefIndex(iEntity, iAttribList[i]); flAttribValues[i] = TF2Attrib_GetValue(aAttr); PrintToConsole(iClient, "Attrib %i: %i ; %0.2f", i+1, iAttribList[i], flAttribValues[i]); } } else { PrintToConsole(iClient, "----- No attributes found for (%N) in slot (%i) -----", iClient, iSlot); }
PrintToConsole(iClient, "----- Listing attributes for (%N) in slot (%i) -----", iClient, iSlot); return true; } #endif
You might notice spy doesn't spawn sappers. That's because I never figured out how it works.
Would your thing be useful for determining whether or not an item has X attribute? And its value. I tried TF2Attributes related natives but I must've done it wrong. (I was trying to check if a player had attribute 252 and get the float value it's set to).
ReFlexPoison
01-19-2015 22:37
Re: [TF2Items] Extended Stocks
Quote:
Originally Posted by Chdata
(Post 2251277)
Would your thing be useful for determining whether or not an item has X attribute? And its value. I tried TF2Attributes related natives but I must've done it wrong. (I was trying to check if a player had attribute 252 and get the float value it's set to).
Use TF2Items_FindAttributeIndex and check if it is not equal to -1.
You can then retrieve the attributes value via TF2Items_GetAttributeValue.
I tend to avoid using TF2Attributes since several of its core functionality could already be accessed though OnGiveNamedItem by using a little brain power.
Chdata
01-19-2015 22:46
Re: [TF2Items] Extended Stocks
I hear the getattribute stuff doesn't work on a weapons "default" attributes (well, the bottom function I listed there at least) and only works on extra attributes that were added by tf2attributes or modified by tf2items.
(Except Flam has yet to push out a version that can lul).
hmm
I mean, I guess I already have a hard coded array that I populate every time I use spawnweapon and after post_inventoryapplication. But eh.
ReFlexPoison
01-19-2015 22:49
Re: [TF2Items] Extended Stocks
Quote:
Originally Posted by Chdata
(Post 2251286)
I hear the getattribute stuff doesn't work on a weapons "default" attributes (well, the bottom function I listed there at least) and only works on extra attributes that were added by tf2attributes or modified by tf2items.
(Except Flam has yet to push out a version that can lul).
hmm
I mean, I guess I already have a hard coded array that I populate every time I use spawnweapon and after post_inventoryapplication. But eh.
You can loop though attributes found with tf2itemsinfo, and use TF2Items_ReplaceAttribute to completly overwrite it. I've been using TF2Items_ReplaceAttribute for everything now, even if it may a bit excessive.
VoiDeD
01-21-2015 14:39
Re: [TF2Items] Extended Stocks
Iterating the non-networked SOC attributes of items is fairly difficult and requires an extension to do the proper way. Generally I'd say avoid that and tf2attribs entirely if you can manage, unless you enjoy the pain that is gamedata updating every few updates.
And it really goes without saying that tf2itemsinfo is a bloated trainwreck.
friagram
01-24-2015 04:42
Re: [TF2Items] Extended Stocks
I'd suggest not naming your functions the same as the extension, since it's different.
As for tf2attributes, can we get setbyname and removebyname added to tf2stocks along with automatic gd updates? These 2 are very useful. There are a few others in tf2attributes plugin, like getvalue and such, but they're not used nearly as often.
Michalplyoutube
01-30-2015 10:36
Re: [TF2Items] Extended Stocks
TF2BWRR Can spawn a sapper using tf2itemsinfo
Uyuzgamer
08-08-2015 15:06
Re: [TF2Items] Extended Stocks
L 08/08/2015 - 22:07:42: [SM] Displaying call stack trace for plugin "tf2itemsinfo.smx":
L 08/08/2015 - 22:07:42: [SM] [0] Line 1652, C:\Server\tf\addons\sourcemod\scripting\tf2it emsinfo.sp::GetAttribIDByName()
L 08/08/2015 - 22:07:42: [SM] [1] Line 1526, C:\Server\tf\addons\sourcemod\scripting\tf2it emsinfo.sp:: PrecacheItemSchema()
L 08/08/2015 - 22:07:42: [SM] [2] Line 252, C:\Server\tf\addons\sourcemod\scripting\tf2it emsinfo.sp::OnPluginStart()
on Centos
Pls help
Potato Uno
08-09-2015 02:29
Re: [TF2Items] Extended Stocks
You cut off the most important part of the error message. Likely TF2ItemsInfo got killed by the watchdog timer.