2009-04-20 02:56:26 +02:00
|
|
|
/*
|
|
|
|
* ============================================================================
|
|
|
|
*
|
2009-04-12 08:04:00 +02:00
|
|
|
* Zombie:Reloaded
|
2009-04-20 02:56:26 +02:00
|
|
|
*
|
|
|
|
* File: weapons.inc
|
|
|
|
* Description: API for all weapon-related functions.
|
|
|
|
*
|
|
|
|
* ============================================================================
|
2009-04-12 08:04:00 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maximum length of a weapon name string
|
|
|
|
*/
|
|
|
|
#define WEAPONS_MAX_LENGTH 32
|
|
|
|
/**
|
|
|
|
* @endsection
|
|
|
|
*/
|
2009-04-20 05:43:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Number of weapon slots (For CS:S)
|
|
|
|
*/
|
|
|
|
#define WEAPONS_SLOTS_MAX 5
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Weapon types.
|
|
|
|
*/
|
|
|
|
enum WeaponsType
|
|
|
|
{
|
|
|
|
Type_Invalid = -1,
|
|
|
|
Type_Primary = 0,
|
|
|
|
Type_Secondary = 1,
|
|
|
|
Type_Melee = 2,
|
|
|
|
Type_Projectile = 3,
|
|
|
|
Type_Explosive = 4,
|
|
|
|
}
|
|
|
|
|
2009-04-12 08:04:00 +02:00
|
|
|
/**
|
|
|
|
* Array to store keyvalue data.
|
|
|
|
*/
|
|
|
|
new Handle:kvWeapons = INVALID_HANDLE;
|
|
|
|
|
|
|
|
#include "zr/weapons/restrict"
|
|
|
|
#include "zr/weapons/markethandler"
|
|
|
|
#include "zr/weapons/menu_weapons"
|
|
|
|
|
2009-04-14 04:58:05 +02:00
|
|
|
/**
|
2009-04-15 09:42:12 +02:00
|
|
|
* Weapons module init function.
|
2009-04-14 04:58:05 +02:00
|
|
|
*/
|
2009-04-13 20:33:13 +02:00
|
|
|
WeaponsInit()
|
|
|
|
{
|
|
|
|
// Forward event to sub-module
|
|
|
|
RestrictInit();
|
|
|
|
}
|
|
|
|
|
2009-04-12 08:04:00 +02:00
|
|
|
/**
|
2009-04-15 09:42:12 +02:00
|
|
|
* Clears weapon data.
|
2009-04-12 08:04:00 +02:00
|
|
|
*/
|
2009-04-14 04:58:05 +02:00
|
|
|
WeaponsClearData()
|
2009-04-12 08:04:00 +02:00
|
|
|
{
|
|
|
|
// Load weapon data
|
|
|
|
if (kvWeapons != INVALID_HANDLE)
|
|
|
|
{
|
|
|
|
CloseHandle(kvWeapons);
|
|
|
|
}
|
|
|
|
|
|
|
|
kvWeapons = CreateKeyValues("weapons");
|
2009-04-14 04:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads weapon data from file.
|
|
|
|
*/
|
2009-04-15 03:24:02 +02:00
|
|
|
WeaponsLoad()
|
2009-04-14 04:58:05 +02:00
|
|
|
{
|
2009-04-15 09:42:12 +02:00
|
|
|
// Clear weapon data.
|
2009-04-14 04:58:05 +02:00
|
|
|
WeaponsClearData();
|
|
|
|
|
2009-04-20 02:56:26 +02:00
|
|
|
// If module is disabled, then stop.
|
|
|
|
new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]);
|
|
|
|
if (!weapons)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2009-04-12 08:04:00 +02:00
|
|
|
|
|
|
|
decl String:path[PLATFORM_MAX_PATH];
|
|
|
|
BuildPath(Path_SM, path, sizeof(path), "configs/zr/weapons/weapons.txt");
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// If file isn't found, stop plugin.
|
2009-04-12 08:04:00 +02:00
|
|
|
if (!FileToKeyValues(kvWeapons, path))
|
|
|
|
{
|
2009-04-20 05:43:20 +02:00
|
|
|
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
|
2009-04-14 04:58:05 +02:00
|
|
|
{
|
2009-04-20 05:43:20 +02:00
|
|
|
LogMessageFormatted(-1, "Weapons", "Config Validation", "Missing file weapons.txt.", LOG_FORMAT_TYPE_ERROR);
|
2009-04-14 04:58:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// Validate weapons config.
|
2009-04-15 03:24:02 +02:00
|
|
|
WeaponsValidateConfig();
|
2009-04-13 20:33:13 +02:00
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// Forward event to sub-module.
|
2009-04-13 20:33:13 +02:00
|
|
|
RestrictOnMapStart();
|
|
|
|
}
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
/**
|
|
|
|
* Validate weapon config file and settings.
|
2009-04-17 01:09:52 +02:00
|
|
|
*/
|
2009-04-15 03:24:02 +02:00
|
|
|
WeaponsValidateConfig()
|
2009-04-13 20:33:13 +02:00
|
|
|
{
|
2009-04-15 09:42:12 +02:00
|
|
|
// If log flag check fails, don't log.
|
2009-04-20 05:43:20 +02:00
|
|
|
if (!LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
|
2009-04-14 04:58:05 +02:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-04-12 08:04:00 +02:00
|
|
|
KvRewind(kvWeapons);
|
2009-04-14 04:58:05 +02:00
|
|
|
if (!KvGotoFirstSubKey(kvWeapons))
|
2009-04-12 08:04:00 +02:00
|
|
|
{
|
2009-04-20 05:43:20 +02:00
|
|
|
LogMessageFormatted(-1, "Weapons", "Config Validation", "No weapons listed in weapons.txt.", LOG_FORMAT_TYPE_ERROR);
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|
2009-04-13 20:33:13 +02:00
|
|
|
}
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
/**
|
|
|
|
* Client is joining the server.
|
|
|
|
*
|
|
|
|
* @param client The client index.
|
2009-04-19 19:54:21 +02:00
|
|
|
*/
|
2009-04-13 20:33:13 +02:00
|
|
|
WeaponsClientInit(client)
|
|
|
|
{
|
2009-04-15 09:42:12 +02:00
|
|
|
// Forward event to sub-module.
|
2009-04-13 20:33:13 +02:00
|
|
|
RestrictClientInit(client);
|
|
|
|
}
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
/**
|
|
|
|
* Client is leaving the server.
|
|
|
|
*
|
|
|
|
* @param client The client index.
|
2009-04-19 19:54:21 +02:00
|
|
|
*/
|
2009-04-13 20:33:13 +02:00
|
|
|
WeaponsOnClientDisconnect(client)
|
|
|
|
{
|
2009-04-15 09:42:12 +02:00
|
|
|
// Forward event to sub-module.
|
2009-04-13 20:33:13 +02:00
|
|
|
RestrictOnClientDisconnect(client);
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
WeaponsCreateWeaponArray(&Handle:arrayWeapons, maxlen = WEAPONS_MAX_LENGTH)
|
|
|
|
{
|
2009-04-14 22:05:20 +02:00
|
|
|
// Initialize array handle.
|
2009-04-12 08:04:00 +02:00
|
|
|
arrayWeapons = CreateArray(maxlen);
|
|
|
|
new count = 0;
|
|
|
|
|
2009-04-14 22:05:20 +02:00
|
|
|
// Reset keyvalue's traveral stack.
|
2009-04-12 08:04:00 +02:00
|
|
|
KvRewind(kvWeapons);
|
|
|
|
if (KvGotoFirstSubKey(kvWeapons))
|
|
|
|
{
|
|
|
|
decl String:weapon[maxlen];
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
KvGetSectionName(kvWeapons, weapon, maxlen);
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// Push weapon name into the array.
|
2009-04-12 08:04:00 +02:00
|
|
|
PushArrayString(arrayWeapons, weapon);
|
2009-04-14 22:05:20 +02:00
|
|
|
|
|
|
|
// Increment count.
|
2009-04-12 08:04:00 +02:00
|
|
|
count++;
|
|
|
|
} while (KvGotoNextKey(kvWeapons));
|
|
|
|
}
|
|
|
|
|
2009-04-14 22:05:20 +02:00
|
|
|
// Return the count
|
2009-04-12 08:04:00 +02:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-04-15 09:42:12 +02:00
|
|
|
* Checks if a weapon is valid. (aka listed in weapons.txt)
|
2009-04-13 20:33:13 +02:00
|
|
|
* @param weapon The weapon name.
|
|
|
|
* @return Returns true if valid, false it not.
|
2009-04-12 08:04:00 +02:00
|
|
|
*/
|
2009-04-13 20:33:13 +02:00
|
|
|
bool:WeaponsIsValidWeapon(const String:weapon[])
|
2009-04-12 08:04:00 +02:00
|
|
|
{
|
2009-04-15 09:42:12 +02:00
|
|
|
// Reset keyvalue's traversal stack.
|
2009-04-13 20:33:13 +02:00
|
|
|
KvRewind(kvWeapons);
|
|
|
|
if (KvGotoFirstSubKey(kvWeapons))
|
2009-04-12 08:04:00 +02:00
|
|
|
{
|
2009-04-13 20:33:13 +02:00
|
|
|
decl String:validweapon[WEAPONS_MAX_LENGTH];
|
2009-04-12 08:04:00 +02:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
2009-04-13 20:33:13 +02:00
|
|
|
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
|
2009-04-12 08:04:00 +02:00
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// If weaponname matches a valid weapon, then return true.
|
2009-04-13 20:33:13 +02:00
|
|
|
if (StrEqual(validweapon, weapon, false))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (KvGotoNextKey(kvWeapons));
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// Weapon is invalid.
|
2009-04-13 20:33:13 +02:00
|
|
|
return false;
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-04-15 09:42:12 +02:00
|
|
|
* Looks up a weapon in weapons.txt and returns exact display name.
|
2009-04-12 08:04:00 +02:00
|
|
|
* @param weapon The weapon name.
|
2009-04-13 20:33:13 +02:00
|
|
|
* @param display Returns with the display name, is not changed if weapon is invalid.
|
2009-04-12 08:04:00 +02:00
|
|
|
*/
|
2009-04-13 20:33:13 +02:00
|
|
|
WeaponGetDisplayName(const String:weapon[], String:display[])
|
2009-04-12 08:04:00 +02:00
|
|
|
{
|
2009-04-15 09:42:12 +02:00
|
|
|
// Reset keyvalue's traversal stack.
|
2009-04-13 20:33:13 +02:00
|
|
|
KvRewind(kvWeapons);
|
|
|
|
if (KvGotoFirstSubKey(kvWeapons))
|
|
|
|
{
|
|
|
|
decl String:validweapon[WEAPONS_MAX_LENGTH];
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
|
|
|
|
|
2009-04-15 09:42:12 +02:00
|
|
|
// If weapon matches a valid weapon (case-insensitive), then return display name.
|
2009-04-13 20:33:13 +02:00
|
|
|
if (StrEqual(validweapon, weapon, false))
|
|
|
|
{
|
|
|
|
strcopy(display, WEAPONS_MAX_LENGTH, validweapon);
|
|
|
|
}
|
|
|
|
|
|
|
|
} while (KvGotoNextKey(kvWeapons));
|
|
|
|
}
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
bool:WeaponsIsWeaponMenu(const String:weapon[])
|
|
|
|
{
|
2009-04-14 22:05:20 +02:00
|
|
|
// Reset keyvalue's traversal stack.
|
2009-04-13 20:33:13 +02:00
|
|
|
KvRewind(kvWeapons);
|
|
|
|
if (KvGotoFirstSubKey(kvWeapons))
|
|
|
|
{
|
|
|
|
decl String:validweapon[WEAPONS_MAX_LENGTH];
|
|
|
|
decl String:menu[8];
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
KvGetSectionName(kvWeapons, validweapon, sizeof(validweapon));
|
|
|
|
|
2009-04-14 22:05:20 +02:00
|
|
|
// If this is the right weapon, then return setting for it.
|
2009-04-13 20:33:13 +02:00
|
|
|
if (StrEqual(validweapon, weapon, false))
|
|
|
|
{
|
2009-04-14 01:29:24 +02:00
|
|
|
KvGetString(kvWeapons, "menu", menu, sizeof(menu), "yes");
|
2009-04-13 20:33:13 +02:00
|
|
|
|
2009-04-14 22:05:20 +02:00
|
|
|
// Return weapon's setting.
|
2009-04-17 12:16:44 +02:00
|
|
|
return ZRConfigSettingToBool(menu);
|
2009-04-13 20:33:13 +02:00
|
|
|
}
|
|
|
|
} while (KvGotoNextKey(kvWeapons));
|
|
|
|
}
|
2009-04-12 08:04:00 +02:00
|
|
|
|
2009-04-13 20:33:13 +02:00
|
|
|
return false;
|
2009-04-14 22:05:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-04-15 09:42:12 +02:00
|
|
|
* Returns knockback multiplier of the weapon.
|
2009-04-14 22:05:20 +02:00
|
|
|
* @param weapon The weapon name.
|
|
|
|
* @return The float value of the knockback multiplier, 1.0 if not found.
|
|
|
|
*/
|
|
|
|
Float:WeaponGetWeaponKnockback(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 this is the right weapon, then return setting for it.
|
|
|
|
if (StrEqual(validweapon, weapon, false))
|
|
|
|
{
|
|
|
|
return KvGetFloat(kvWeapons, "knockback", 1.0);
|
|
|
|
}
|
|
|
|
} while (KvGotoNextKey(kvWeapons));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1.0;
|
2009-04-20 05:43:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* General weapon API.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return an array that contains all client's weapon indexes.
|
|
|
|
*
|
|
|
|
* @param client The client index.
|
|
|
|
* @param weapons The weapon index array.
|
|
|
|
* -1 if no weapon in slot.
|
|
|
|
*/
|
|
|
|
WeaponsGetClientWeapons(client, weapons[WeaponsType])
|
|
|
|
{
|
|
|
|
// x = weapon slot.
|
|
|
|
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
|
|
|
|
{
|
|
|
|
weapons[x] = GetPlayerWeaponSlot(client, x);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns weapon index of the client's deployed weapon.
|
|
|
|
*
|
|
|
|
* @param client The client index.
|
|
|
|
* @return The weapon index of the deployed weapon.
|
|
|
|
* -1 if no weapon is deployed.
|
|
|
|
*/
|
|
|
|
WeaponsGetDeployedWeaponIndex(client)
|
|
|
|
{
|
|
|
|
// Return the client's active weapon.
|
|
|
|
return GetEntDataEnt2(client, offsActiveWeapon);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns slot of client's deployed weapon.
|
|
|
|
*
|
|
|
|
* @param client The client index.
|
|
|
|
* @return The slot number of deployed weapon.
|
|
|
|
*/
|
|
|
|
WeaponsType:WeaponsGetDeployedWeaponSlot(client)
|
|
|
|
{
|
|
|
|
// Get all client's weapon indexes.
|
|
|
|
new weapons[WeaponsType];
|
|
|
|
WeaponsGetClientWeapons(client, weapons);
|
|
|
|
|
|
|
|
// Get client's deployed weapon.
|
|
|
|
new deployedweapon = WeaponsGetDeployedWeaponIndex(client);
|
|
|
|
|
|
|
|
// If client has no deployed weapon, then stop.
|
|
|
|
if (deployedweapon == -1)
|
|
|
|
{
|
|
|
|
return Type_Invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
// x = weapon slot.
|
|
|
|
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
|
|
|
|
{
|
|
|
|
if (weapons[x] == deployedweapon)
|
|
|
|
{
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Type_Invalid;
|
2009-04-12 08:04:00 +02:00
|
|
|
}
|