[TF2][BETA] Wearable Items (Core 1.0 / Manager 1.0)
[Please READ]
Rewritten from the grounds up, this plugin is the evolution of the E quipment Manager plugin. It allows players to equip wearable items (those being hats, armors, or anything the administrator sets in the server) to customize the visuals of the characters.
Basically, the plugin is now divided in two: the core plugin, wich manages the basic funcionalities (Equipping items, removing them, managing and storing item attributes, etc.) and interfaces with other Sourcemod plugins; and the manager plugin, wich parses the repository files and manages the menu interface with the core.
This new plugin features a huge lot of new functionalities, but due to lack of time on my side, it's still not complete (at least, not as flexible as the Equipment manager) so it's meant to be used in development environments rather than on real servers.
I'm releasing this hoping to find people who could help me making plugins to expand/enhance it's funcionality (for example, creating an interface to the Custom Achievements plugin) and improving the core plugins.
[/Please READ]
Features:
- Support for wearable items - Both the original ones and custom ones.
- Up to 8 slots with customizable slot name.
- Modular item reference system - Just drag and drop the reference to the repository folder, there's no need to edit the config file anymore.
- Rewrote with modularity in mind (completely Trie based).
- Plugin can interface through fake natives and forwards - Other plugins are able to communicate with it, useful for allowing players to use a hat after achieving a custom achievement.
- Makes use of clientprefs to remember wich hats the player was using.
Cvars
- tf_items_version - Current version of the core plugin.
- tf_items_manager_version - Current version of the manager plugin.
Commands:
- tf_items - Used to equip and remove items.
- items - Used to equip and remove items (alias).
- hats - Used to equip and remove items (alias).
- em - Used to equip and remove items (alias).
Usage: tf_items <equip/remove> <shortname/slot>. If no arguments are present, a menu with the slots and options will appear. How to Install:
- Place the provided files in the zip file on the correct folders in Sourcemod.
- In case of updating, delete the previous files used by the plugin, before placing the new contents.
How to Configure:
1. Changing the repository location:
The repository is the folder where the plugin will start to search for item definition files ( item.res). Basically, the plugin will iterate the subfolders located in the repository and search for it. You could have it anywhere, but in the example provided, it is on the custom models folder I use on my server.
Open up the config.cfg file located at /addons/Sourcemod/config/items/ and change this line:
PHP Code:
"string:repository" "models/rss-custom/hats/"
For the repository directory you want.
2. Changing the slot names:
Again, open up the config.cfg file located at /addons/Sourcemod/config/items/ and change these lines:
PHP Code:
"string:slot0" "Comϊnes" "string:slot1" "Personalizados" "string:slot2" "Especiales"
Basically, you need to set a name for each slot in the same fashion as the example config does ("string:slotN", where N is the slot number, from 0 to 7). The slots whose names aren't set won't be visible on the manager's menu.
3. How to add / modify the items.
As said, the items are defined through the item.res file, located at each subfolder inside the repository folder. Inside the .res file, you can define any number of items you want, as long as you follow the rules correctly. A basic example on how to setup a manager plugin compliant item would be the following:
PHP Code:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // BASIC VALUES // // // These are the basic values common to all the items. need to be set in order to // properly work. // // +========================+===========+===========================================+ // | NAME | TYPE | DESCRIPTION | // +========================+===========+===========================================+ // | name | String | Short, identificative name. Used for | // | | | referring to an item. Needs to be unique. | // +------------------------+-----------+-------------------------------------------+ // | long-name | String | Long name, as it appears on the menus. | // +------------------------+-----------+-------------------------------------------+ // | model | String | The model of this item. | // +------------------------+-----------+-------------------------------------------+ // | index | Integer | The equivalent TF2 item index value. This | // | | | really should be set to one of the hats | // | | | values found in the items.ctx, or else | // | | | the plugin may not work as expected. | // +------------------------+-----------+-------------------------------------------+ // | quality | Integer | The quality level of the item. Determines | // | | | the color in wich will it appear. Valid | // | | | values are from 0 to 8. Anything beyond | // | | | that will make the server crash. | // +------------------------+-----------+-------------------------------------------+ // | level | Integer | The level of the item. Level 100 afro! | // +------------------------+-----------+-------------------------------------------+ // | slot | Integer | The slot where this item will be found. | // | | | The range of slots should lie between 0 | // | | | and 7. | // +------------------------+-----------+-------------------------------------------+ // | bodygroups | Integer | Field to set the bodygroups wich will be | // | | | invisible with this hat. This field | // | | | is filled as a bitfield, so it may not be | // | | | so user friendly. Instead, use the | // | | | bodygroups-table if you're using the | // | | | manager plugin along the core. | // +------------------------+-----------+-------------------------------------------+ // // // MANAGER VALUES // // // The manager plugin also needs a number of keys that need to be set in order to // properly work. // // +========================+===========+===========================================+ // | NAME | TYPE | DESCRIPTION | // +========================+===========+===========================================+ // | class-restrictions | String | Sets wich classes can use this item. Each | // | | | class name should be separated by a | // | | | comma. Valid parameters: | // | | | | // | | | all, scout, sniper, soldier, demoman, | // | | | medic, heavy, pyro, spy, engineer | // +------------------------+-----------+-------------------------------------------+ // | team-restrictions | String | Sets wich teams can use this item. It | // | | | works pretty much like the one above. | // | | | Valid parameters: | // | | | | // | | | all, red, blue | // +------------------------+-----------+-------------------------------------------+ // | admin-restrictions | String | Admin flags needed for a client to be | // | | | able to use this item. If not set, there | // | | | is no admin restriction. | // +------------------------+-----------+-------------------------------------------+ // | bodygroups-table | String | Special field to set the bodygroups in a | // | | | more user-friendly fashion. The parame- | // | | | ters are separated by comma. | // | | | Valid parameters: | // | | | | // | | | scout_hat, scout_headphones, heavy_hands, | // | | | engineer_helmet, sniper_quiver, | // | | | sniper_hat, soldier_rocket, soldier_medal,| // | | | soldier_helmet | // +------------------------+-----------+-------------------------------------------+ // // // RESOURCES // // // The resources are the files (models, textures, particles) that need to be precached // and used along the item model for it to work. Each of the resources listed will // automatically be precached and downloaded to the tables list at the start of each // map. // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"item" { // - Basics ---------------------------------- "string:name" "demomanfro" "string:long-name" "Demoman's Fro" "string:model" "models/player/items/demo/demo_afro.mdl" "integer:index" "47" "integer:quality" "3" "integer:level" "100" "integer:slot" "0" "integer:bodygroups" "0" // - Manager --------------------------------- "string:class-restrictions" "demoman" "string:team-restrictions" "all" "string:bodygroups-table" "scout_hat, scout_headphones, sniper_hat, soldier_helmet, engineer_helmet" }
Another example of a custom hat with download table references
PHP Code:
"item" { // - Basics ---------------------------------- "string:name" "pedobear" "string:long-name" "Casco de Pedobear" "string:model" "models/rss-custom/hats/pedobear/pedobear.mdl" "integer:index" "125" "integer:quality" "3" "integer:level" "100" "integer:slot" "1" "integer:bodygroups" "0" // - Manager --------------------------------- "string:class-restrictions" "heavy" "string:team-restrictions" "all" "string:bodygroups-table" "scout_hat, scout_headphones, sniper_hat, soldier_helmet, engineer_helmet"
// - Resources ------------------------------- "string:resource-0" "materials/models/rss-custom/hats/pedobear/pedobear.vtf" "string:resource-1" "materials/models/rss-custom/hats/pedobear/pedobear.vmt" "string:resource-2" "models/rss-custom/hats/pedobear/pedobear.dx80.vtx" "string:resource-3" "models/rss-custom/hats/pedobear/pedobear.dx90.vtx" "string:resource-4" "models/rss-custom/hats/pedobear/pedobear.mdl" "string:resource-5" "models/rss-custom/hats/pedobear/pedobear.phy" "string:resource-6" "models/rss-custom/hats/pedobear/pedobear.sw.vtx" "string:resource-7" "models/rss-custom/hats/pedobear/pedobear.vvd" }
How to interface:
The core plugin supplies a basic (but powerful) interface with it so other plugins can know what's going on, interact with the core and modify item settings.
The include file to interface with it is called items_core.inc wich describes the following:
PHP Code:
#if defined _items_core_included #endinput #endif #define _items_core_included
/* ** ** ______ __ __ ** / ____/___ ____ _____/ /_____ _____ / /______ ** / / / __ \/ __ \/ ___/ __/ __ `/ __ \/ __/ ___/ ** / /___/ /_/ / / / (__ ) /_/ /_/ / / / / /_(__ ) ** \____/\____/_/ /_/____/\__/\__,_/_/ /_/\__/____/ ** ** */
// ---- Flags and everything ------------------------------------------------------- #define MAX_SLOTS 8
#define FLAG_HIDE_SCOUT_HAT (1 << 0) #define FLAG_HIDE_SCOUT_HEADPHONES (1 << 1) #define FLAG_HIDE_HEAVY_HANDS (1 << 2) #define FLAG_HIDE_ENGINEER_HELMET (1 << 3) #define FLAG_SHOW_SNIPER_QUIVER (1 << 4) #define FLAG_HIDE_SNIPER_HAT (1 << 5) #define FLAG_HIDE_SOLDIER_ROCKET (1 << 6) #define FLAG_HIDE_SOLDIER_HELMET (1 << 7) #define FLAG_SHOW_SOLDIER_MEDAL (1 << 8)
#define BODYGROUP_SCOUT_HAT (1 << 0) #define BODYGROUP_SCOUT_HEADPHONES (1 << 1) #define BODYGROUP_HEAVY_HANDS (1 << 0) #define BODYGROUP_ENGINEER_HELMET (1 << 0) #define BODYGROUP_SNIPER_QUIVER (1 << 0) #define BODYGROUP_SNIPER_HAT (1 << 1) #define BODYGROUP_SOLDIER_ROCKET (1 << 0) #define BODYGROUP_SOLDIER_HELMET (1 << 1) #define BODYGROUP_SOLDIER_MEDAL (1 << 2)
// ---- Plugin constants ----------------------------------------------------------- enum eItemCodes { Success = 1, Error_InvalidItem = -1, Error_NotInit = -2, Error_AlreadyExists = -3, Error_NotFound = -4, Error_Cancelled = -5, Error_CanNotUse = -6, Error_InvalidClient = -7, Error_InvalidSlot = -8 };
/* ** ** ______ __ ** / ____/___ ______ ______ __________/ /____ ** / /_ / __ \/ ___/ | /| / / __ `/ ___/ __ / ___/ ** / __/ / /_/ / / | |/ |/ / /_/ / / / /_/ (__ ) ** /_/ \____/_/ |__/|__/\__,_/_/ \__,_/____/ ** ** */
/* OnItemCreated() ** ** Called whenever an item has been created and registered in the plugin. ** -------------------------------------------------------------------------- */ forward OnItemCreated(Handle:hItem);
/* OnItemDeleted() ** ** Called whenever an item has been deleted. ** -------------------------------------------------------------------------- */ forward OnItemDeleted(Handle:hItem);
/* CanPlayerUseItem() ** ** Determines if the given item can be used by the client. The reference va- ** riable "bCanUse" tells the plugin if it's permitted to use it or not. The ** "iTopLevel" one is an optional variable in case you want to stablish an ** hierarchy between plugins when deciding if it's usable. ** ** For example, if plugin A with level 4 says the item is usable, but the ** plugin B with level 10 says it isn't, if both plugins respect the hierachical ** levels, the plugin B will be the one to decide if it's useable. ** -------------------------------------------------------------------------- */ forward CanPlayerUseItem(iClient, Handle:hItem, &bool:bCanUse, &iTopLevel);
/* OnPlayerEquipItem() ** ** Called whenever a client successfully equipped an item. ** -------------------------------------------------------------------------- */ forward OnPlayerEquipItem(iClient, Handle:hItem, bool:bRegenerating);
/* OnPlayerEquipItemPre() ** ** Called whenever a client is about to equip an item. This call is always done ** before the CanPlayerUseItem forward, and returning the action Plugin_Stop will ** inmediately cancel the equip method. ** -------------------------------------------------------------------------- */ forward Action:OnPlayerEquipItemPre(iClient, Handle:hItem, bool:bRegenerating);
/* OnPlayerRemoveItem() ** ** Called whenever a client successfully removed an item. ** -------------------------------------------------------------------------- */ forward OnPlayerRemoveItem(iClient, Handle:hItem, bool:bDeleted);
/* OnPlayerRemoveItemPre() ** ** Called whenever a client is about to remove an item. Returning the action ** state Plugin_Stop will inmediately cancel the remove method. ** -------------------------------------------------------------------------- */ forward Action:OnPlayerRemoveItemPre(iClient, Handle:hItem, bool:bDeleted);
/* OnItemPreload() ** ** Tells the other plugins we're about to preload. ** -------------------------------------------------------------------------- */ forward OnItemPreload();
/* ** ** _ __ __ _ ** / | / /___ _/ /_(_) _____ _____ ** / |/ / __ `/ __/ / | / / _ \/ ___/ ** / /| / /_/ / /_/ /| |/ / __(__ ) ** /_/ |_/\__,_/\__/_/ |___/\___/____/ ** ** ** */
/* CreateItem() ** ** Fake native method wich obtains an item structure and registers it onto the ** plugin tables. ** -------------------------------------------------------------------------- */ native eItemCodes:CreateItem(Handle:hItem);
/* DeleteItem() ** ** Deletes the given item from the tables and removes it from any player that ** had it equipped. ** -------------------------------------------------------------------------- */ native eItemCodes:DeleteItem(Handle:hItem);
/* FindItemByName() ** ** Looksup the tables to find the given item through it's short name. ** -------------------------------------------------------------------------- */ native Handle:FindItemByName(String:strName[]);
/* CountItems() ** ** Returns the item count. ** -------------------------------------------------------------------------- */ native CountItems();
/* GetItemFromTable() ** ** Navigates and returns an item from the table. ** -------------------------------------------------------------------------- */ native Handle:GetItemFromTable(iIndex);
/* CountItemSlots() ** ** Retrieves the number of slots available for the items. ** -------------------------------------------------------------------------- */ native CountItemSlots();
/* GetItemAtSlot() ** ** Retrieves the equipped item at the given slot. ** -------------------------------------------------------------------------- */ native Handle:GetItemAtSlot(iClient, iSlot);
/* SetItemAtSlot() ** ** Sets the equipped item at the given slot. ** -------------------------------------------------------------------------- */ native Handle:SetItemAtSlot(iClient, iSlot, Handle:hItem);
/* QueryPlayerCanUseItem() ** ** Queries the other plugins to check if the given item can be used by the ** client. ** -------------------------------------------------------------------------- */ native bool:QueryPlayerCanUseItem(iClient, Handle:hItem);
/* EquipPlayerItem() ** ** Equips the given item on the player, querying the other plugins for it. ** -------------------------------------------------------------------------- */ native eItemCodes:EquipPlayerWearableItem(iClient, Handle:hItem);
/* RemovePlayerItem() ** ** Removes the given item on the player (if it's equipped) ** -------------------------------------------------------------------------- */ native eItemCodes:RemovePlayerWearableItem(iClient, Handle:hItem);
/* RemovePlayerItemSlot() ** ** Removes the item equipped on the slot (if any) ** -------------------------------------------------------------------------- */ native eItemCodes:RemoveWearableItemSlot(iClient, iSlot);
/* ** ** __ ___ _ __ __ _ ** / |/ /___ _____ (_)___ __ __/ /___ _/ /_(_)___ ____ ** / /|_/ / __ `/ __ \/ / __ \/ / / / / __ `/ __/ / __ \/ __ \ ** / / / / /_/ / / / / / /_/ / /_/ / / /_/ / /_/ / /_/ / / / / ** /_/ /_/\__,_/_/ /_/_/ .___/\__,_/_/\__,_/\__/_/\____/_/ /_/ ** /_/ ** ** */
/* SetItem...() ** ** Methods to change the basic properties of the item structures. ** -------------------------------------------------------------------------- */ stock SetItemName(Handle:hItem, String:strBuffer[]) { SetTrieString(hItem, "name", strBuffer); } stock SetItemLongName(Handle:hItem, String:strBuffer[]) { SetTrieString(hItem, "long-name", strBuffer); } stock SetItemModel(Handle:hItem, String:strBuffer[]) { SetTrieString(hItem, "model", strBuffer); } stock SetItemIndex(Handle:hItem, iIndex) { SetTrieValue(hItem, "index", iIndex); } stock SetItemQuality(Handle:hItem, iQuality) { SetTrieValue(hItem, "quality", iQuality); } stock SetItemLevel(Handle:hItem, iLevel) { SetTrieValue(hItem, "level", iLevel); } stock SetItemSlot(Handle:hItem, iSlot) { SetTrieValue(hItem, "slot", iSlot); } stock SetItemBodyGroups(Handle:hItem, iBodyGroups) { SetTrieValue(hItem, "bodygroups", iBodyGroups); }
/* GetItem...() ** ** Methods to retrieve the basic properties of the item structures. ** -------------------------------------------------------------------------- */ stock GetItemName(Handle:hItem, String:strBuffer[], iMaxLength) { GetTrieString(hItem, "name", strBuffer, iMaxLength); } stock GetItemLongName(Handle:hItem, String:strBuffer[], iMaxLength) { GetTrieString(hItem, "long-name", strBuffer, iMaxLength); } stock GetItemModel(Handle:hItem, String:strBuffer[], iMaxLength) { GetTrieString(hItem, "model", strBuffer, iMaxLength); } stock GetItemIndex(Handle:hItem) { decl iValue; GetTrieValue(hItem, "index", iValue); return iValue; } stock GetItemQuality(Handle:hItem) { decl iValue; GetTrieValue(hItem, "quality", iValue); return iValue; } stock GetItemLevel(Handle:hItem) { decl iValue; GetTrieValue(hItem, "level", iValue); return iValue; } stock GetItemSlot(Handle:hItem) { decl iValue; GetTrieValue(hItem, "slot", iValue); return iValue; } stock GetItemBodyGroups(Handle:hItem) { decl iValue; GetTrieValue(hItem, "bodygroups", iValue); return iValue; }
/* ** ** ____ __ _ ** / __ \___ ____ ___ ____ ____/ /__ ____ _____(_)__ _____ ** / / / / _ \/ __ \/ _ \/ __ \/ __ / _ \/ __ \/ ___/ / _ \/ ___/ ** / /_/ / __/ /_/ / __/ / / / /_/ / __/ / / / /__/ / __(__ ) ** /_____/\___/ .___/\___/_/ /_/\__,_/\___/_/ /_/\___/_/\___/____/ ** /_/ ** ** */ public SharedPlugin:__pl_ItemsCore = { name = "ItemsCore", file = "TF2_ItemsCore.smx", #if defined REQUIRE_PLUGIN required = 1, #else required = 0, #endif };
public __pl_ItemsCore_SetNTVOptional() { }
Changelog:Known Issues:
- May be a little slow sometimes - Perhaps I need to find a better way other than tries (or at least, less memory hog).
- The plugin forces to reset the bodygroups, so if a client already has equipped and item wich modifies these, the two will overlap.
- When the player dies, on non-drop hat types, the ragdoll hat skin appears as Red. Aesthetical problem, I still haven't figured how to fix it, but it's not very relevant.
To do:
- Fix the bodygroups issue [/lazy]
- Integrate admin functionalities.
- Integrate admin menu funcionalities.
- Expand the manager to allow more restrictions (steamid based, perhaps).
- Translations, of course.
Credits:
- Pedobear item model by Dobkeratops. Thanks to him for this
- Thanks to everyone who helped enhance the Equipment Manager (and who will help me to enhance this one).
__________________
Last edited by Damizean; 01-12-2010 at 08:08.
|