Recoded weapon restrictions, and made new way of storing data. (Arrays)

* Removed ZMarket as an external plugin (to be integrated next commit)
* Updated weapon configs, removed weapongroups.txt and moved weapons.txt to root zr config folder.
* Moved offset finding to respective module, made new forward *OnOffsetsFound.
* Updated weapons&hitgroups config file format to match playerclass.txt
* Updated translations.
* Recoded weapon restrict menu, commented out all zadmin options that don't quite work.
* Added weaponammo module (not finished but existent)
* Started zmarket module.
This commit is contained in:
Greyscale
2009-05-28 23:43:15 -07:00
parent b1f8de9526
commit 0f8206596a
34 changed files with 2565 additions and 2673 deletions

View File

@ -14,9 +14,6 @@
* Maximum length of a weapon name string
*/
#define WEAPONS_MAX_LENGTH 32
/**
* @endsection
*/
/**
* Number of weapon slots (For CS:S)
@ -24,27 +21,52 @@
#define WEAPONS_SLOTS_MAX 5
/**
* Weapon types.
* Weapon config data indexes.
*/
enum WeaponsType
enum WeaponsData
{
Type_Invalid = -1, /** Invalid weapon (slot). */
Type_Primary = 0, /** Primary weapon slot. */
Type_Secondary = 1, /** Secondary weapon slot. */
Type_Melee = 2, /** Melee (knife) weapon slot. */
Type_Projectile = 3, /** Projectile (grenades, flashbangs, etc) weapon slot. */
Type_Explosive = 4, /** Explosive (c4) weapon slot. */
WEAPONS_DATA_NAME = 0,
WEAPONS_DATA_TYPE,
WEAPONS_DATA_RESTRICTDEFAULT,
WEAPONS_DATA_TOGGLEABLE,
WEAPONS_DATA_AMMOTYPE,
WEAPONS_DATA_AMMOPRICE,
WEAPONS_DATA_KNOCKBACK,
WEAPONS_DATA_ZMARKETPRICE,
WEAPONS_DATA_RESTRICTED,
}
/**
* Keyvalue handle to store weapon data.
*
* @redir config.inc
* @endsection
*/
/**
* Variable to store active weapon offset value.
*/
new g_iToolsActiveWeapon;
/**
* Weapon slots.
*/
enum WeaponsSlot
{
Slot_Invalid = -1, /** Invalid weapon (slot). */
Slot_Primary = 0, /** Primary weapon slot. */
Slot_Secondary = 1, /** Secondary weapon slot. */
Slot_Melee = 2, /** Melee (knife) weapon slot. */
Slot_Projectile = 3, /** Projectile (grenades, flashbangs, etc) weapon slot. */
Slot_Explosive = 4, /** Explosive (c4) weapon slot. */
}
/**
* Array handle to store weapon config data.
*/
new Handle:arrayWeapons = INVALID_HANDLE;
#include "zr/weapons/restrict"
#include "zr/weapons/weaponammo"
#include "zr/weapons/weaponalpha"
#include "zr/weapons/markethandler"
#include "zr/weapons/zmarket"
#include "zr/weapons/menu_weapons"
/**
@ -52,10 +74,26 @@ enum WeaponsType
*/
WeaponsInit()
{
// Forward event to sub-module
// Forward event to sub-modules.
RestrictInit();
}
/**
* Find active weapon-specific offsets here.
*/
WeaponsOnOffsetsFound()
{
// If offset "m_hActiveWeapon" can't be found, then stop the plugin.
g_iToolsActiveWeapon = FindSendPropInfo("CBasePlayer", "m_hActiveWeapon");
if (g_iToolsActiveWeapon == -1)
{
LogPrintToLog(LOG_FORMAT_TYPE_FATALERROR, "Tools", "Offsets", "Offset \"CBasePlayer::m_hActiveWeapon\" was not found.");
}
// Forward event to sub-modules
WeaponAmmoOnOffsetsFound();
}
/**
* Create commands related to weapons here.
*/
@ -65,34 +103,13 @@ WeaponsOnCommandsCreate()
RestrictOnCommandsCreate();
}
/**
* Clears weapon data.
*/
WeaponsClearData()
{
// Load weapon data
if (kvWeapons != INVALID_HANDLE)
{
CloseHandle(kvWeapons);
}
kvWeapons = CreateKeyValues("weapons");
}
/**
* Loads weapon data from file.
*/
WeaponsLoad()
{
// Clear weapon data.
WeaponsClearData();
// Get weapons config path.
decl String:pathweapons[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_WEAPONS, pathweapons);
// Register config info.
ConfigRegisterConfig(ConfigWeapons, false, GetFunctionByName(GetMyHandle(), "WeaponsOnConfigReload"), _, pathweapons, CONFIG_FILE_ALIAS_WEAPONS);
// Register config file.
ConfigRegisterConfig(File_Weapons, Structure_Keyvalue, CONFIG_FILE_ALIAS_WEAPONS);
// If module is disabled, then stop.
new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]);
@ -101,6 +118,10 @@ WeaponsLoad()
return;
}
// Get weapons config path.
decl String:pathweapons[PLATFORM_MAX_PATH];
new bool:exists = ConfigGetCvarFilePath(CVAR_CONFIG_PATH_WEAPONS, pathweapons);
// If file doesn't exist, then log and stop.
if (!exists)
{
@ -110,46 +131,121 @@ WeaponsLoad()
return;
}
// Put file data into memory.
FileToKeyValues(kvWeapons, pathweapons);
// Set the path to the config file.
ConfigSetConfigPath(File_Weapons, pathweapons);
// Load config from file and create array structure.
new bool:success = ConfigLoadConfig(File_Weapons, arrayWeapons);
// Unexpected error, stop plugin.
if (!success)
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Weapons", "Config Validation", "Unexpected error encountered loading: %s", pathweapons);
return;
}
// Validate weapons config.
WeaponsValidateConfig();
new size = GetArraySize(arrayWeapons);
if (!size)
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Weapons", "Config Validation", "No usable data found in weapons config file: %s", pathweapons);
}
// Now copy data to array structure.
WeaponsCacheData();
// Set config data.
ConfigSetConfigLoaded(ConfigWeapons, true);
ConfigSetConfigHandle(ConfigWeapons, kvWeapons);
ConfigSetConfigLoaded(File_Weapons, true);
ConfigSetConfigReloadFunc(File_Weapons, GetFunctionByName(GetMyHandle(), "WeaponsOnConfigReload"));
ConfigSetConfigHandle(File_Weapons, arrayWeapons);
// Forward event to sub-module.
// Forward event to sub-modules
RestrictLoad();
}
/**
* Called when configs are being reloaded.
*
* @param config The config being reloaded. (only if 'all' is false)
* Caches weapon data from file into arrays.
* Make sure the file is loaded before (ConfigLoadConfig) to prep array structure.
*/
public WeaponsOnConfigReload(ConfigFile:config)
WeaponsCacheData()
{
// Reload weapons config.
if (config == ConfigWeapons)
// Get config's file path.
decl String:pathweapons[PLATFORM_MAX_PATH];
ConfigGetConfigPath(File_Weapons, pathweapons, sizeof(pathweapons));
new Handle:kvWeapons;
new bool:success = ConfigOpenConfigFile(File_Weapons, kvWeapons);
if (!success)
{
WeaponsLoad();
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Weapons", "Config Validation", "Unexpected error caching data from weapons config file: %s", pathweapons);
}
decl String:weaponname[WEAPONS_MAX_LENGTH];
// x = array index
new size = GetArraySize(arrayWeapons);
for (new x = 0; x < size; x++)
{
WeaponsGetName(x, weaponname, sizeof(weaponname));
KvRewind(kvWeapons);
if (!KvJumpToKey(kvWeapons, weaponname))
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Weapons", "Config Validation", "Couldn't cache weapon data for: %s (check weapons config)", weaponname);
continue;
}
// Get config data.
decl String:weapontype[CONFIG_MAX_LENGTH];
decl String:ammotype[CONFIG_MAX_LENGTH];
// General
KvGetString(kvWeapons, "weapontype", weapontype, sizeof(weapontype));
// Restrict (core)
new bool:restrictdefault = ConfigKvGetStringBool(kvWeapons, "restrictdefault", "no");
new bool:toggleable = ConfigKvGetStringBool(kvWeapons, "toggleable", "yes");
// Weapon Ammo (core)
KvGetString(kvWeapons, "ammotype", ammotype, sizeof(ammotype));
new ammoprice = KvGetNum(kvWeapons, "ammoprice");
// Knockback (module)
new Float:knockback = KvGetFloat(kvWeapons, "knockback", 1.0);
// ZMarket (module)
new zmarketprice = KvGetNum(kvWeapons, "zmarketprice", -1);
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, x);
// Push data into array.
PushArrayString(arrayWeapon, weapontype); // Index: 1
PushArrayCell(arrayWeapon, restrictdefault); // Index: 2
PushArrayCell(arrayWeapon, toggleable); // Index: 3
PushArrayString(arrayWeapon, ammotype); // Index: 4
PushArrayCell(arrayWeapon, ammoprice); // Index: 5
PushArrayCell(arrayWeapon, knockback); // Index: 6
PushArrayCell(arrayWeapon, zmarketprice); // Index: 7
// Initialize other stored weapon info here.
PushArrayCell(arrayWeapon, restrictdefault); // Index: 8
}
// We're done with this file now, so we can close it.
CloseHandle(kvWeapons);
}
/**
* Validate weapon config file and settings.
* Called when config is being reloaded.
*/
WeaponsValidateConfig()
public WeaponsOnConfigReload()
{
KvRewind(kvWeapons);
if (!KvGotoFirstSubKey(kvWeapons))
{
LogPrintToLog(LOG_FORMAT_TYPE_ERROR, "Weapons", "Config Validation", "No weapons listed in weapons.txt.");
}
// Reload weapons config.
WeaponsLoad();
}
/**
* Client is joining the server.
*
@ -195,154 +291,173 @@ WeaponsOnRoundEnd()
}
/**
* Creates an array of all listed weapons in weapons.txt.
* @param arrayWeapons The handle of the array, don't forget to call CloseHandle
* on it when finished!
* @return The size of the array.
* Weapon data reading API.
*/
stock WeaponsCreateWeaponArray(&Handle:arrayWeapons, maxlen = WEAPONS_MAX_LENGTH)
/**
* Clear cache for a given weapon.
*
* @param index The weapon index.
*/
WeaponsClearCache(index)
{
// Initialize array handle.
arrayWeapons = CreateArray(maxlen);
new count = 0;
// Get array handle of weapon at given index.
new Handle:hWeapon = GetArrayCell(arrayWeapons, index);
// Reset keyvalue's traveral stack.
KvRewind(kvWeapons);
if (KvGotoFirstSubKey(kvWeapons))
{
decl String:weapon[maxlen];
do
{
KvGetSectionName(kvWeapons, weapon, maxlen);
// Push weapon name into the array.
PushArrayString(arrayWeapons, weapon);
// Increment count.
count++;
} while (KvGotoNextKey(kvWeapons));
}
// Return the count
return count;
// Clear array.
ClearArray(hWeapon);
}
/**
* Checks if a weapon is valid. (aka listed in weapons.txt)
* Find the index at which the weapon's name is at.
*
* @param weapon The weapon name.
* @return The array index containing the given weapon name.
*/
stock WeaponsNameToIndex(const String:weapon[])
{
decl String:weaponname[WEAPONS_MAX_LENGTH];
// x = Array index.
new size = GetArraySize(arrayWeapons);
for (new x = 0; x < size; x++)
{
WeaponsGetName(x, weaponname, sizeof(weaponname));
// If names match, then return index.
if (StrEqual(weapon, weaponname, false))
{
return x;
}
}
// Name doesn't exist.
return -1;
}
/**
* Checks if a weapon is valid. (E.G. listed in weapons.txt)
* @param weapon The weapon name.
* @return Returns true if valid, false it not.
*/
stock bool:WeaponsIsValidWeapon(const String:weapon[])
stock bool:WeaponsIsWeaponValid(const String:weapon[])
{
// Reset keyvalue's traversal stack.
KvRewind(kvWeapons);
if (KvGotoFirstSubKey(kvWeapons))
{
decl String:validweapon[WEAPONS_MAX_LENGTH];
do
{
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
// If weaponname matches a valid weapon, then return true.
if (StrEqual(validweapon, weapon, false))
{
return true;
}
} while (KvGotoNextKey(kvWeapons));
}
// Weapon is invalid.
return false;
return (WeaponsNameToIndex(weapon) != -1);
}
/**
* Looks up a weapon in weapons.txt and returns exact display name.
* @param weapon The weapon name.
* @param display Returns with the display name, is not changed if weapon is invalid.
* Gets the name of a weapon at a given index.
* @param index The weapon index.
* @param weapon The string to return name in.
* @param maxlen The max length of the string.
*/
stock WeaponsGetDisplayName(const String:weapon[], String:display[])
stock WeaponsGetName(index, String:weapon[], maxlen)
{
// Reset keyvalue's traversal stack.
KvRewind(kvWeapons);
if (KvGotoFirstSubKey(kvWeapons))
{
decl String:validweapon[WEAPONS_MAX_LENGTH];
do
{
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
// If weapon matches a valid weapon (case-insensitive), then return display name.
if (StrEqual(validweapon, weapon, false))
{
strcopy(display, WEAPONS_MAX_LENGTH, validweapon);
}
} while (KvGotoNextKey(kvWeapons));
}
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
// Get weapon name.
GetArrayString(arrayWeapon, _:WEAPONS_DATA_NAME, weapon, maxlen);
}
/**
* Checks if a weapon restriction can be toggled by the admin menu.
* @param weapon The weapon name.
* @return Returns true if restricted, false it not.
* Gets the type of a weapon at a given index.
* @param index The weapon index.
* @param type The string to return type in.
* @param maxlen The max length of the string.
*/
stock bool:WeaponsIsWeaponMenu(const String:weapon[])
stock WeaponsGetType(index, String:type[], maxlen)
{
// Reset keyvalue's traversal stack.
KvRewind(kvWeapons);
if (KvGotoFirstSubKey(kvWeapons))
{
decl String:validweapon[WEAPONS_MAX_LENGTH];
decl String:menu[8];
do
{
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
// If this is the right weapon, then return setting for it.
if (StrEqual(validweapon, weapon, false))
{
KvGetString(kvWeapons, "menu", menu, sizeof(menu), "yes");
// Return weapon's setting.
return ConfigSettingToBool(menu);
}
} while (KvGotoNextKey(kvWeapons));
}
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
return false;
// Get weapon type.
GetArrayString(arrayWeapon, _:WEAPONS_DATA_TYPE, type, maxlen);
}
/**
* Returns knockback multiplier of the weapon.
* @param weapon The weapon name.
* @return The float value of the knockback multiplier, 1.0 if not found.
* Gets if a weapon is restricted by default.
* @param index The weapon index.
* @return True if the weapon is restricted by default, false if not.
*/
stock Float:WeaponGetWeaponKnockback(const String:weapon[])
stock bool:WeaponsGetRestrictDefault(index)
{
// Reset keyvalue's traversal stack.
KvRewind(kvWeapons);
if (KvGotoFirstSubKey(kvWeapons))
{
decl String:validweapon[WEAPONS_MAX_LENGTH];
do
{
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
// If this is the right weapon, then return setting for it.
if (StrEqual(validweapon, weapon, false))
{
return KvGetFloat(kvWeapons, "knockback", 1.0);
}
} while (KvGotoNextKey(kvWeapons));
}
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
return 1.0;
// Return default restriction status.
return bool:GetArrayCell(arrayWeapon, _:WEAPONS_DATA_RESTRICTDEFAULT);
}
/**
* Gets if a weapon's restriction status is toggleable.
* @param index The weapon index.
* @return True if the weapon restriction can be toggled, false if not.
*/
stock bool:WeaponsGetToggleable(index)
{
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
// Return if weapon is toggleable.
return bool:GetArrayCell(arrayWeapon, _:WEAPONS_DATA_TOGGLEABLE);
}
/**
* Gets the ammo type of a weapon at a given index.
* @param index The weapon index.
* @param ammotype The string to return ammotype in.
* @param maxlen The max length of the string.
*/
stock WeaponsGetAmmoType(index, String:ammotype[], maxlen)
{
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
// Get ammo type of the weapon.
GetArrayString(arrayWeapon, _:WEAPONS_DATA_AMMOTYPE, type, maxlen);
}
/**
* Gets the price of ammo for the weapon.
* @param index The weapon index.
* @return The ammo price.
*/
stock WeaponsGetAmmoPrice(index)
{
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
// Return ammo price of the weapon.
return GetArrayCell(arrayWeapon, _:WEAPONS_DATA_AMMOPRICE);
}
/**
* Gets the knockback multiplier for the weapon.
* @param index The weapon index.
* @return The weapon knockback multiplier.
*/
stock Float:WeaponsGetKnockback(index)
{
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
// Return knockback multiplier of the weapon.
return Float:GetArrayCell(arrayWeapon, _:WEAPONS_DATA_KNOCKBACK);
}
/**
* Gets the ZMarket price for the weapon.
* @param index The weapon index.
* @return The ZMarket price.
*/
stock WeaponsGetZMarketPrice(index)
{
// Get array handle of weapon at given index.
new Handle:arrayWeapon = GetArrayCell(arrayWeapons, index);
// Return the ZMarket price of the weapon.
return GetArrayCell(arrayWeapon, _:WEAPONS_DATA_ZMARKETPRICE);
}
/**
@ -356,7 +471,7 @@ stock Float:WeaponGetWeaponKnockback(const String:weapon[])
* @param weapons The weapon index array.
* -1 if no weapon in slot.
*/
stock WeaponsGetClientWeapons(client, weapons[WeaponsType])
stock WeaponsGetClientWeapons(client, weapons[WeaponsSlot])
{
// x = weapon slot.
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
@ -384,10 +499,10 @@ stock WeaponsGetDeployedWeaponIndex(client)
* @param client The client index.
* @return The slot number of deployed weapon.
*/
stock WeaponsType:WeaponsGetDeployedWeaponSlot(client)
stock WeaponsSlot:WeaponsGetDeployedWeaponSlot(client)
{
// Get all client's weapon indexes.
new weapons[WeaponsType];
new weapons[WeaponsSlot];
WeaponsGetClientWeapons(client, weapons);
// Get client's deployed weapon.
@ -404,7 +519,7 @@ stock WeaponsType:WeaponsGetDeployedWeaponSlot(client)
{
if (weapons[x] == deployedweapon)
{
return x;
return WeaponsSlot:x;
}
}